pax_global_header00006660000000000000000000000064134306362740014522gustar00rootroot0000000000000052 comment=030814506e529ef1f1572c7b6e3fc2e4c10cb544 libnfs-libnfs-4.0.0/000077500000000000000000000000001343063627400142535ustar00rootroot00000000000000libnfs-libnfs-4.0.0/.gitignore000066400000000000000000000006461343063627400162510ustar00rootroot00000000000000.* *.h *.c *.in *.la *.a *.lo *.o *.obj *.lib *.dll *.ilk *.pdb *.ex? *-stamp libnfs-raw-*.x Makefile examples/nfsclient-raw examples/nfsclient-sync examples/nfsclient-async examples/nfsclient-bcast examples/nfsclient-listservers aclocal.m4 autom4te.cache/ compile config.guess config.h.in~ config.log config.status config.sub configure depcomp install-sh libtool ltmain.sh missing stamp-h1 libnfs.pc !libnfs.pc.in build libnfs-libnfs-4.0.0/CHANGELOG000066400000000000000000000041771343063627400154760ustar00rootroot00000000000000Changes since 3.0.0 Fix the versioning in makerpms.sh Fix some compile issues in the test programs. NFSv3: skip commit on close if the file has not been written to. Add nfs_umount() to NFSv3 Add nfs_statvfs64() Fix invalid shift of pid_t when generating rpc->xid Compile fixes for Mac OSX Fix for dup2() on Windows NFSv4 fix for directory handling Improvements to configure/bulding Changes since 2.0.0 NFSv4 support. lockf() support (NFSv4 only). fcntl() support for locking (NFSv4 only). Add CMake support. URL arguments to select NFS version. URL argument to set nfsport. This allows NFSv4 to work for servers without portmapper support. URL argument to set he mount port. NFSv4: use getpwnam to map NFSv4 (Ganesha) when passing uid/gid as a user/group name insead of as a uid/gid. Added nfs-fh: a simle utility to print the filehandle for a nfs file. Win32 build fixes. Add a new open2() function that takes a mode argument. Add a testsuite for libnfs. Changes since 1.11.0 BUGS ==== Fix NULL pointer crash in nfs_link(). Clamp read/write size for servers (Ganesha) that offer very large io sizes instead of failing to connect to the export. Tell the server to commit all data to stable storage when we close files. Double free fix: don't call rpc_free_pdu() after rpc_queue_pdu() failure. Fix for memory leak in rpc_allocate_*(). Fixes to build nfs-ls and nfs-cp on win32. Abort the mount process correctly if MOUNT/MNT returns error or is cancelled. Fix memory leak in error path in nfs_create_2_cb(). Fix leak of rpc->inbuf if we destroy the context while we still have PDUs in flight. FEATURES ======== Add O_NOFOLLOW support for nfs_open() Add a new mkdir2 command that also takes a mode argument. Add a new readlink2 command that avoids having to preallocate the buffer. Add support for RPC timeouts for both the sync and async interfaces. Build fixes for Mingw and Cygwin Update README to document two new Windows builds Use SOCK_CLOEXEC for the sockets Make rpc_set{g|u}id() public Performance optimization: socket: Batch pdu read in rpc_read_from_socket Low level support for NFSv4 and some examples Support for building RPC servers libnfs-libnfs-4.0.0/CMakeLists.txt000066400000000000000000000057771343063627400170330ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.2) project(libnfs LANGUAGES C VERSION 2.0.0) set(SOVERSION 11.0.0 CACHE STRING "" FORCE) set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_PREFIX}/lib/cmake/libnfs" CACHE PATH "Installation directory for cmake (.cmake) files") option(BUILD_SHARED_LIBS "Build shared libraries" ON) option(ENABLE_TESTS "Build and run test programs" OFF) option(ENABLE_DOCUMENTATION "Build Documentation" OFF) option(ENABLE_UTILS "Build util programs" OFF) option(ENABLE_EXAMPLES "Build example programs" OFF) if(ENABLE_TESTS) set(ENABLE_UTILS ON CACHE BOOL "Building utils required by tests" FORCE) endif() include(cmake/Macros.cmake) include(cmake/ConfigureChecks.cmake) include_directories(${CMAKE_CURRENT_BINARY_DIR} include include/nfsc) set(CORE_LIBRARIES nfs) set(core_DEPENDS "" CACHE STRING "" FORCE) if(CMAKE_SYSTEM_NAME STREQUAL Windows) list(APPEND CORE_LIBRARIES -lws2_32.lib) add_subdirectory(win32) elseif(CMAKE_SYSTEM_NAME STREQUAL Solaris) find_library(SOCKET_LIBRARY socket) find_library(NSL_LIBRARY nsl) list(APPEND CORE_LIBRARIES ${SOCKET_LIBRARY} ${NSL_LIBRARY}) elseif(CMAKE_SYSTEM_NAME STREQUAL aros) add_definitions(-DAROS) add_subdirectory(aros) endif() if(ENABLE_DOCUMENTATION) add_subdirectory(doc) endif() if(ENABLE_EXAMPLES) add_subdirectory(examples) endif() if(ENABLE_TESTS) enable_testing() add_subdirectory(tests) endif() if(ENABLE_UTILS) add_subdirectory(utils) endif() add_subdirectory(mount) add_subdirectory(nfs) add_subdirectory(nfs4) add_subdirectory(nlm) add_subdirectory(nsm) add_subdirectory(portmap) add_subdirectory(rquota) add_subdirectory(lib) include(CMakePackageConfigHelpers) write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/libnfs-config-version.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion) configure_file(cmake/libnfs.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libnfs.pc @ONLY) install(DIRECTORY include/nfsc DESTINATION ${INSTALL_INC_DIR}) install(FILES mount/libnfs-raw-mount.h nfs/libnfs-raw-nfs.h nlm/libnfs-raw-nlm.h nsm/libnfs-raw-nsm.h portmap/libnfs-raw-portmap.h rquota/libnfs-raw-rquota.h DESTINATION ${INSTALL_INC_DIR}/nfsc) install(FILES cmake/FindNFS.cmake ${CMAKE_CURRENT_BINARY_DIR}/libnfs-config-version.cmake DESTINATION ${INSTALL_CMAKE_DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfs.pc DESTINATION ${INSTALL_PKGCONFIG_DIR}) libnfs-libnfs-4.0.0/COPYING000066400000000000000000000031011343063627400153010ustar00rootroot00000000000000Libnfs components fall under two separate licences The library sources and include directories =========================================== The nfs client library itself, i.e. the lib and include directories, is licenced under 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. The protocol definition, .x, files ================================== These are based on old RFCs and studying how wireshark dissects various packets. These are distributed under the simplified BSD licence. The files generated from the .x files ===================================== The files that are generated from the .x sources, i.e. */libnfs-raw-.[ch] can be considered to be distributed under the simplified BSD licence. These files are only provided as a convenience, so that you do not need to install and run rpcgen on the *.x files locally. If you disagree with the simplified BSD licence I provide them under then just delete them and then generate identical copies of these files yourself using "make compile_rpc" in each protocol subdirectory. Then you can pick whatever licence you want on those files. The examples directory ================================ The utility and example applications using this library, i.e. the examples directory, are licenced under the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. To avoid any confusion, every source file contains a licence boilerplate. libnfs-libnfs-4.0.0/LICENCE-BSD.txt000066400000000000000000000026611343063627400164710ustar00rootroot00000000000000Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. libnfs-libnfs-4.0.0/LICENCE-GPL-3.txt000066400000000000000000001045131343063627400166420ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . libnfs-libnfs-4.0.0/LICENCE-LGPL-2.1.txt000066400000000000000000000636421343063627400171230ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. 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. 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. 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. 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. 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. 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. 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. 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 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. Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libnfs-libnfs-4.0.0/Makefile.am000066400000000000000000000004711343063627400163110ustar00rootroot00000000000000SUBDIRS = doc mount nfs nfs4 nlm nsm portmap rquota lib include $(MAYBE_UTILS) . $(MAYBE_EXAMPLES) ACLOCAL_AMFLAGS = -I m4 pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libnfs.pc EXTRA_DIST = \ README \ COPYING \ LICENCE-BSD.txt \ LICENCE-GPL-3.txt \ LICENCE-LGPL-2.1.txt \ examples \ libnfs.pc.in libnfs-libnfs-4.0.0/README000066400000000000000000000163461343063627400151450ustar00rootroot00000000000000LIBNFS is a client library for accessing NFS shares over a network. LIBNFS offers three different APIs, for different use : 1, RAW : A fully async low level RPC library for NFS protocols This API is described in include/libnfs-raw.h it offers a fully async interface to raw XDR encoded blobs. This API provides very flexible and precise control of the RPC issued. examples/nfsclient-raw.c provides examples on how to use the raw API 2, NFS ASYNC : A fully asynchronous library for high level vfs functions This API is described by the *_async() functions in include/libnfs.h. This API provides a fully async access to posix vfs like functions such as stat(), read(), ... examples/nfsclient-async.c provides examples on how to use this API 3, NFS SYNC : A synchronous library for high level vfs functions This API is described by the *_sync() functions in include/libnfs.h. This API provides access to posix vfs like functions such as stat(), read(), ... examples/nfsclient-sync.c provides examples on how to use this API NFSv4: ====== NFSv3 is the default but NFSv4 can be selected either by using the URL argument version=4 or programatically calling nfs_set_version(nfs, NFS_V4) before connecting to the server/share. SERVER SUPPORT: =============== Libnfs supports building RPC servers. Examples/portmapper-server.c is a small "portmapper" example written using libnfs. URL-FORMAT: =========== Libnfs uses RFC2224 style URLs extended with some minor libnfs extensions. The basic syntax of these URLs is : nfs:///path[?arg=val[&arg=val]*] Arguments supported by libnfs are : tcp-syncnt= : Number of SYNs to send during the session establish before failing setting up the tcp connection to the server. uid= : UID value to use when talking to the server. default it 65534 on Windows and getuid() on unixen. gid= : GID value to use when talking to the server. default it 65534 on Windows and getgid() on unixen. readahead= : Enable readahead for files and set the maximum amount of readahead to bytes. auto-traverse-mounts=<0|1> : Should libnfs try to traverse across nested mounts automatically or not. Default is 1 == enabled. dircache=<0|1> : Disable/enable directory caching. Enabled by default. autoreconnect=<-1|0|>=1> : Control the auto-reconnect behaviour to the NFS session. -1 : Try to reconnect forever on session failures. Just like normal NFS clients do. 0 : Disable auto-reconnect completely and immediately return a failure to the application. >=1 : Retry to connect back to the server this many times before failing and returing an error back to the application. if= : Interface name (e.g., eth1) to bind; requires `root` version=<3|4> : NFS Version. Default is 3. nfsport= : Use this port for NFS instead of using the portmapper. mountport= : Use this port for the MOUNT protocol instead of using portmapper. This argument is ignored for NFSv4 as it does not use the MOUNT protocol. Auto_traverse_mounts ==================== Normally in NFSv3 if a server has nested exports, for example if it would export both /data and /data/tmp then a client would need to mount both these exports as well. The reason is because the NFSv3 protocol does not allow a client request to return data for an object in a different filesystem/mount. (legacy, but it is what it is. One reason for this restriction is to guarantee that inodes are unique across the mounted system.) This option, when enabled, will make libnfs perform all these mounts internally for you. This means that one libnfs mount may now have files with duplicate inode values so if you cache files based on inode make sure you cache files based on BOTH st.st_ino and st.st_dev. ROOT vs NON-ROOT ================ When running as root, libnfs tries to allocate a system port for its connection to the NFS server. When running as non-root it will use a normal ephemeral port. Many NFS servers default to a mode where they do not allow non-system ports from connecting. These servers require you use the "insecure" export option in /etc/exports in order to allow libnfs clients to be able to connect. On Linux we can get around this restriction by setting the NET_BIND_SERVICE capability for the application binary. This is set up by running sudo setcap 'cap_net_bind_service=+ep' /path/to/executable This capability allows the binary to use systems ports like this even when not running as root. Thus if you set this capability for your application you no longer need to edit the export on the NFS server to set "insecure". I do not know what equivalent "capability" support is available on other platforms. Please drop me an email if your os of choice has something similar and I can add it to the README. DOCUMENTATION ============= libnfs sources ship with prebuilt manpage(s) in the doc directory. If you change the manpage sources you need to manually regenerate the new manpages by running cd doc make doc PLATFORM support ================= This is a truly multiplatform library. Linux: - tested with Ubuntu 10.04 - should work with others as well Cygwin: - tested under 64bit win2k8. MacOSX: - tested with SDK 10.4 (under Snow Leopard) - should also work with later SDKs and 64Bit iOS: - tested with iOS SDK 4.2 - running on iOS 4.3.x FreeBSD:- tested with 8.2 Solaris Windows:- tested on Windows 7 64 and Windows XP 32 using Visual Studio 10 (see README.win32.txt for build instructions) - tested on Windows 7 64 using MingW on Linux to cross-compile (Debian and Ubuntu tested) Android:- tested with NDK r10e - running on Android 4.4 (should work starting from 2.3.3) AROS: - Build with 'make -f aros/Makefile.AROS' LD_PRELOAD ========== examples/ld_nfs.c contains a LD_PRELOADable module that can be used to make several standard utilities nfs aware. It is still very incomplete but can be used for basic things such as cat and cp. Patches to add more coverage is welcome. Compile with : gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs Then try things like LD_NFS_DEBUG=9 LD_PRELOAD=./ld_nfs.so cat nfs://127.0.0.1/data/tmp/foo123 LD_NFS_DEBUG=9 LD_PRELOAD=./ld_nfs.so cp nfs://127.0.0.1/data/tmp/foo123 nfs://127.0.0.1/data/tmp/foo123.copy LD_NFS_UID and LD_NFS_GID can be used to fake the uid andthe gid in the nfs context. This can be useful on "insecure" enabled NFS share to make the server trust you as a root. You can try to run as a normal user things like : LD_NFS_DEBUG=9 LD_NFS_UID=0 LD_NFS_GID=0 LD_PRELOAD=./ld_nfs.so chown root:root nfs://127.0.0.1/data/tmp/foo123 This is just a toy preload module. Don't open bugs if it does not work. Send patches to make it better instead. RELEASE TARBALLS ================ Release tarballs are available at https://sites.google.com/site/libnfstarballs/li MAILING LIST ============ A libnfs mailing list is available at http://groups.google.com/group/libnfs Announcements of new versions of libnfs will be posted to this list. libnfs-libnfs-4.0.0/aros/000077500000000000000000000000001343063627400152175ustar00rootroot00000000000000libnfs-libnfs-4.0.0/aros/CMakeLists.txt000066400000000000000000000001161343063627400177550ustar00rootroot00000000000000set(SOURCES aros_compat.c) set(HEADERS aros_compat.h) core_add_library(aros) libnfs-libnfs-4.0.0/aros/Makefile.AROS000077500000000000000000000027371343063627400174360ustar00rootroot00000000000000AR=ar CC=gcc CFLAGS=-g -O0 -DAROS=1 -D_U_=" " -DHAVE_SOCKADDR_LEN -I. -Iinclude -Iinclude/nfsc -Iaros -Infs -Imount OBJS=lib/init.o lib/libnfs.o lib/libnfs-sync.o lib/libnfs-zdr.o lib/pdu.o lib/socket.o OBJS+=mount/mount.o mount/libnfs-raw-mount.o OBJS+=nfs/nfs.o nfs/nfsacl.o nfs/libnfs-raw-nfs.o OBJS+=nlm/nlm.o nlm/libnfs-raw-nlm.o OBJS+=portmap/portmap.o portmap/libnfs-raw-portmap.o OBJS+=rquota/rquota.o rquota/libnfs-raw-rquota.o OBJS+=aros/aros_compat.o EXAMPLES=examples/nfsclient-listservers examples/nfsclient-sync examples/nfs-cp examples/nfs-ls all: lib/libnfs.a $(EXAMPLES) lib/libnfs.a: $(OBJS) $(AR) cru $@ $(OBJS) .c.o: echo $(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $< install: all cp lib/libnfs.a GCC:lib mkdir -p INCLUDE:nfsc cp include/nfsc/libnfs.h INCLUDE:nfsc cp include/nfsc/libnfs-raw.h INCLUDE:nfsc cp include/nfsc/libnfs-zdr.h INCLUDE:nfsc cp mount/libnfs-raw-mount.h INCLUDE:nfsc cp nlm/libnfs-raw-nlm.h INCLUDE:nfsc cp nfs/libnfs-raw-nfs.h INCLUDE:nfsc cp portmap/libnfs-raw-portmap.h INCLUDE:nfsc cp rquota/libnfs-raw-rquota.h INCLUDE:nfsc examples/nfsclient-listservers: examples/nfsclient-listservers.c lib/libnfs.a $(CC) $(CFLAGS) -o $@ $< lib/libnfs.a examples/nfsclient-sync: examples/nfsclient-sync.c lib/libnfs.a $(CC) $(CFLAGS) -o $@ $< lib/libnfs.a examples/nfs-ls: examples/nfs-ls.c lib/libnfs.a $(CC) $(CFLAGS) -o $@ $< lib/libnfs.a examples/nfs-cp: examples/nfs-cp.c lib/libnfs.a $(CC) $(CFLAGS) -o $@ $< lib/libnfs.a libnfs-libnfs-4.0.0/aros/aros_compat.c000066400000000000000000000101231343063627400176670ustar00rootroot00000000000000/* Copyright (C) 2013 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #include #include #include #include #include #include #include #include "aros_compat.h" #include #include #undef poll int aros_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { struct sockaddr_in *sin = (struct sockaddr_in *)sa; if (host) { snprintf(host, hostlen, Inet_NtoA(sin->sin_addr.s_addr)); } return 0; } int aros_getaddrinfo(const char *node, const char*service, const struct addrinfo *hints, struct addrinfo **res) { struct sockaddr_in *sin; sin = malloc(sizeof(struct sockaddr_in)); sin->sin_len = sizeof(struct sockaddr_in); sin->sin_family=AF_INET; /* Some error checking would be nice */ sin->sin_addr.s_addr = inet_addr(node); sin->sin_port=0; if (service) { sin->sin_port=htons(atoi(service)); } *res = malloc(sizeof(struct addrinfo)); (*res)->ai_family = AF_INET; (*res)->ai_addrlen = sizeof(struct sockaddr_in); (*res)->ai_addr = (struct sockaddr *)sin; return 0; } void aros_freeaddrinfo(struct addrinfo *res) { free(res->ai_addr); free(res); } int aros_inet_pton(int af, char *src, void *dst) { struct sockaddr_in sin; sin.sin_addr.s_addr = inet_addr(src); memcpy(dst, &sin.sin_addr.s_addr, sizeof(sin.sin_addr.s_addr)); return 1; } /* unix device numbers dont really make much sense on aros ... */ int major(int i) { return 1; } int minor(int i) { return 2; } struct Library * SocketBase = NULL; extern int errno; int h_errno = 0; void aros_init_socket(void) { if (!(SocketBase = OpenLibrary("bsdsocket.library", 4))) { printf("NoTCP/IP Stack available"); exit(10); } if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (IPTR)&errno, SBTM_SETVAL(SBTC_HERRNOLONGPTR), (IPTR)&h_errno, TAG_DONE)) { printf("Failed to set ERRNO"); exit(10); } } int aros_poll(struct pollfd *fds, unsigned int nfds, int timo) { struct timeval timeout, *toptr; fd_set ifds, ofds, efds, *ip, *op; unsigned int i, maxfd = 0; int rc; // Set up the file-descriptor sets in ifds, ofds and efds. FD_ZERO(&ifds); FD_ZERO(&ofds); FD_ZERO(&efds); for (i = 0, op = ip = 0; i < nfds; ++i) { fds[i].revents = 0; if(fds[i].events & (POLLIN|POLLPRI)) { ip = &ifds; FD_SET(fds[i].fd, ip); } if(fds[i].events & POLLOUT) { op = &ofds; FD_SET(fds[i].fd, op); } FD_SET(fds[i].fd, &efds); if (fds[i].fd > maxfd) { maxfd = fds[i].fd; } } // Set up the timeval structure for the timeout parameter if(timo < 0) { toptr = 0; } else { toptr = &timeout; timeout.tv_sec = timo / 1000; timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000; } rc = WaitSelect(maxfd + 1, ip, op, &efds, toptr, NULL); if(rc <= 0) return rc; if(rc > 0) { for (i = 0; i < nfds; ++i) { int fd = fds[i].fd; if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds)) fds[i].revents |= POLLIN; if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds)) fds[i].revents |= POLLOUT; if(FD_ISSET(fd, &efds)) // Some error was detected ... should be some way to know. fds[i].revents |= POLLHUP; } } return rc; } libnfs-libnfs-4.0.0/aros/aros_compat.h000066400000000000000000000040531343063627400177010ustar00rootroot00000000000000/* Copyright (C) 2013 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifndef AROS_COMPAT_H #define AROS_COMPAT_H #include #include #include #include #include #include #include #include #include #include #define statvfs statfs #define ioctl IoctlSocket #define close CloseSocket #define inet_pton aros_inet_pton #define freeaddrinfo aros_freeaddrinfo #define getnameinfo aros_getnameinfo #define getaddrinfo aros_getaddrinfo extern struct Library * SocketBase; void aros_init_socket(void); #define f_flag f_flags #define f_favail f_ffree /* we dont have these at all */ #define f_fsid f_spare[0] #define f_frsize f_spare[0] #define f_namemax f_spare[0] #define POLLIN 0x0001 /* There is data to read */ #define POLLPRI 0x0002 /* There is urgent data to read */ #define POLLOUT 0x0004 /* Writing now will not block */ #define POLLERR 0x0008 /* Error condition */ #define POLLHUP 0x0010 /* Hung up */ #define POLLNVAL 0x0020 /* Invalid request: fd not open */ struct utimbuf { int actime; int modtime; }; struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ }; #define poll(x, y, z) aros_poll(x, y, z) #endif libnfs-libnfs-4.0.0/bootstrap000077500000000000000000000000421343063627400162120ustar00rootroot00000000000000#!/bin/sh -e exec autoreconf -vif libnfs-libnfs-4.0.0/cmake/000077500000000000000000000000001343063627400153335ustar00rootroot00000000000000libnfs-libnfs-4.0.0/cmake/ConfigureChecks.cmake000066400000000000000000000103551343063627400214030ustar00rootroot00000000000000include(CheckIncludeFile) check_include_file("arpa/inet.h" HAVE_ARPA_INET_H) check_include_file("dlfcn.h" HAVE_DLFCN_H) check_include_file("fuse.h" HAVE_FUSE_H) check_include_file("inttypes.h" HAVE_INTTYPES_H) check_include_file("memory.h" HAVE_MEMORY_H) check_include_file("netdb.h" HAVE_NETDB_H) check_include_file("netinet/in.h" HAVE_NETINET_IN_H) check_include_file("netinet/tcp.h" HAVE_NETINET_TCP_H) check_include_file("net/if.h" HAVE_NET_IF_H) check_include_file("poll.h" HAVE_POLL_H) check_include_file("stdint.h" HAVE_STDINT_H) check_include_file("stdlib.h" HAVE_STDLIB_H) check_include_file("strings.h" HAVE_STRINGS_H) check_include_file("string.h" HAVE_STRING_H) check_include_file("sys/filio.h" HAVE_SYS_FILIO_H) check_include_file("sys/ioctl.h" HAVE_SYS_IOCTL_H) check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H) check_include_file("sys/statvfs.h" HAVE_SYS_STATVFS_H) check_include_file("sys/stat.h" HAVE_SYS_STAT_H) check_include_file("sys/sysmacros.h" HAVE_SYS_SYSMACROS_H) check_include_file("sys/time.h" HAVE_SYS_TIME_H) check_include_file("sys/types.h" HAVE_SYS_TYPES_H) check_include_file("sys/vfs.h" HAVE_SYS_VFS_H) check_include_file("unistd.h" HAVE_UNISTD_H) check_include_file("utime.h" HAVE_UTIME_H) include(CheckStructHasMember) check_struct_has_member("struct sockaddr" sa_len sys/socket.h HAVE_SOCKADDR_LEN) check_struct_has_member("struct sockaddr_storage" ss_family sys/socket.h HAVE_SOCKADDR_STORAGE) check_struct_has_member("struct stat" st_mtim.tv_nsec sys/stat.h HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) include(CheckCSourceCompiles) check_c_source_compiles("#include int main(void) { int i = SO_BINDTODEVICE; }" HAVE_SO_BINDTODEVICE) check_c_source_compiles("#include #include int main(void) { struct tevent_context *ctx = tevent_context_init(NULL); int major = talloc_version_major(); }" HAVE_TALLOC_TEVENT) check_c_source_compiles("#include int main(void) { int i = clock_gettime(CLOCK_MONOTONIC_COARSE, NULL); }" HAVE_CLOCK_GETTIME) check_c_source_compiles("#include #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main() { return 0; }" NO_LFS_REQUIRED) if(NOT NO_LFS_REQUIRED) check_c_source_compiles("#include #define _FILE_OFFSET_BITS 64 #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main() { return 0; }" _FILE_OFFSET_BITS) check_c_source_compiles("#include #define _LARGE_FILES 1 #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main() { return 0; }" _LARGE_FILES) endif() include(CheckSymbolExists) check_symbol_exists("makedev" "sys/mkdev.h" MAJOR_IN_MKDEV) check_symbol_exists("makedev" "sys/sysmacros.h" MAJOR_IN_SYSMACROS) include(CheckCCompilerFlag) if(CMAKE_COMPILER_IS_GNUCC) check_c_compiler_flag(-Wall C_ACCEPTS_WALL) if(C_ACCEPTS_WALL) add_definitions(-Wall) endif() endif() configure_file(cmake/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) add_definitions(-DHAVE_CONFIG_H) libnfs-libnfs-4.0.0/cmake/FindNFS.cmake000066400000000000000000000017121343063627400175650ustar00rootroot00000000000000#.rst: # FindNFS # ------- # Finds the libnfs library # # This will will define the following variables:: # # NFS_FOUND - system has libnfs # NFS_INCLUDE_DIRS - the libnfs include directory # NFS_LIBRARIES - the libnfs libraries # NFS_DEFINITIONS - the libnfs compile definitions # if(PKG_CONFIG_FOUND) pkg_check_modules(PC_NFS libnfs QUIET) endif() find_path(NFS_INCLUDE_DIR nfsc/libnfs.h PATHS ${PC_NFS_INCLUDEDIR}) find_library(NFS_LIBRARY NAMES nfs PATHS ${PC_NFS_LIBDIR}) set(NFS_VERSION ${PC_NFS_VERSION}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NFS REQUIRED_VARS NFS_LIBRARY NFS_INCLUDE_DIR VERSION_VAR NFS_VERSION) if(NFS_FOUND) set(NFS_LIBRARIES ${NFS_LIBRARY}) set(NFS_INCLUDE_DIRS ${NFS_INCLUDE_DIR}) set(NFS_DEFINITIONS -DHAVE_LIBNFS=1) endif() mark_as_advanced(NFS_INCLUDE_DIR NFS_LIBRARY) libnfs-libnfs-4.0.0/cmake/Macros.cmake000066400000000000000000000011021343063627400175530ustar00rootroot00000000000000# Add sources to main application # Arguments: # name name of the library to add # Implicit arguments: # SOURCES the sources of the library # HEADERS the headers of the library (only for IDE support) # On return: # Library will be built and added to ${core_DEPENDS} function(core_add_library name) set(name core_${name}) set(CMAKE_POSITION_INDEPENDENT_CODE ON) add_library(${name} STATIC ${SOURCES} ${HEADERS}) target_include_directories(${name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) set(core_DEPENDS ${name} ${core_DEPENDS} CACHE STRING "" FORCE) endfunction() libnfs-libnfs-4.0.0/cmake/config.h.cmake000066400000000000000000000067461343063627400200450ustar00rootroot00000000000000/* config.h.cmake */ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ARPA_INET_H /* Whether we have clock_gettime */ #cmakedefine HAVE_CLOCK_GETTIME /* Define to 1 if you have the header file. */ #cmakedefine HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_FUSE_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H /* Define to 1 if you have the `nsl' library (-lnsl). */ #cmakedefine HAVE_LIBNSL /* Define to 1 if you have the `socket' library (-lsocket). */ #cmakedefine HAVE_LIBSOCKET /* Define to 1 if you have the header file. */ #cmakedefine HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETDB_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_TCP_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NET_IF_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_POLL_H /* Whether sockaddr struct has sa_len */ #cmakedefine HAVE_SOCKADDR_LEN /* Whether we have sockaddr_Storage */ #cmakedefine HAVE_SOCKADDR_STORAGE /* Whether our sockets support SO_BINDTODEVICE */ #cmakedefine HAVE_SO_BINDTODEVICE /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRING_H /* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ #cmakedefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_FILIO_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SOCKIO_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STATVFS_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SYSMACROS_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_VFS_H /* Whether we have talloc nad tevent support */ #cmakedefine HAVE_TALLOC_TEVENT /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UTIME_H /* Define to 1 if `major', `minor', and `makedev' are declared in . */ #cmakedefine MAJOR_IN_MKDEV /* Define to 1 if `major', `minor', and `makedev' are declared in . */ #cmakedefine MAJOR_IN_SYSMACROS /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #cmakedefine _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #cmakedefine _LARGE_FILES libnfs-libnfs-4.0.0/cmake/libnfs.pc.cmake000066400000000000000000000005201343063627400202100ustar00rootroot00000000000000# libnfs pkg-config file prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@INSTALL_LIB_DIR@ includedir=@INSTALL_INC_DIR@ Name: libnfs Description: libnfs is a client library for accessing NFS shares over a network. Version: @PROJECT_VERSION@ Requires: Conflicts: Libs: -L${libdir} -lnfs Cflags: -I${includedir} libnfs-libnfs-4.0.0/configure.ac000077500000000000000000000160061343063627400165470ustar00rootroot00000000000000AC_PREREQ(2.50) AC_INIT([libnfs], [4.0.0], [ronniesahlberg@gmail.com]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) AC_CANONICAL_HOST AC_CONFIG_MACRO_DIR([m4]) m4_pattern_allow([AM_PROG_AR]) AM_PROG_AR # Work around stupid autoconf default cflags. pt 1 SAVE_CFLAGS="x${CFLAGS}" AC_PROG_CC AC_PROG_LIBTOOL AM_PROG_CC_C_O PKG_PROG_PKG_CONFIG # Work around stupid autoconf default cflags. pt 2 if test "$SAVE_CFLAGS" = "x"; then CFLAGS="" fi # We always want 64 bit file offsets AC_SYS_LARGEFILE #option: utils MAYBE_UTILS="utils" AC_ARG_ENABLE([utils], [AC_HELP_STRING([--enable-utils], [Build util programs])], [if test $enableval = no ; then MAYBE_UTILS="" fi]) AC_SUBST(MAYBE_UTILS) #option: examples AC_ARG_ENABLE([examples], [AC_HELP_STRING([--enable-examples], [Build example programs])], [ENABLE_EXAMPLES=$enableval], [ENABLE_EXAMPLES="no"]) # We need popt to compile the examples if test x$ENABLE_EXAMPLES = xyes; then AC_MSG_CHECKING(whether libpopt is available) ac_save_LIBS="$LIBS" LIBS="$LIBS -lpopt" AC_TRY_LINK([#include ], [ /* * Just see if we can compile/link with popt */ int _argc; char **_argv; struct poptOption popt_options[] = { POPT_TABLEEND }; poptGetContext(_argv[0], _argc, _argv, popt_options, POPT_CONTEXT_KEEP_FIRST); ], ac_cv_have_popt=yes, ac_cv_have_popt=no) LIBS="$ac_save_LIBS" if test "$ac_cv_have_popt" = yes ; then AC_MSG_RESULT(yes) MAYBE_EXAMPLES="examples" else AC_MSG_RESULT(no) AC_MSG_NOTICE(You need libpopt to compile the sample libnfs clients.) AC_MSG_NOTICE(Only the library will be compiled and installed.) fi fi AC_SUBST(MAYBE_EXAMPLES) AC_MSG_CHECKING(whether SO_BINDTODEVICE is available) AC_TRY_COMPILE([#include ], [ int i = SO_BINDTODEVICE; ], ac_cv_have_so_bindtodevice=yes, ac_cv_have_so_bindtodevice=no) if test "$ac_cv_have_so_bindtodevice" = yes ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_SO_BINDTODEVICE, 1, [Whether our sockets support SO_BINDTODEVICE]) else AC_MSG_RESULT(no) AC_MSG_NOTICE(SO_BINDTODEVICE support for if= support is missing.) AC_MSG_NOTICE(Compiling without if= support.) fi AC_MSG_CHECKING(whether getpwnam() is available) AC_TRY_COMPILE([ #include #include ], [ struct passwd *pwd = getpwnam("nobody"); ], ac_cv_have_getpwnam=yes, ac_cv_have_getpwnam=no) if test "$ac_cv_have_getpwnam" = yes ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_GETPWNAM, 1, [Whether we have getpwnam()]) else AC_MSG_RESULT(no) AC_MSG_NOTICE(getpwnam() support is missing.) AC_MSG_NOTICE(Compiling without getpwnam() support.) fi AC_ARG_ENABLE([werror], [AS_HELP_STRING([--disable-werror], [Disables building with -Werror by default])]) if test "$ac_cv_prog_gcc" = yes; then WARN_CFLAGS="-Wall -Wshadow -Wno-write-strings -Wstrict-prototypes -Wpointer-arith -Wcast-align -Wno-strict-aliasing" if test "x$enable_werror" != "xno"; then WARN_CFLAGS="$WARN_CFLAGS -Werror" fi fi AC_SUBST(WARN_CFLAGS) LIBSOCKET= SYS= case $host in *solaris*) AC_CHECK_HEADERS([sys/filio.h]) AC_CHECK_HEADERS([sys/sockio.h]) AC_CHECK_LIB([socket], [main], , [AC_MSG_ERROR([Can not find required library])]) AC_CHECK_LIB([nsl], [main], , [AC_MSG_ERROR([Can not find required library])]) ;; *mingw32* | *wince* | *mingwce*) LIBSOCKET='-lws2_32' SYS=mingw32 ;; *) ;; esac AM_CONDITIONAL(HAVE_WIN32, test "${SYS}" = "mingw32") AC_SUBST([LIBSOCKET]) # check for sys/sysmacros.h dnl Check for sys/sysmacros.h AC_CHECK_HEADERS([sys/sysmacros.h]) # check for poll.h dnl Check for poll.h AC_CHECK_HEADERS([poll.h]) # check for unistd.h dnl Check for unistd.h AC_CHECK_HEADERS([unistd.h]) # check for netdb.h dnl Check for netdb.h AC_CHECK_HEADERS([netdb.h]) # check for utime.h dnl Check for utime.h AC_CHECK_HEADERS([utime.h]) # check for net/if.h dnl Check for net/if.h AC_CHECK_HEADERS([net/if.h]) # check for sys/time.h dnl Check for sys/time.h AC_CHECK_HEADERS([sys/time.h]) # check for sys/ioctl.h dnl Check for sys/ioctl.h AC_CHECK_HEADERS([sys/ioctl.h]) # check for sys/vfs.h dnl Check for sys/vfs.h AC_CHECK_HEADERS([sys/vfs.h]) # check for sys/statvfs.h dnl Check for sys/statvfs.h AC_CHECK_HEADERS([sys/statvfs.h]) # check for fuse.h dnl Check for fuse.h AC_CHECK_HEADERS([fuse.h]) # check for sys/socket.h dnl Check for sys/socket.h AC_CHECK_HEADERS([sys/socket.h]) # check for netinet/tcp.h dnl Check for netinet/tcp.h AC_CHECK_HEADERS([netinet/tcp.h]) # check for netinet/in.h dnl Check for netinet/in.h AC_CHECK_HEADERS([netinet/in.h]) # check for arpa/inet.h dnl Check for arpa/inet.h AC_CHECK_HEADERS([arpa/inet.h]) # check for SA_LEN dnl Check if sockaddr data structure includes a "sa_len" AC_CHECK_MEMBER([struct sockaddr.sa_len], [ AC_DEFINE(HAVE_SOCKADDR_LEN,1,[Whether sockaddr struct has sa_len]) ], [], [ #include #include ]) # check for sockaddr_storage dnl Check if sockaddr structure includes a "ss_family" AC_CHECK_MEMBER([struct sockaddr_storage.ss_family], [ AC_DEFINE(HAVE_SOCKADDR_STORAGE,1,[Whether we have sockaddr_Storage]) ], [], [ #include #include ]) # check for clock_gettime(CLOCK_MONOTONIC_COARSE) AC_MSG_CHECKING(if clock_gettime(CLOCK_MONOTONIC_COARSE) is available) AC_TRY_COMPILE([#include ], [ int i = clock_gettime(CLOCK_MONOTONIC_COARSE, NULL); ], ac_cv_have_clock_gettime=yes, ac_cv_have_clock_gettime=no) if test "$ac_cv_have_clock_gettime" = yes ; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Whether we have clock_gettime]) else AC_MSG_RESULT(no) AC_MSG_NOTICE(clock_gettime(CLOCK_MONOTONIC_COARSE) support is missing.) AC_MSG_NOTICE(Compiling without clock_gettime support..) fi # check for tevent + talloc AC_CACHE_CHECK([for talloc and tevent support],libnfs_cv_HAVE_TALLOC_TEVENT,[ AC_TRY_COMPILE([ #include #include ], [struct tevent_context *ctx = tevent_context_init(NULL); int major = talloc_version_major();], libiscsi_cv_HAVE_TALLOC_TEVENT=yes,libiscsi_cv_HAVE_TALLOC_TEVENT=no)]) if test x"$libiscsi_cv_HAVE_TALLOC_TEVENT" = x"yes"; then AC_DEFINE(HAVE_TALLOC_TEVENT,1,[Whether we have talloc nad tevent support]) fi AM_CONDITIONAL([HAVE_TALLOC_TEVENT], [test $libiscsi_cv_HAVE_TALLOC_TEVENT = yes]) AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec]) # check where makedev is defined AC_HEADER_MAJOR #output AC_CONFIG_FILES([Makefile] [doc/Makefile] [examples/Makefile] [include/Makefile] [lib/Makefile] [mount/Makefile] [nfs/Makefile] [nfs4/Makefile] [nlm/Makefile] [nsm/Makefile] [portmap/Makefile] [rquota/Makefile] [tests/Makefile] [utils/Makefile] ) AC_OUTPUT([libnfs.pc]) libnfs-libnfs-4.0.0/doc/000077500000000000000000000000001343063627400150205ustar00rootroot00000000000000libnfs-libnfs-4.0.0/doc/CMakeLists.txt000066400000000000000000000011431343063627400175570ustar00rootroot00000000000000find_program(XSLTPROC_PROGRAM xsltproc) set(MANPAGES nfs-cat.1 nfs-cp.1 nfs-ls.1) set(DOCKBOOK_URL http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl) if(XSLTPROC_PROGRAM) foreach(TARGET ${MANPAGES}) file(COPY ${TARGET}.xml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) add_custom_command(OUTPUT ${TARGET} COMMAND ${XSLTPROC_PROGRAM} -o ${TARGET} ${DOCKBOOK_URL} ${TARGET}.xml) endforeach() add_custom_target(doc ALL DEPENDS ${MANPAGES}) endif() install(FILES ${MANPAGES} DESTINATION ${INSTALL_MAN_DIR}/man1/) libnfs-libnfs-4.0.0/doc/Makefile.am000066400000000000000000000011031343063627400170470ustar00rootroot00000000000000XSLTPROC = /usr/bin/xsltproc EXTRA_DIST = nfs-cat.1 nfs-cat.1.xml nfs-cp.1 nfs-cp.1.xml nfs-ls.1 nfs-ls.1.xml # Manpages man1_MANS = nfs-cat.1 nfs-cp.1 nfs-ls.1 doc: -test -z "$(XSLTPROC)" || $(XSLTPROC) -o nfs-cat.1 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl nfs-cat.1.xml -test -z "$(XSLTPROC)" || $(XSLTPROC) -o nfs-cp.1 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl nfs-cp.1.xml -test -z "$(XSLTPROC)" || $(XSLTPROC) -o nfs-ls.1 http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl nfs-ls.1.xml libnfs-libnfs-4.0.0/doc/nfs-cat.1000066400000000000000000000032421343063627400164360ustar00rootroot00000000000000'\" t .\" Title: nfs-cat .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 05/24/2015 .\" Manual: nfs-cat: read a file from nfs .\" Source: nfs-cat .\" Language: English .\" .TH "NFS\-CAT" "1" "05/24/2015" "nfs\-cat" "nfs\-cat: read a file from nfs" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nfs-cat \- Utility to read a file off NFS .SH "SYNOPSIS" .HP \w'\fBnfs\-cat\ \fR\ 'u \fBnfs\-cat \fR .SH "DESCRIPTION" .PP nfs\-cat is a utility to read a file off an NFS server\&. .PP Example: Print the content of a file: .sp .if n \{\ .RS 4 .\} .nf $ nfs\-cat nfs://127\&.0\&.0\&.1/data/tmp/foo\&.c .fi .if n \{\ .RE .\} .sp .SH "SEE ALSO" .PP \m[blue]\fB\%http://github.com/sahlberg/libnfs\fR\m[] libnfs-libnfs-4.0.0/doc/nfs-cat.1.xml000066400000000000000000000016761343063627400172460ustar00rootroot00000000000000 nfs-cat 1 nfs-cat nfs-cat: read a file from nfs nfs-cat Utility to read a file off NFS nfs-cat <NFS-URL> DESCRIPTION nfs-cat is a utility to read a file off an NFS server. Example: Print the content of a file: $ nfs-cat nfs://127.0.0.1/data/tmp/foo.c SEE ALSO libnfs-libnfs-4.0.0/doc/nfs-cp.1000066400000000000000000000035011343063627400162670ustar00rootroot00000000000000'\" t .\" Title: nfs-cp .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 05/24/2015 .\" Manual: nfs-cp: copy files to/from an NFS share .\" Source: nfs-cp .\" Language: English .\" .TH "NFS\-CP" "1" "05/24/2015" "nfs\-cp" "nfs\-cp: copy files to/from an" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nfs-cp \- Utility to copy files to/from and NFS server .SH "SYNOPSIS" .HP \w'\fBnfs\-cp\ \ \fR\ 'u \fBnfs\-cp \fR .SH "DESCRIPTION" .PP nfs\-cp is a utility to copy files to/from and NFS server\&. .PP Examples: .sp .if n \{\ .RS 4 .\} .nf $ nfs\-cp foo\&.c nfs://127\&.0\&.0\&.1/data/tmp/foo\&.c $ nfs\-cp nfs://127\&.0\&.0\&.1/data/tmp/foo\&.c bob\&.c $ nfs\-cp nfs://127\&.0\&.0\&.1/data/tmp/foo\&.c nfs://127\&.0\&.0\&.1/data/tmp/copy\-of\-foo\&.c .fi .if n \{\ .RE .\} .sp .SH "SEE ALSO" .PP \m[blue]\fB\%http://github.com/sahlberg/libnfs\fR\m[] libnfs-libnfs-4.0.0/doc/nfs-cp.1.xml000066400000000000000000000021041343063627400170640ustar00rootroot00000000000000 nfs-cp 1 nfs-cp nfs-cp: copy files to/from an NFS share nfs-cp Utility to copy files to/from and NFS server nfs-cp <src> <dst> DESCRIPTION nfs-cp is a utility to copy files to/from and NFS server. Examples: $ nfs-cp foo.c nfs://127.0.0.1/data/tmp/foo.c $ nfs-cp nfs://127.0.0.1/data/tmp/foo.c bob.c $ nfs-cp nfs://127.0.0.1/data/tmp/foo.c nfs://127.0.0.1/data/tmp/copy-of-foo.c SEE ALSO libnfs-libnfs-4.0.0/doc/nfs-ls.1000066400000000000000000000060031343063627400163030ustar00rootroot00000000000000'\" t .\" Title: nfs-ls .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 05/24/2015 .\" Manual: nfs-ls: list servers, exports and directories .\" Source: nfs-ls .\" Language: English .\" .TH "NFS\-LS" "1" "05/24/2015" "nfs\-ls" "nfs\-ls: list servers, exports" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nfs-ls \- Utility to list NFS servers, exports and directories .SH "SYNOPSIS" .HP \w'\fBnfs\-ls\ [\ OPTIONS\ ]\ \fR\ 'u \fBnfs\-ls [ OPTIONS ] \fR .HP \w'\fBnfs\-ls\fR\ 'u \fBnfs\-ls\fR [\-R\ \-\-recursive] [\-s\ \-\-summary] [\-D\ \-\-discovery] [\-?\ \-\-help] [\-\-usage] .SH "DESCRIPTION" .PP nfs\-ls is a utility to list NFS servers, exports or directories\&. .PP Example: List the content of a directory on the NFS server .sp .if n \{\ .RS 4 .\} .nf $ nfs\-ls nfs://127\&.0\&.0\&.1/data/tmp \-rwxrwxr\-x 1 1000 1000 1190802 a\&.out \-rwxr\-xr\-x 1 1000 1000 13 foo123\&.copy \-rwxrwxrwx 1 1000 1000 8 foo123\&.writtenx .fi .if n \{\ .RE .\} .sp .SH "OPTIONS" .PP \-s \-\-summary .RS 4 Print a summary line at the end of output\&. .RE .PP \-R \-\-recursive .RS 4 Recursive listing of the specified URL\&. .RE .PP \-D \-\-discovery; .RS 4 This option is used to discover local NFS servers and to list the exports for specific servers\&. .sp When used with the \*(Aqnfs://\*(Aq URL the command will try to detect all local NFS servers and will list their IPs\&. .sp When used with a \*(Aqnfs://server\*(Aq the command will list all the exports on the specified server\&. .sp Example: Discover and list all local NFS servers .sp .if n \{\ .RS 4 .\} .nf $ nfs\-ls \-D nfs:// nfs://10\&.10\&.10\&.10 nfs://10\&.0\&.0\&.10 .fi .if n \{\ .RE .\} .sp Example: List the exports for a server .sp .if n \{\ .RS 4 .\} .nf $ nfs\-ls \-D nfs://10\&.10\&.10\&.10 nfs://10\&.10\&.10\&.10/foo nfs://10\&.10\&.10\&.10/bar .fi .if n \{\ .RE .\} .sp .RE .PP \-? \-\-help .RS 4 Display basic help text\&. .RE .PP \-\-usage .RS 4 Display basic usage text\&. .RE .SH "SEE ALSO" .PP \m[blue]\fB\%http://github.com/sahlberg/libnfs\fR\m[] libnfs-libnfs-4.0.0/doc/nfs-ls.1.xml000066400000000000000000000060611343063627400171060ustar00rootroot00000000000000 nfs-ls 1 nfs-ls nfs-ls: list servers, exports and directories nfs-ls Utility to list NFS servers, exports and directories nfs-ls [ OPTIONS ] <NFS-URL> nfs-ls -R --recursive -s --summary -D --discovery -? --help --usage DESCRIPTION nfs-ls is a utility to list NFS servers, exports or directories. Example: List the content of a directory on the NFS server $ nfs-ls nfs://127.0.0.1/data/tmp -rwxrwxr-x 1 1000 1000 1190802 a.out -rwxr-xr-x 1 1000 1000 13 foo123.copy -rwxrwxrwx 1 1000 1000 8 foo123.writtenx OPTIONS -s --summary Print a summary line at the end of output. -R --recursive Recursive listing of the specified URL. -D --discovery; This option is used to discover local NFS servers and to list the exports for specific servers. When used with the 'nfs://' URL the command will try to detect all local NFS servers and will list their IPs. When used with a 'nfs://server' the command will list all the exports on the specified server. Example: Discover and list all local NFS servers $ nfs-ls -D nfs:// nfs://10.10.10.10 nfs://10.0.0.10 Example: List the exports for a server $ nfs-ls -D nfs://10.10.10.10 nfs://10.10.10.10/foo nfs://10.10.10.10/bar -? --help Display basic help text. --usage Display basic usage text. SEE ALSO libnfs-libnfs-4.0.0/examples/000077500000000000000000000000001343063627400160715ustar00rootroot00000000000000libnfs-libnfs-4.0.0/examples/CMakeLists.txt000066400000000000000000000016041343063627400206320ustar00rootroot00000000000000find_library(TALLOC_LIBRARY talloc) find_library(TALLOC_EVENT_LIBRARY tevent) find_library(EVENT_LIBARY event) find_library(POPT_LIBRARY popt) list(APPEND CORE_LIBRARIES ${POPT_LIBRARY}) set(SOURCES nfsclient-async nfsclient-raw nfsclient-sync nfsclient-bcast nfsclient-listservers nfs-io nfs-ln portmap-client) if(HAVE_TALLOC_TEVENT) list(APPEND SOURCES nfs4-cat-talloc) list(APPEND CORE_LIBRARIES ${TALLOC_EVENT_LIBRARY} ${TALLOC_LIBRARY}) endif() if(EVENT_LIBARY) list(APPEND SOURCES nfs4-cat portmap-server) list(APPEND CORE_LIBRARIES ${EVENT_LIBARY}) endif() foreach(TARGET ${SOURCES}) add_executable(${TARGET} ${TARGET}.c) target_link_libraries(${TARGET} ${CORE_LIBRARIES}) add_dependencies(${TARGET} nfs) endforeach() add_definitions("-D_U_=__attribute__((unused))") libnfs-libnfs-4.0.0/examples/Makefile.am000066400000000000000000000020101343063627400201160ustar00rootroot00000000000000noinst_PROGRAMS = nfsclient-async nfsclient-raw nfsclient-sync nfsclient-bcast nfsclient-listservers nfs-fh nfs-io nfs-ln nfs4-cat portmap-client portmap-server if HAVE_TALLOC_TEVENT noinst_PROGRAMS += nfs4-cat-talloc endif AM_CPPFLAGS = \ -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/include/win32 \ -I$(abs_top_srcdir)/mount \ -I$(abs_top_srcdir)/nfs \ -I$(abs_top_srcdir)/nfs4 \ -I$(abs_top_srcdir)/portmap \ -I$(abs_top_srcdir)/rquota \ "-D_U_=__attribute__((unused))" COMMON_LIBS = ../lib/libnfs.la -lpopt nfsclient_async_LDADD = $(COMMON_LIBS) nfsclient_raw_LDADD = $(COMMON_LIBS) nfsclient_sync_LDADD = $(COMMON_LIBS) nfsclient_bcast_LDADD = $(COMMON_LIBS) nfsclient_listservers_LDADD = $(COMMON_LIBS) nfs_fh_LDADD = $(COMMON_LIBS) nfs_io_LDADD = $(COMMON_LIBS) nfs_ln_LDADD = $(COMMON_LIBS) nfs4_cat_LDADD = $(COMMON_LIBS) -levent nfs4_cat_talloc_LDADD = $(COMMON_LIBS) -ltevent -ltalloc portmap_client_LDADD = $(COMMON_LIBS) portmap_server_LDADD = $(COMMON_LIBS) -levent libnfs-libnfs-4.0.0/examples/ld_nfs.c000066400000000000000000000446101343063627400175070ustar00rootroot00000000000000/* Copyright (C) 2014 by Ronnie Sahlberg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #define NFS_MAX_FD 255 static int debug = 0; static int nfsuid = -1; static int nfsgid = -1; #ifndef discard_const #define discard_const(ptr) ((void *)((intptr_t)(ptr))) #endif #define LD_NFS_DPRINTF(level, fmt, args...) \ do { \ if ((debug) >= level) { \ fprintf(stderr,"ld_nfs: "); \ fprintf(stderr, (fmt), ##args); \ fprintf(stderr,"\n"); \ } \ } while (0); struct nfs_fd_list { int is_nfs; struct nfs_context *nfs; struct nfsfh *fh; /* so we can reopen and emulate dup2() */ const char *path; int flags; mode_t mode; }; static struct nfs_fd_list nfs_fd_list[NFS_MAX_FD]; int (*real_open)(__const char *path, int flags, mode_t mode); int open(const char *path, int flags, mode_t mode) { if (!strncmp(path, "nfs:", 4)) { struct nfs_context *nfs; struct nfs_url *url; struct nfsfh *fh = NULL; int ret, fd; LD_NFS_DPRINTF(9, "open(%s, %x, %o)", path, flags, mode); nfs = nfs_init_context(); if (nfs == NULL) { LD_NFS_DPRINTF(1, "Failed to create context"); errno = ENOMEM; return -1; } if (nfsuid >= 0) nfs_set_uid(nfs, nfsuid); if (nfsgid >= 0) nfs_set_gid(nfs, nfsgid); url = nfs_parse_url_full(nfs, path); if (url == NULL) { LD_NFS_DPRINTF(1, "Failed to parse URL: %s\n", nfs_get_error(nfs)); nfs_destroy_context(nfs); errno = EINVAL; return -1; } if (nfs_mount(nfs, url->server, url->path) != 0) { LD_NFS_DPRINTF(1, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); nfs_destroy_url(url); nfs_destroy_context(nfs); errno = EINVAL; return -1; } if (flags & O_CREAT) { if ((ret = nfs_creat(nfs, url->file, mode, &fh)) != 0) { LD_NFS_DPRINTF(1, "Failed to creat nfs file : " "%s\n", nfs_get_error(nfs)); nfs_destroy_url(url); nfs_destroy_context(nfs); errno = -ret; return -1; } } else { if ((ret = nfs_open(nfs, url->file, flags, &fh)) != 0) { LD_NFS_DPRINTF(1, "Failed to open nfs file : " "%s\n", nfs_get_error(nfs)); nfs_destroy_url(url); nfs_destroy_context(nfs); errno = -ret; return -1; } } fd = nfs_get_fd(nfs); if (fd >= NFS_MAX_FD) { LD_NFS_DPRINTF(1, "Too many files open"); nfs_destroy_url(url); nfs_destroy_context(nfs); errno = ENFILE; return -1; } nfs_fd_list[fd].is_nfs = 1; nfs_fd_list[fd].nfs = nfs; nfs_fd_list[fd].fh = fh; nfs_fd_list[fd].path = strdup(path); nfs_fd_list[fd].flags = flags; nfs_fd_list[fd].mode = mode; nfs_destroy_url(url); LD_NFS_DPRINTF(9, "open(%s) == %d", path, fd); return fd; } return real_open(path, flags, mode); } int open64(const char *path, int flags, mode_t mode) { return open(path, flags | O_LARGEFILE, mode); } int (*real_close)(int fd); int close(int fd) { if (nfs_fd_list[fd].is_nfs == 1) { int i; LD_NFS_DPRINTF(9, "close(%d)", fd); nfs_fd_list[fd].is_nfs = 0; nfs_close(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh); nfs_fd_list[fd].fh = NULL; nfs_destroy_context(nfs_fd_list[fd].nfs); nfs_fd_list[fd].nfs = NULL; free(discard_const(nfs_fd_list[fd].path)); nfs_fd_list[fd].path = NULL; return 0; } return real_close(fd); } ssize_t (*real_read)(int fd, void *buf, size_t count); ssize_t read(int fd, void *buf, size_t count) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; LD_NFS_DPRINTF(9, "read(fd:%d count:%d)", fd, (int)count); if ((ret = nfs_read(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, count, buf)) < 0) { errno = -ret; return -1; } return ret; } return real_read(fd, buf, count); } ssize_t (*real_pread)(int fd, void *buf, size_t count, off_t offset); ssize_t pread(int fd, void *buf, size_t count, off_t offset) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; LD_NFS_DPRINTF(9, "pread(fd:%d offset:%d count:%d)", fd, (int)offset, (int)count); if ((ret = nfs_pread(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, offset, count, buf)) < 0) { errno = -ret; return -1; } return ret; } return real_pread(fd, buf, count, offset); } ssize_t (*real_write)(int fd, const void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; LD_NFS_DPRINTF(9, "write(fd:%d count:%d)", fd, (int)count); if ((ret = nfs_write(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, count, (char *)discard_const(buf))) < 0) { errno = -ret; return -1; } return ret; } return real_write(fd, buf, count); } ssize_t (*real_pwrite)(int fd, const void *buf, size_t count, off_t offset); ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; LD_NFS_DPRINTF(9, "pwrite(fd:%d offset:%d count:%d)", fd, (int)offset, (int)count); if ((ret = nfs_pwrite(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, offset, count, (char *)discard_const(buf))) < 0) { errno = -ret; return -1; } return ret; } return real_pwrite(fd, buf, count, offset); } int (*real_dup2)(int oldfd, int newfd); int dup2(int oldfd, int newfd) { close(newfd); if (nfs_fd_list[oldfd].is_nfs == 1) { struct nfs_context *nfs; struct nfs_url *url; struct nfsfh *fh = NULL; int ret, fd; LD_NFS_DPRINTF(9, "dup2(%s:%d, %d)", nfs_fd_list[oldfd].path, oldfd, newfd); nfs = nfs_init_context(); if (nfs == NULL) { LD_NFS_DPRINTF(1, "Failed to create context"); errno = ENOMEM; return -1; } url = nfs_parse_url_full(nfs, nfs_fd_list[oldfd].path); if (url == NULL) { LD_NFS_DPRINTF(1, "Failed to parse URL: %s\n", nfs_get_error(nfs)); nfs_destroy_context(nfs); errno = EINVAL; return -1; } if (nfs_mount(nfs, url->server, url->path) != 0) { LD_NFS_DPRINTF(1, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); nfs_destroy_url(url); nfs_destroy_context(nfs); errno = EINVAL; return -1; } if ((ret = nfs_open(nfs, url->file, nfs_fd_list[oldfd].mode, &fh)) != 0) { LD_NFS_DPRINTF(1, "Failed to open nfs file : %s\n", nfs_get_error(nfs)); nfs_destroy_url(url); nfs_destroy_context(nfs); errno = -ret; return -1; } /* We could actually end on the right descriptor by chance */ if (nfs_get_fd(nfs) != newfd) { if (real_dup2(nfs_get_fd(nfs), newfd) < 0) { LD_NFS_DPRINTF(1, "Failed to dup2 file : %d", errno); return -1; } close(rpc_get_fd(nfs_get_rpc_context(nfs))); rpc_set_fd(nfs_get_rpc_context(nfs), newfd); } fd = nfs_get_fd(nfs); if (fd >= NFS_MAX_FD) { LD_NFS_DPRINTF(1, "Too many files open"); nfs_destroy_url(url); nfs_destroy_context(nfs); errno = ENFILE; return -1; } nfs_fd_list[fd].is_nfs = 1; nfs_fd_list[fd].nfs = nfs; nfs_fd_list[fd].fh = fh; nfs_fd_list[fd].path = strdup(nfs_fd_list[oldfd].path); nfs_fd_list[fd].flags = nfs_fd_list[oldfd].flags; nfs_fd_list[fd].mode = nfs_fd_list[oldfd].mode; nfs_destroy_url(url); LD_NFS_DPRINTF(9, "dup2(%s) successful", nfs_fd_list[oldfd].path); return fd; } return real_dup2(oldfd, newfd); } int (*real_xstat)(int ver, __const char *path, struct stat *buf); int __xstat(int ver, const char *path, struct stat *buf) { if (!strncmp(path, "nfs:", 4)) { int fd, ret; LD_NFS_DPRINTF(9, "__xstat(%s)", path); fd = open(path, 0, 0); if (fd == -1) { return fd; } ret = __fxstat(ver, fd, buf); close(fd); return ret; } return real_xstat(ver, path, buf); } int (*real_xstat64)(int ver, __const char *path, struct stat64 *buf); int __xstat64(int ver, const char *path, struct stat64 *buf) { if (!strncmp(path, "nfs:", 4)) { int fd, ret; LD_NFS_DPRINTF(9, "__xstat64(%s)", path); fd = open(path, 0, 0); if (fd == -1) { return fd; } ret = __fxstat64(ver, fd, buf); close(fd); return ret; } return real_xstat64(ver, path, buf); } int (*real_lxstat)(int ver, __const char *path, struct stat *buf); int __lxstat(int ver, const char *path, struct stat *buf) { if (!strncmp(path, "nfs:", 4)) { int fd, ret; LD_NFS_DPRINTF(9, "__lxstat(%s)", path); fd = open(path, 0, 0); if (fd == -1) { return fd; } ret = __fxstat(ver, fd, buf); close(fd); return ret; } return real_lxstat(ver, path, buf); } int (*real_lxstat64)(int ver, __const char *path, struct stat64 *buf); int __lxstat64(int ver, const char *path, struct stat64 *buf) { if (!strncmp(path, "nfs:", 4)) { int fd, ret; LD_NFS_DPRINTF(9, "__lxstat64(%s)", path); fd = open(path, 0, 0); if (fd == -1) { return fd; } ret = __fxstat64(ver, fd, buf); close(fd); return ret; } return real_lxstat64(ver, path, buf); } int (*real_fxstat)(int ver, int fd, struct stat *buf); int __fxstat(int ver, int fd, struct stat *buf) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; struct nfs_stat_64 st64; LD_NFS_DPRINTF(9, "__fxstat(%d)", fd); if ((ret = nfs_fstat64(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, (void *)&st64)) < 0) { errno = -ret; return -1; } buf->st_dev = st64.nfs_dev; buf->st_ino = st64.nfs_ino; buf->st_mode = st64.nfs_mode; buf->st_nlink = st64.nfs_nlink; buf->st_uid = st64.nfs_uid; buf->st_gid = st64.nfs_gid; buf->st_rdev = st64.nfs_rdev; buf->st_size = st64.nfs_size; buf->st_blksize = st64.nfs_blksize; buf->st_blocks = st64.nfs_blocks; buf->st_atim.tv_sec = st64.nfs_atime; buf->st_mtim.tv_sec = st64.nfs_mtime; buf->st_ctim.tv_sec = st64.nfs_ctime; LD_NFS_DPRINTF(9, "__fxstat(%d) success", fd); return ret; } return real_fxstat(ver, fd, buf); } int (*real_fxstat64)(int ver, int fd, struct stat64 *buf); int __fxstat64(int ver, int fd, struct stat64 *buf) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; struct nfs_stat_64 st64; LD_NFS_DPRINTF(9, "__fxstat64(%d)", fd); if ((ret = nfs_fstat64(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, (void *)&st64)) < 0) { errno = -ret; return -1; } buf->st_dev = st64.nfs_dev; buf->st_ino = st64.nfs_ino; buf->st_mode = st64.nfs_mode; buf->st_nlink = st64.nfs_nlink; buf->st_uid = st64.nfs_uid; buf->st_gid = st64.nfs_gid; buf->st_rdev = st64.nfs_rdev; buf->st_size = st64.nfs_size; buf->st_blksize = st64.nfs_blksize; buf->st_blocks = st64.nfs_blocks; buf->st_atim.tv_sec = st64.nfs_atime; buf->st_mtim.tv_sec = st64.nfs_mtime; buf->st_ctim.tv_sec = st64.nfs_ctime; LD_NFS_DPRINTF(9, "__fxstat64(%d) success", fd); return ret; } return real_fxstat64(ver, fd, buf); } int (*real_fxstatat)(int ver, int fd, const char *path, struct stat *buf, int flag); int __fxstatat(int ver, int fd, const char *path, struct stat *buf, int flag) { if (!strncmp(path, "nfs:", 4)) { return __xstat(ver, path, buf); } return real_fxstatat(ver, fd, path, buf, flag); } int (*real_fxstatat64)(int ver, int fd, const char *path, struct stat64 *buf, int flag); int __fxstatat64(int ver, int fd, const char *path, struct stat64 *buf, int flag) { if (!strncmp(path, "nfs:", 4)) { return __xstat64(ver, path, buf); } return real_fxstatat64(ver, fd, path, buf, flag); } int (*real_fallocate)(int fd, int mode, off_t offset, off_t len); int fallocate(int fd, int mode, off_t offset, off_t len) { if (nfs_fd_list[fd].is_nfs == 1) { LD_NFS_DPRINTF(9, "fallocate(%d)", fd); errno = EOPNOTSUPP; return -1; } return real_fallocate(fd, mode, offset, len); } int (*real_ftruncate)(int fd, off_t len); int ftruncate(int fd, off_t len) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; LD_NFS_DPRINTF(9, "ftruncate(%d, %d)", fd, (int)len); if ((ret = nfs_ftruncate(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, len)) < 0) { errno = -ret; return -1; } return 0; } return real_ftruncate(fd, len); } int (*real_truncate)(const char *path, off_t len); int truncate(const char *path, off_t len) { if (!strncmp(path, "nfs:", 4)) { int fd, ret; LD_NFS_DPRINTF(9, "truncate(%s, %d)", path, (int)len); fd = open(path, 0, 0); if (fd == -1) { return fd; } ret = ftruncate(fd, len); close(fd); return ret; } return real_truncate(path, len); } int (*real_fchmod)(int fd, mode_t mode); int fchmod(int fd, mode_t mode) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; LD_NFS_DPRINTF(9, "fchmod(%d, %o)", fd, (int)mode); if ((ret = nfs_fchmod(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, mode)) < 0) { errno = -ret; return -1; } return 0; } return real_fchmod(fd, mode); } int (*real_chmod)(const char *path, mode_t mode); int chmod(const char *path, mode_t mode) { if (!strncmp(path, "nfs:", 4)) { int fd, ret; LD_NFS_DPRINTF(9, "chmod(%s, %o)", path, (int)mode); fd = open(path, 0, 0); if (fd == -1) { return fd; } ret = fchmod(fd, mode); close(fd); return ret; } return real_chmod(path, mode); } int (*real_fchmodat)(int fd, const char *path, mode_t mode, int flags); int fchmodat(int fd, const char *path, mode_t mode, int flags) { if (!strncmp(path, "nfs:", 4)) { return chmod(path, mode); } return real_fchmodat(fd, path, mode, flags); } int (*real_fchown)(int fd, __uid_t uid, __gid_t gid); int fchown(int fd, __uid_t uid, __gid_t gid) { if (nfs_fd_list[fd].is_nfs == 1) { int ret; LD_NFS_DPRINTF(9, "fchown(%d, %o, %o)", fd, (int)uid, (int)gid); if ((ret = nfs_fchown(nfs_fd_list[fd].nfs, nfs_fd_list[fd].fh, uid, gid)) < 0) { errno = -ret; return -1; } return 0; } return real_fchown(fd, uid, gid); } int (*real_chown)(const char *path, __uid_t uid, __gid_t gid); int chown(const char *path, __uid_t uid, __gid_t gid) { if (!strncmp(path, "nfs:", 4)) { int fd, ret; LD_NFS_DPRINTF(9, "chown(%s, %o, %o)", path, (int)uid, (int)gid); fd = open(path, 0, 0); if (fd == -1) { return fd; } ret = fchown(fd, uid, gid); close(fd); return ret; } return real_chown(path, uid, gid); } int (*real_fchownat)(int fd, const char *path, __uid_t uid, __gid_t gid, int flags); int fchownat(int fd, const char *path, uid_t uid, gid_t gid, int flags) { if (!strncmp(path, "nfs:", 4)) { return chown(path, uid, gid); } return real_fchownat(fd, path, uid, gid, flags); } static void __attribute__((constructor)) _init(void) { int i; if (getenv("LD_NFS_DEBUG") != NULL) { debug = atoi(getenv("LD_NFS_DEBUG")); } if (getenv("LD_NFS_UID") != NULL) { nfsuid = atoi(getenv("LD_NFS_UID")); } if (getenv("LD_NFS_GID") != NULL) { nfsgid = atoi(getenv("LD_NFS_GID")); } real_open = dlsym(RTLD_NEXT, "open"); if (real_open == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(open)"); exit(10); } real_close = dlsym(RTLD_NEXT, "close"); if (real_close == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(close)"); exit(10); } real_read = dlsym(RTLD_NEXT, "read"); if (real_read == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(read)"); exit(10); } real_pread = dlsym(RTLD_NEXT, "pread"); if (real_pread == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(pread)"); exit(10); } real_write = dlsym(RTLD_NEXT, "write"); if (real_write == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(write)"); exit(10); } real_pwrite = dlsym(RTLD_NEXT, "pwrite"); if (real_pwrite == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(pwrite)"); exit(10); } real_xstat = dlsym(RTLD_NEXT, "__xstat"); if (real_xstat == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(__xstat)"); exit(10); } real_xstat64 = dlsym(RTLD_NEXT, "__xstat64"); if (real_xstat64 == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(__xstat64)"); } real_lxstat = dlsym(RTLD_NEXT, "__lxstat"); if (real_lxstat == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(__lxstat)"); exit(10); } real_lxstat64 = dlsym(RTLD_NEXT, "__lxstat64"); if (real_lxstat64 == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(_lxstat64)"); exit(10); } real_fxstat = dlsym(RTLD_NEXT, "__fxstat"); if (real_fxstat == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(__fxstat)"); exit(10); } real_fxstat64 = dlsym(RTLD_NEXT, "__fxstat64"); if (real_fxstat64 == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(__fxstat64)"); exit(10); } real_fxstatat = dlsym(RTLD_NEXT, "__fxstatat"); if (real_fxstatat == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(__fxstatat)"); exit(10); } real_fxstatat64 = dlsym(RTLD_NEXT, "__fxstatat64"); if (real_fxstatat64 == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(__fxstatat64)"); exit(10); } real_fallocate = dlsym(RTLD_NEXT, "fallocate"); if (real_fallocate == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(fallocate)"); exit(10); } real_dup2 = dlsym(RTLD_NEXT, "dup2"); if (real_dup2 == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(dup2)"); exit(10); } real_truncate = dlsym(RTLD_NEXT, "truncate"); if (real_truncate == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(truncate)"); exit(10); } real_ftruncate = dlsym(RTLD_NEXT, "ftruncate"); if (real_ftruncate == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(ftruncate)"); exit(10); } real_chmod = dlsym(RTLD_NEXT, "chmod"); if (real_chmod == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(chmod)"); exit(10); } real_fchmod = dlsym(RTLD_NEXT, "fchmod"); if (real_fchmod == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(fchmod)"); exit(10); } real_fchmodat = dlsym(RTLD_NEXT, "fchmodat"); if (real_fchmodat == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(fchmodat)"); exit(10); } real_chown = dlsym(RTLD_NEXT, "chown"); if (real_chown == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(chown)"); exit(10); } real_fchown = dlsym(RTLD_NEXT, "fchown"); if (real_fchown == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(fchown)"); exit(10); } real_fchownat = dlsym(RTLD_NEXT, "fchownat"); if (real_fchownat == NULL) { LD_NFS_DPRINTF(0, "Failed to dlsym(fchownat)"); exit(10); } } libnfs-libnfs-4.0.0/examples/nfs-fh.c000066400000000000000000000054031343063627400174200ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2018 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #else #include #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-nfs.h" void usage(void) { fprintf(stderr, "Usage: nfs-fh \n"); fprintf(stderr, "\tPrints the NFS filehandle for a URL.\n"); exit(0); } int main(int argc, char *argv[]) { int i; int ret = 0; struct nfs_context *nfs = NULL; struct nfsfh *nfsfh = NULL; struct nfs_fh3 *fh3; struct nfs_url *url = NULL; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); return 1; } #endif #ifdef AROS aros_init_socket(); #endif if (argc < 2) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { fprintf(stderr, "failed to init context\n"); goto finished; } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_open(nfs, url->file, O_RDONLY, &nfsfh) != 0) { fprintf(stderr, "Failed to open file %s: %s\n", url->file, nfs_get_error(nfs)); ret = 1; goto finished; } fh3 = (struct nfs_fh3 *)nfs_get_fh(nfsfh); for (i = 0; i < fh3->data.data_len; i++) { printf("%02x", (unsigned char)(fh3->data.data_val[i])); } printf("\n"); finished: if (nfsfh) { nfs_close(nfs, nfsfh); } nfs_umount(nfs); if (url) { nfs_destroy_url(url); } if (nfs) { nfs_destroy_context(nfs); } return ret; } libnfs-libnfs-4.0.0/examples/nfs-io.c000066400000000000000000000076641343063627400174450ustar00rootroot00000000000000/* Copyright (C) by Peter Lieven 2013 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #define PRId64 "ll" #else #include #include #include #include #ifndef AROS #include #endif #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" void print_usage(void) { fprintf(stderr, "Usage: nfs-io [-?|--help|--usage] [stat|creat|trunc|unlink|mkdir|rmdir] \n"); } int main(int argc, char *argv[]) { int ret = 1; struct nfs_context *nfs = NULL; struct nfsfh *nfsfh = NULL; struct nfs_url *url = NULL; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif #ifdef AROS aros_init_socket(); #endif if (argc < 3) { fprintf(stderr, "No URL specified.\n"); goto finished; } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); goto finished; } url = nfs_parse_url_full(nfs, argv[argc - 1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); goto finished; } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); goto finished; } if (!strncmp(argv[1], "creat", 5)) { ret = nfs_creat(nfs, url->file, 0600, &nfsfh); } else if (!strncmp(argv[1], "unlink", 6)) { ret = nfs_unlink(nfs, url->file); } else if (!strncmp(argv[1], "mkdir", 5)) { ret = nfs_mkdir(nfs, url->file); } else if (!strncmp(argv[1], "rmdir", 5)) { ret = nfs_rmdir(nfs, url->file); } else if (!strncmp(argv[1], "trunc", 5)) { ret = nfs_truncate(nfs, url->file, 0); } else if (!strncmp(argv[1], "stat", 4)) { struct nfs_stat_64 st; ret = nfs_stat64(nfs, url->file, &st); if (!ret) { switch (st.nfs_mode & S_IFMT) { #ifndef WIN32 case S_IFLNK: printf("l"); break; #endif case S_IFREG: printf("-"); break; case S_IFDIR: printf("d"); break; case S_IFCHR: printf("c"); break; case S_IFBLK: printf("b"); break; } printf("%c%c%c", "-r"[!!(st.nfs_mode & S_IRUSR)], "-w"[!!(st.nfs_mode & S_IWUSR)], "-x"[!!(st.nfs_mode & S_IXUSR)] ); printf("%c%c%c", "-r"[!!(st.nfs_mode & S_IRGRP)], "-w"[!!(st.nfs_mode & S_IWGRP)], "-x"[!!(st.nfs_mode & S_IXGRP)] ); printf("%c%c%c", "-r"[!!(st.nfs_mode & S_IROTH)], "-w"[!!(st.nfs_mode & S_IWOTH)], "-x"[!!(st.nfs_mode & S_IXOTH)] ); printf(" %2d", (int)st.nfs_nlink); printf(" %5d", (int)st.nfs_uid); printf(" %5d", (int)st.nfs_gid); printf(" %12" PRId64, st.nfs_size); printf("\n"); } } else { goto finished; } if (ret) { fprintf(stderr, "ERROR: %s\n", nfs_get_error(nfs)); } finished: if (ret > 0) { print_usage(); } nfs_destroy_url(url); if (nfs != NULL) { if (nfsfh) { nfs_close(nfs, nfsfh); } nfs_destroy_context(nfs); } return !!ret; } libnfs-libnfs-4.0.0/examples/nfs-ln.c000066400000000000000000000051151343063627400174340ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #define PRId64 "ll" #else #include #include #include #include #ifndef AROS #include #endif #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" void print_usage(void) { fprintf(stderr, "Usage: nfs-ln \n"); } int main(int argc, char *argv[]) { int ret = 1; struct nfs_context *nfs = NULL; struct nfsfh *nfsfh = NULL; struct nfs_url *url = NULL; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif #ifdef AROS aros_init_socket(); #endif if (argc != 4) { print_usage(); goto finished; } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); goto finished; } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); goto finished; } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); goto finished; } ret = nfs_link(nfs, argv[2], argv[3]); if (ret) { fprintf(stderr, "nfs_link() failed with %s\n", nfs_get_error(nfs)); goto finished; } finished: if (ret > 0) { print_usage(); } nfs_destroy_url(url); if (nfs != NULL) { if (nfsfh) { nfs_close(nfs, nfsfh); } nfs_destroy_context(nfs); } return !!ret; } libnfs-libnfs-4.0.0/examples/nfs4-cat-talloc.c000066400000000000000000000716521343063627400211430ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* THIS IS NOT A PROPER NFS4 CLIENT! * This software is only meant to illustrate how to plug libnfs into * an eventsystem like libevent and then use the raw rpc api * connect to an nfsv4 server and read a file. * If any kind of error occurs it will immediately terminate by calling * exit() without even attempting to cleanup. * If the access to the server is successful it should however run valgrind * clean. * * NFSv4 access is done through the raw async interface and is cumbersome * to use for NFSv4 due to the richness of the protocol. * A future aim will be to build better helper functions to make ease * of use better. */ /* Copyright (C) by Ronnie Sahlberg 2015 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #else #include #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-nfs4.h" #include #include struct tevent_context *ev; struct client { struct nfs_context *nfs; struct rpc_context *rpc; char *server; char *path; struct tevent_fd *fde; int callback_fd; /* For SETCLIENTID */ verifier4 verifier; char *id; clientid4 clientid; verifier4 setclientid_confirm; /* For OPEN */ char *owner; int op_len; /* filehandle and state for the open file */ nfs_fh4 fh; uint32_t seqid; stateid4 stateid; /* offset when reading */ uint64_t offset; int is_finished; }; static void set_nonblocking(int fd) { int v = 0; #if defined(WIN32) long nonblocking=1; v = ioctl(fd, FIONBIO, &nonblocking); #else v = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, v | O_NONBLOCK); #endif } static int client_destructor(struct client *c) { if (c->nfs) { nfs_destroy_context(c->nfs); } if (c->callback_fd != -1) { close(c->callback_fd); } }; void usage(void) { fprintf(stderr, "Usage: nfs4-cat-talloc \n"); fprintf(stderr, " is an nfs url.\n"); exit(0); } static void update_events(struct rpc_context *rpc, struct tevent_fd *fde) { int events = rpc_which_events(rpc); int flags = 0; if (events & POLLIN) { flags |= TEVENT_FD_READ; } if (events & POLLOUT) { flags |= TEVENT_FD_WRITE; } tevent_fd_set_flags(fde, flags); } struct server { struct rpc_context *rpc; struct tevent_fd *fde; }; /* * Helper functions to send client RPC requests. */ static void send_setclientid(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; SETCLIENTID4args *sc4args; nfs_argop4 op[1]; struct sockaddr_storage ss; socklen_t len = sizeof(ss); struct sockaddr_in *in; struct sockaddr_in6 *in6; char *netid; char str[240], addr[256]; unsigned short port; if (getsockname(client->callback_fd, (struct sockaddr *)&ss, &len) < 0) { fprintf(stderr, "getsockaddr failed\n"); talloc_free(client); exit(10); } switch (ss.ss_family) { case AF_INET: netid = "tcp"; in = (struct sockaddr_in *)&ss; inet_ntop(AF_INET, &in->sin_addr, str, sizeof(str)); port = ntohs(in->sin_port); break; case AF_INET6: netid = "tcp6"; in6 = (struct sockaddr_in6 *)&ss; inet_ntop(AF_INET6, &in6->sin6_addr, str, sizeof(str)); port = ntohs(in6->sin6_port); break; } sprintf(addr, "%s.%d.%d", str, port >> 8, port & 0xff); memset(op, 0, sizeof(op)); op[0].argop = OP_SETCLIENTID; sc4args = &op[0].nfs_argop4_u.opsetclientid; memcpy(sc4args->client.verifier, client->verifier, sizeof(verifier4)); sc4args->client.id.id_len = strlen(client->id); sc4args->client.id.id_val = client->id; sc4args->callback.cb_program = NFS4_CALLBACK; sc4args->callback.cb_location.r_netid = netid; sc4args->callback.cb_location.r_addr = addr; sc4args->callback_ident = 0x00000001; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 SETCLIENTID request\n"); talloc_free(client); exit(10); } } static void send_setclientid_confirm(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; SETCLIENTID_CONFIRM4args *scc4args; nfs_argop4 op[1]; memset(op, 0, sizeof(op)); op[0].argop = OP_SETCLIENTID_CONFIRM; scc4args = &op[0].nfs_argop4_u.opsetclientid_confirm; scc4args->clientid = client->clientid; memcpy(scc4args->setclientid_confirm, client->setclientid_confirm, NFS4_VERIFIER_SIZE); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 SETCLIENTID_CONFIRM request\n"); talloc_free(client); exit(10); } } static void send_getrootfh(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; nfs_argop4 op[2]; memset(op, 0, sizeof(op)); op[0].argop = OP_PUTROOTFH; op[1].argop = OP_GETFH; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 GETROOTFH request\n"); talloc_free(client); exit(10); } } static void send_open(struct rpc_context *rpc, nfs_fh4 dir, char *path, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; ACCESS4args *a4args; LOOKUP4args *l4args; OPEN4args *o4args; nfs_argop4 *op; int i = 0, idx = 0; char *tmp; /* * Count how many directories we have in the path. */ tmp = path; while (tmp = strchr(tmp, '/')) { i++; tmp++; } op = talloc_zero_array(client, nfs_argop4, 4 + i); op[idx].argop = OP_PUTFH; op[idx].nfs_argop4_u.opputfh.object = dir; idx++; while (i-- > 0) { tmp = strchr(path, '/'); *tmp++ = '\0'; op[idx].argop = OP_LOOKUP; l4args = &op[idx].nfs_argop4_u.oplookup; l4args->objname.utf8string_len = strlen(path); l4args->objname.utf8string_val = path; idx++; path = tmp; } op[idx].argop = OP_OPEN; o4args = &op[idx].nfs_argop4_u.opopen; o4args->seqid = client->seqid; o4args->share_access = OPEN4_SHARE_ACCESS_READ; o4args->share_deny = OPEN4_SHARE_DENY_NONE; o4args->owner.clientid = client->clientid; o4args->owner.owner.owner_len = strlen(client->owner); o4args->owner.owner.owner_val = client->owner; o4args->openhow.opentype = OPEN4_NOCREATE; o4args->claim.claim = CLAIM_NULL; o4args->claim.open_claim4_u.file.utf8string_len = strlen(path); o4args->claim.open_claim4_u.file.utf8string_val = path; idx++; op[idx].argop = OP_GETFH; idx++; op[idx].argop = OP_ACCESS; a4args = &op[idx].nfs_argop4_u.opaccess; a4args->access = ACCESS4_READ; client->seqid++; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = idx; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 OPEN request\n"); talloc_free(client); exit(10); } talloc_free(op); } static void send_open_confirm(struct rpc_context *rpc, nfs_fh4 object, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; OPEN_CONFIRM4args *oc4args; PUTFH4args *pfh4args; nfs_argop4 op[2]; memset(op, 0, sizeof(op)); op[0].argop = OP_PUTFH; pfh4args = &op[0].nfs_argop4_u.opputfh; pfh4args->object = object; op[1].argop = OP_OPEN_CONFIRM; oc4args = &op[1].nfs_argop4_u.opopen_confirm; oc4args->open_stateid.seqid = client->seqid; memcpy(oc4args->open_stateid.other, client->stateid.other, 12); oc4args->seqid = client->seqid; client->seqid++; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 CLOSE request\n"); talloc_free(client); exit(10); } } static void send_read(struct rpc_context *rpc, nfs_fh4 object, uint64_t offset, uint32_t count, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; PUTFH4args *pfh4args; READ4args *r4args; nfs_argop4 op[3]; memset(op, 0, sizeof(op)); op[0].argop = OP_PUTFH; pfh4args = &op[0].nfs_argop4_u.opputfh; pfh4args->object = object; op[1].argop = OP_READ; r4args = &op[1].nfs_argop4_u.opread; r4args->stateid.seqid = client->seqid; memcpy(r4args->stateid.other, client->stateid.other, 12); r4args->offset = offset; r4args->count = count; op[2].argop = OP_GETATTR; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 READ request\n"); talloc_free(client); exit(10); } } static void send_close(struct rpc_context *rpc, nfs_fh4 object, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; CLOSE4args *c4args; PUTFH4args *pfh4args; nfs_argop4 op[2]; memset(op, 0, sizeof(op)); op[0].argop = OP_PUTFH; pfh4args = &op[0].nfs_argop4_u.opputfh; pfh4args->object = object; op[1].argop = OP_CLOSE; c4args = &op[1].nfs_argop4_u.opclose; c4args->seqid = client->seqid; c4args->open_stateid.seqid = client->seqid; memcpy(c4args->open_stateid.other, client->stateid.other, 12); client->seqid++; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 CLOSE request\n"); talloc_free(client); exit(10); } } /* * Callbacks for completed requests. */ void close_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; /* * FINISHED */ /* * Note that we can not start tearing down and destroying the contexts * right here as we are still in a callback from ... rpc_service(). * Instead flag that we should abort and start doing the teardown * in client_io once we return from libnfs. */ client->is_finished = 1; } void read_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; struct READ4res *r4res; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to read file on server %s\n", client->server); talloc_free(client); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to read file on server %s\n", client->server); talloc_free(client); exit(10); } r4res = &res->resarray.resarray_val[1].nfs_resop4_u.opread; write(1, r4res->READ4res_u.resok4.data.data_val, r4res->READ4res_u.resok4.data.data_len); /* * Are we at end-of-file? If so we can close the file and exit. */ if (r4res->READ4res_u.resok4.eof) { send_close(rpc, client->fh, close_cb, client); return; } /* * We still have more data to read. */ client->offset += r4res->READ4res_u.resok4.data.data_len; send_read(rpc, client->fh, client->offset, 4096, read_cb, client); } void open_confirm_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to confirm open file on server %s\n", client->server); talloc_free(client); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to confirm open file on server %s\n", client->server); talloc_free(client); exit(10); } send_read(rpc, client->fh, client->offset, 4096, read_cb, client); } void open_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; GETFH4res *gfh4res; OPEN4res *o4res; int idx; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to open file on server %s\n", client->server); talloc_free(client); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to open file on server %s\n", client->server); talloc_free(client); exit(10); } /* Find the index for the OPEN opcode */ for (idx = 1; idx < res->resarray.resarray_len - 1; idx++) { if ((res->resarray.resarray_val[idx].resop == OP_OPEN) && (res->resarray.resarray_val[idx + 1].resop == OP_GETFH)) { break; } } if (idx >= res->resarray.resarray_len - 1) { fprintf(stderr, "No OP_OPEN in server response\n"); talloc_free(client); exit(10); } /* Store the open handle in the client structure */ gfh4res = &res->resarray.resarray_val[idx+1].nfs_resop4_u.opgetfh; client->fh.nfs_fh4_len = gfh4res->GETFH4res_u.resok4.object.nfs_fh4_len; client->fh.nfs_fh4_val = talloc_size(client, client->fh.nfs_fh4_len); if (client->fh.nfs_fh4_val == NULL) { fprintf(stderr, "Failed to allocate data for nfs_fh4\n"); talloc_free(client); exit(10); } memcpy(client->fh.nfs_fh4_val, gfh4res->GETFH4res_u.resok4.object.nfs_fh4_val, client->fh.nfs_fh4_len); /* Store stateid for the open handle in the client structure */ o4res = &res->resarray.resarray_val[idx].nfs_resop4_u.opopen; client->stateid.seqid = o4res->OPEN4res_u.resok4.stateid.seqid; memcpy(client->stateid.other, o4res->OPEN4res_u.resok4.stateid.other, 12); /* Check if server wants us to confirm the open */ if (o4res->OPEN4res_u.resok4.rflags & OPEN4_RESULT_CONFIRM) { send_open_confirm(rpc, client->fh, open_confirm_cb, client); return; } send_read(rpc, client->fh, client->offset, 4096, read_cb, client); } void getrootfh_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; GETFH4res *gfh4res; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to get root filehandle of server %s\n", client->server); talloc_free(client); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to get root filehandle of server %s\n", client->server); talloc_free(client); exit(10); } gfh4res = &res->resarray.resarray_val[1].nfs_resop4_u.opgetfh; send_open(rpc, gfh4res->GETFH4res_u.resok4.object, client->path, open_cb, client); } void setclientid_confirm_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; char *path; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to set client id of server %s\n", client->server); talloc_free(client); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to set client id of server %s\n", client->server); talloc_free(client); exit(10); } send_getrootfh(rpc, getrootfh_cb, client); } void setclientid_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; SETCLIENTID4res *sc4res; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to set client id on server %s\n", client->server); talloc_free(client); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to set client id on server %s\n", client->server); talloc_free(client); exit(10); } sc4res = &res->resarray.resarray_val[0].nfs_resop4_u.opsetclientid; client->clientid = sc4res->SETCLIENTID4res_u.resok4.clientid; memcpy(client->setclientid_confirm, sc4res->SETCLIENTID4res_u.resok4.setclientid_confirm, NFS4_VERIFIER_SIZE); send_setclientid_confirm(rpc, setclientid_confirm_cb, client); } /* * NULL procedure for the callback protocol. */ static int cb_null_proc(struct rpc_context *rpc, struct rpc_msg *call) { rpc_send_reply(rpc, call, NULL, (zdrproc_t)zdr_void, 0); return 0; } /* * CB_COMPOUND procedure for the callback protocol. * This is where the server will inform us about lease breaks and similar. */ static int cb_compound_proc(struct rpc_context *rpc, struct rpc_msg *call) { CB_COMPOUND4args *args = call->body.cbody.args; fprintf(stderr, "cb_compund_cb. Do something here.\n"); return 0; } struct service_proc pt[] = { {CB_NULL, cb_null_proc, (zdrproc_t)zdr_void, 0}, {CB_COMPOUND, cb_compound_proc, (zdrproc_t)zdr_CB_COMPOUND4args, sizeof(CB_COMPOUND4args)}, }; static void server_io(struct tevent_context *ev, struct tevent_fd *fde, uint16_t events, void *private_data) { struct server *server = private_data; int revents = 0; if (events & TEVENT_FD_READ) { revents |= POLLIN; } if (events & TEVENT_FD_WRITE) { revents |= POLLOUT; } if (rpc_service(server->rpc, revents) < 0) { talloc_free(server); return; } update_events(server->rpc, server->fde); } static int server_destructor(struct server *s) { if (s->rpc) { rpc_destroy_context(s->rpc); } } /* * This callback is invoked when others (the nfsv4 server) initiates a * NFSv4 CALLBACK sessions to us. * We accept() the connection and create a local rpc server context * for the callback protocol. */ static void client_accept(struct tevent_context *ev, struct tevent_fd *fde, uint16_t events, void *private_data) { struct client *client = private_data; struct server *server; struct sockaddr_storage ss; socklen_t len = sizeof(ss); int fd; server = talloc_zero(client, struct server); talloc_set_destructor(server, server_destructor); if ((fd = accept(client->callback_fd, (struct sockaddr *)&ss, &len)) < 0) { fprintf(stderr, "accept failed\n"); talloc_free(server); return; } set_nonblocking(fd); server->rpc = rpc_init_server_context(fd); if (server->rpc == NULL) { fprintf(stderr, "Failed to create server rpc context\n"); talloc_free(server); return; } rpc_register_service(server->rpc, NFS4_CALLBACK, NFS_CB, pt, sizeof(pt) / sizeof(pt[0])); server->fde = tevent_add_fd(ev, server, fd, TEVENT_FD_READ, server_io, server); tevent_fd_set_auto_close(server->fde); update_events(server->rpc, server->fde); } /* * This callback is invoked when our async connect() to the server has * completed. At this point we know which IP address was used locally for * the connection and can bind our nfsv4 callback server instance to it. */ void connect_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; struct sockaddr_storage ss; socklen_t len = sizeof(ss); struct sockaddr_in *in; struct sockaddr_in6 *in6; struct tevent_fd *fde; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "connection to NFSv4 server %s failed\n", client->server); talloc_free(client); exit(10); } /* * NFSv4 CALLBACK * Now that we have a client connection we can register a callback * server port on the same IP address as was used to the outgoing * client connection. That way we know that the address used by the * server is routable, and uses the same version of ip, that the client * supports and can route to. */ if (getsockname(rpc_get_fd(rpc), (struct sockaddr *)&ss, &len) < 0) { fprintf(stderr, "getsockaddr failed\n"); talloc_free(client); exit(10); } switch (ss.ss_family) { case AF_INET: in = (struct sockaddr_in *)&ss; in->sin_port=0; break; case AF_INET6: in6 = (struct sockaddr_in6 *)&ss; in6->sin6_port=0; break; default: fprintf(stderr, "Can not handle AF_FAMILY:%d", ss.ss_family); talloc_free(client); exit(10); } client->callback_fd = socket(AF_INET, SOCK_STREAM, 0); if (client->callback_fd == -1) { fprintf(stderr, "Failed to create callback socket\n"); talloc_free(client); exit(10); } set_nonblocking(client->callback_fd); if (bind(client->callback_fd, (struct sockaddr *)&ss, sizeof(ss)) < 0) { fprintf(stderr, "Failed to bind callback socket\n"); talloc_free(client); exit(10); } if (listen(client->callback_fd, 16) < 0) { fprintf(stderr, "failed to listen to callback socket\n"); talloc_free(client); exit(10); } fde = tevent_add_fd(ev, client, client->callback_fd, TEVENT_FD_READ, client_accept, private_data); tevent_fd_set_auto_close(fde); update_events(client->rpc, client->fde); /* * Now that we are finished setting up the callback server port * we can proceed and negotiate the nfsv4 client id. */ send_setclientid(rpc, setclientid_cb, client); } static void client_io(struct tevent_context *ev, struct tevent_fd *fde, uint16_t events, void *private_data) { struct client *client = private_data; int revents = 0; if (events & TEVENT_FD_READ) { revents |= POLLIN; } if (events & TEVENT_FD_WRITE) { revents |= POLLOUT; } if (rpc_service(client->rpc, revents) < 0) { fprintf(stderr, "rpc_service failed\n"); talloc_free(client); exit(10); } update_events(client->rpc, client->fde); if (client->is_finished) { talloc_free(client); } } int main(int argc, char *argv[]) { TALLOC_CTX *ctx = talloc_new(NULL); struct client *client; struct nfs_url *url; int i, fd; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { fprintf(stderr, "Failed to start Winsock2\n"); exit(10); } #endif #ifdef AROS aros_init_socket(); #endif srandom(time(NULL) ^ getpid()); if (argc < 2) { usage(); } ev = tevent_context_init(ctx); client = talloc_zero(ctx, struct client); talloc_set_destructor(client, client_destructor); client->callback_fd = -1; client->nfs = nfs_init_context(); if (client->nfs == NULL) { fprintf(stderr, "failed to init nfs context\n"); talloc_free(ctx); exit(10); } url = nfs_parse_url_dir(client->nfs, argv[1]); if (url == NULL) { fprintf(stderr, "failed to parse url\n"); talloc_free(ctx); exit(10); } client->server = talloc_strdup(client, url->server); client->path = talloc_strdup(client, &url->path[1]); // skip leading '/' nfs_destroy_url(url); for (i = 0; i < NFS4_VERIFIER_SIZE; i++) { client->verifier[i] = random() & 0xff; } client->id = talloc_asprintf(client, "Libnfs %s tcp pid:%d", argv[1], getpid()); client->owner = talloc_asprintf(client, "open id:libnfs pid:%d", getpid()); /* * From here on we will mainly use the rpc context directly * and not the nfs context so lets store the rpc context here * for easy access. */ client->rpc = nfs_get_rpc_context(client->nfs); if (rpc_connect_program_async(client->rpc, client->server, NFS4_PROGRAM, NFS_V4, connect_cb, client) != 0) { fprintf(stderr, "Failed to start connection: %s\n", rpc_get_error(client->rpc)); talloc_free(ctx); exit(10); } /* * Set up the events we need for the outgoing client RPC channel. */ fd = rpc_get_fd(client->rpc); client->fde = tevent_add_fd(ev, client, fd, TEVENT_FD_READ, client_io, (void *)client); update_events(client->rpc, client->fde); tevent_loop_wait(ev); talloc_free(ctx); return 0; } libnfs-libnfs-4.0.0/examples/nfs4-cat.c000066400000000000000000000726671343063627400176760ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* THIS IS NOT A PROPER NFS4 CLIENT! * This software is only meant to illustrate how to plug libnfs into * an eventsystem like libevent and then use the raw rpc api * connect to an nfsv4 server and read a file. * If any kind of error occurs it will immediately terminate by calling * exit() without even attempting to cleanup. * If the access to the server is successful it should however run valgrind * clean. * * NFSv4 access is done through the raw async interface and is cumbersome * to use for NFSv4 due to the richness of the protocol. * A future aim will be to build better helper functions to make ease * of use better. */ /* Copyright (C) by Ronnie Sahlberg 2015 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #else #include #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-nfs4.h" #include struct event_base *base; struct client { struct rpc_context *rpc; struct event *read_event; struct event *write_event; struct event *listen_event; char *server; char *path; int op_len; int is_finished; verifier4 verifier; char *id; char *owner; clientid4 clientid; verifier4 setclientid_confirm; /* filehandle and state for the open file */ nfs_fh4 fh; uint32_t seqid; stateid4 stateid; /* offset when reading */ uint64_t offset; int callback_fd; }; struct server { struct server *next; struct rpc_context *rpc; struct event *read_event; struct event *write_event; }; struct server *server_list; void usage(void) { fprintf(stderr, "Usage: nfs4-cat \n"); fprintf(stderr, " is an nfs url.\n"); exit(0); } static void update_events(struct rpc_context *rpc, struct event *read_event, struct event *write_event) { int events = rpc_which_events(rpc); if (read_event) { if (events & POLLIN) { event_add(read_event, NULL); } else { event_del(read_event); } } if (write_event) { if (events & POLLOUT) { event_add(write_event, NULL); } else { event_del(write_event); } } } static void free_server(struct server *server) { if (server->rpc) { rpc_disconnect(server->rpc, NULL); rpc_destroy_context(server->rpc); server->rpc = NULL; } if (server->read_event) { event_free(server->read_event); server->read_event = NULL; } if (server->write_event) { event_free(server->write_event); server->write_event = NULL; } free(server); } static void server_io(evutil_socket_t fd, short events, void *private_data) { struct server *server = private_data; int revents = 0; if (events & EV_READ) { revents |= POLLIN; } if (events & EV_WRITE) { revents |= POLLOUT; } if (rpc_service(server->rpc, revents) < 0) { fprintf(stderr, "rpc_service() failed for server\n"); exit(10); } update_events(server->rpc, server->read_event, server->write_event); } static void client_io(evutil_socket_t fd, short events, void *private_data) { struct client *client = private_data; struct server *server; int revents = 0; if (events & EV_READ) { revents |= POLLIN; } if (events & EV_WRITE) { revents |= POLLOUT; } if (rpc_service(client->rpc, revents) < 0) { fprintf(stderr, "rpc_service failed\n"); exit(10); } update_events(client->rpc, client->read_event, client->write_event); if (client->is_finished) { /* * Stop listening for new connections. */ event_free(client->listen_event); client->listen_event = NULL; /* * Stop listening for events on the client context. */ event_free(client->read_event); client->read_event = NULL; event_free(client->write_event); client->write_event = NULL; /* * Stop listening to server connections. */ for (server = server_list; server; server = server->next) { if (server->read_event) { event_free(server->read_event); server->read_event = NULL; } if (server->write_event) { event_free(server->write_event); server->write_event = NULL; } } } } /* * Helper functions to send client RPC requests. */ static void send_setclientid_confirm(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; nfs_argop4 op[1]; memset(op, 0, sizeof(op)); op[0].argop = OP_SETCLIENTID_CONFIRM; op[0].nfs_argop4_u.opsetclientid_confirm.clientid = client->clientid; memcpy(op[0].nfs_argop4_u.opsetclientid_confirm.setclientid_confirm, client->setclientid_confirm, NFS4_VERIFIER_SIZE); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 SETCLIENTID_CONFIRM request\n"); exit(10); } } static void send_setclientid(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; nfs_argop4 op[1]; struct sockaddr_storage ss; socklen_t len = sizeof(ss); struct sockaddr_in *in; struct sockaddr_in6 *in6; char *netid; char str[240], addr[256]; unsigned short port; if (getsockname(client->callback_fd, (struct sockaddr *)&ss, &len) < 0) { fprintf(stderr, "getsockaddr failed\n"); exit(10); } switch (ss.ss_family) { case AF_INET: netid = "tcp"; in = (struct sockaddr_in *)&ss; inet_ntop(AF_INET, &in->sin_addr, str, sizeof(str)); port = ntohs(in->sin_port); break; case AF_INET6: netid = "tcp6"; in6 = (struct sockaddr_in6 *)&ss; inet_ntop(AF_INET6, &in6->sin6_addr, str, sizeof(str)); port = ntohs(in6->sin6_port); break; } sprintf(addr, "%s.%d.%d", str, port >> 8, port & 0xff); memset(op, 0, sizeof(op)); op[0].argop = OP_SETCLIENTID; memcpy(op[0].nfs_argop4_u.opsetclientid.client.verifier, client->verifier, sizeof(verifier4)); op[0].nfs_argop4_u.opsetclientid.client.id.id_len = strlen(client->id); op[0].nfs_argop4_u.opsetclientid.client.id.id_val = client->id; op[0].nfs_argop4_u.opsetclientid.callback.cb_program = NFS4_CALLBACK; op[0].nfs_argop4_u.opsetclientid.callback.cb_location.r_netid = netid; op[0].nfs_argop4_u.opsetclientid.callback.cb_location.r_addr = addr; op[0].nfs_argop4_u.opsetclientid.callback_ident = 0x00000001; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 SETCLIENTID request\n"); exit(10); } } static void send_getrootfh(struct rpc_context *rpc, rpc_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[2]; memset(op, 0, sizeof(op)); op[0].argop = OP_PUTROOTFH; op[1].argop = OP_GETFH; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 GETROOTFH request\n"); exit(10); } } static void send_open(struct rpc_context *rpc, nfs_fh4 dir, char *path, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; nfs_argop4 *op; int i = 0, idx = 0; char *tmp; printf("OPEN called\n"); /* * Count how many directories we have in the path. */ tmp = path; while (tmp = strchr(tmp, '/')) { i++; tmp++; } op = malloc(sizeof(nfs_argop4) * (4 + i)); memset(op, 0, sizeof(nfs_argop4) * (4 + i)); op[idx].argop = OP_PUTFH; op[idx].nfs_argop4_u.opputfh.object = dir; idx++; while (i-- > 0) { tmp = strchr(path, '/'); *tmp++ = '\0'; op[idx].argop = OP_LOOKUP; op[idx].nfs_argop4_u.oplookup.objname.utf8string_len = strlen(path); op[idx].nfs_argop4_u.oplookup.objname.utf8string_val = path; idx++; path = tmp; } op[idx].argop = OP_OPEN; op[idx].nfs_argop4_u.opopen.seqid = client->seqid; op[idx].nfs_argop4_u.opopen.share_access = OPEN4_SHARE_ACCESS_READ; op[idx].nfs_argop4_u.opopen.share_deny = OPEN4_SHARE_DENY_NONE; op[idx].nfs_argop4_u.opopen.owner.clientid = client->clientid; op[idx].nfs_argop4_u.opopen.owner.owner.owner_len = strlen(client->owner); op[idx].nfs_argop4_u.opopen.owner.owner.owner_val = client->owner; op[idx].nfs_argop4_u.opopen.openhow.opentype = OPEN4_NOCREATE; op[idx].nfs_argop4_u.opopen.claim.claim = CLAIM_NULL; op[idx].nfs_argop4_u.opopen.claim.open_claim4_u.file.utf8string_len = strlen(path); op[idx].nfs_argop4_u.opopen.claim.open_claim4_u.file.utf8string_val = path; idx++; op[idx].argop = OP_GETFH; idx++; op[idx].argop = OP_ACCESS; op[idx].nfs_argop4_u.opaccess.access = ACCESS4_READ; client->seqid++; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = idx; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 OPEN request\n"); exit(10); } } static void send_open_confirm(struct rpc_context *rpc, nfs_fh4 object, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; nfs_argop4 op[2]; memset(op, 0, sizeof(op)); op[0].argop = OP_PUTFH; op[0].nfs_argop4_u.opputfh.object = object; op[1].argop = OP_OPEN_CONFIRM; op[1].nfs_argop4_u.opopen_confirm.open_stateid.seqid = client->seqid; memcpy(op[1].nfs_argop4_u.opopen_confirm.open_stateid.other, client->stateid.other, 12); op[1].nfs_argop4_u.opopen_confirm.seqid = client->seqid; client->seqid++; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 CLOSE request\n"); exit(10); } } static void send_read(struct rpc_context *rpc, nfs_fh4 object, uint64_t offset, uint32_t count, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; nfs_argop4 op[3]; memset(op, 0, sizeof(op)); op[0].argop = OP_PUTFH; op[0].nfs_argop4_u.opputfh.object = object; op[1].argop = OP_READ; op[1].nfs_argop4_u.opread.stateid.seqid = client->seqid; memcpy(op[1].nfs_argop4_u.opread.stateid.other, client->stateid.other, 12); op[1].nfs_argop4_u.opread.offset = offset; op[1].nfs_argop4_u.opread.count = count; op[2].argop = OP_GETATTR; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 READ request\n"); exit(10); } } static void send_close(struct rpc_context *rpc, nfs_fh4 object, rpc_cb cb, void *private_data) { struct client *client = private_data; COMPOUND4args args; nfs_argop4 op[2]; memset(op, 0, sizeof(op)); op[0].argop = OP_PUTFH; op[0].nfs_argop4_u.opputfh.object = object; op[1].argop = OP_CLOSE; op[1].nfs_argop4_u.opclose.seqid = client->seqid; op[1].nfs_argop4_u.opclose.open_stateid.seqid = client->seqid; memcpy(op[1].nfs_argop4_u.opclose.open_stateid.other, client->stateid.other, 12); client->seqid++; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = sizeof(op) / sizeof(nfs_argop4); args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, cb, &args, private_data) != 0) { fprintf(stderr, "Failed to send nfs4 CLOSE request\n"); exit(10); } } /* * Callbacks for completed requests. */ void close_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; /* * FINISHED */ /* * Note that we can not start tearing down and destroying the contexts * right here as we are still in a callback from ... rpc_service(). * Instead flag that we should abort and start doing the teardown * in client_io once we return from libnfs. */ client->is_finished = 1; } void read_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to read file on server %s\n", client->server); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to read file on server %s\n", client->server); exit(10); } write(1, res->resarray.resarray_val[1].nfs_resop4_u.opread.READ4res_u.resok4.data.data_val, res->resarray.resarray_val[1].nfs_resop4_u.opread.READ4res_u.resok4.data.data_len); /* * Are we at end-of-file? If so we can close the file and exit. */ if (res->resarray.resarray_val[1].nfs_resop4_u.opread.READ4res_u.resok4.eof) { send_close(rpc, client->fh, close_cb, client); return; } /* * We still have more data to read. */ client->offset += res->resarray.resarray_val[1].nfs_resop4_u.opread.READ4res_u.resok4.data.data_len; send_read(rpc, client->fh, client->offset, 4096, read_cb, client); } void open_confirm_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to confirm open file on server %s\n", client->server); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to confirm open file on server %s\n", client->server); exit(10); } send_read(rpc, client->fh, client->offset, 4096, read_cb, client); } void open_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; int idx; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to open file on server %s\n", client->server); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to open file on server %s\n", client->server); exit(10); } /* Find the index for the OPEN opcode */ for (idx = 1; idx < res->resarray.resarray_len - 1; idx++) { if ((res->resarray.resarray_val[idx].resop == OP_OPEN) && (res->resarray.resarray_val[idx + 1].resop == OP_GETFH)) { break; } } if (idx >= res->resarray.resarray_len - 1) { fprintf(stderr, "No OP_OPEN in server response\n"); exit(10); } /* Store the open handle in the client structure */ client->fh.nfs_fh4_len = res->resarray.resarray_val[idx+1].nfs_resop4_u.opgetfh.GETFH4res_u.resok4.object.nfs_fh4_len; client->fh.nfs_fh4_val = malloc(client->fh.nfs_fh4_len); if (client->fh.nfs_fh4_val == NULL) { fprintf(stderr, "Failed to allocate data for nfs_fh4\n"); exit(10); } memcpy(client->fh.nfs_fh4_val, res->resarray.resarray_val[idx+1].nfs_resop4_u.opgetfh.GETFH4res_u.resok4.object.nfs_fh4_val, client->fh.nfs_fh4_len); /* Store stateid for the open handle in the client structure */ client->stateid.seqid = res->resarray.resarray_val[idx].nfs_resop4_u.opopen.OPEN4res_u.resok4.stateid.seqid; memcpy(client->stateid.other, res->resarray.resarray_val[idx].nfs_resop4_u.opopen.OPEN4res_u.resok4.stateid.other, 12); /* Check if server wants us to confirm the open */ if (res->resarray.resarray_val[idx].nfs_resop4_u.opopen.OPEN4res_u.resok4.rflags & OPEN4_RESULT_CONFIRM) { send_open_confirm(rpc, client->fh, open_confirm_cb, client); return; } send_read(rpc, client->fh, client->offset, 4096, read_cb, client); } void getrootfh_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to get root filehandle of server %s\n", client->server); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to get root filehandle of server %s\n", client->server); exit(10); } send_open(rpc, res->resarray.resarray_val[1].nfs_resop4_u.opgetfh.GETFH4res_u.resok4.object, client->path, open_cb, client); } void setclientid_confirm_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; char *path; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to set client id of server %s\n", client->server); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to set client id of server %s\n", client->server); exit(10); } send_getrootfh(rpc, getrootfh_cb, client); } void setclientid_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; COMPOUND4res *res = data; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "Failed to set client id on server %s\n", client->server); exit(10); } if (res->status != NFS4_OK) { fprintf(stderr, "Failed to set client id on server %s\n", client->server); exit(10); } client->clientid = res->resarray.resarray_val[0].nfs_resop4_u.opsetclientid.SETCLIENTID4res_u.resok4.clientid; memcpy(client->setclientid_confirm, res->resarray.resarray_val[0].nfs_resop4_u.opsetclientid.SETCLIENTID4res_u.resok4.setclientid_confirm, NFS4_VERIFIER_SIZE); send_setclientid_confirm(rpc, setclientid_confirm_cb, client); } /* * NULL procedure for the callback protocol. */ static int cb_null_proc(struct rpc_context *rpc, struct rpc_msg *call) { rpc_send_reply(rpc, call, NULL, (zdrproc_t)zdr_void, 0); return 0; } /* * CB_COMPOUND procedure for the callback protocol. * This is where the server will inform us about lease breaks and similar. */ static int cb_compound_proc(struct rpc_context *rpc, struct rpc_msg *call) { CB_COMPOUND4args *args = call->body.cbody.args; fprintf(stderr, "cb_compund_cb. Do something here.\n"); return 0; } struct service_proc pt[] = { {CB_NULL, cb_null_proc, (zdrproc_t)zdr_void, 0}, {CB_COMPOUND, cb_compound_proc, (zdrproc_t)zdr_CB_COMPOUND4args, sizeof(CB_COMPOUND4args)}, }; /* * This callback is invoked when others (the nfsv4 server) initiates a * NFSv4 CALLBACK sessions to us. * We accept() the connection and create a local rpc server context * for the callback protocol. */ static void client_accept(evutil_socket_t s, short events, void *private_data) { struct client *client = private_data; struct server *server; struct sockaddr_storage ss; socklen_t len = sizeof(ss); int fd; server = malloc(sizeof(struct server)); if (server == NULL) { fprintf(stderr, "failed to malloc server structure\n"); exit(10); } memset(server, 0, sizeof(*server)); server->next = server_list; server_list = server; if ((fd = accept(s, (struct sockaddr *)&ss, &len)) < 0) { free_server(server); fprintf(stderr, "accept failed\n"); exit(10); } evutil_make_socket_nonblocking(fd); server->rpc = rpc_init_server_context(fd); if (server->rpc == NULL) { free_server(server); fprintf(stderr, "Failed to create server rpc context\n"); exit(10); } rpc_register_service(server->rpc, NFS4_CALLBACK, NFS_CB, pt, sizeof(pt) / sizeof(pt[0])); server->read_event = event_new(base, fd, EV_READ|EV_PERSIST, server_io, server); server->write_event = event_new(base, fd, EV_WRITE|EV_PERSIST, server_io, server); update_events(server->rpc, server->read_event, server->write_event); } /* * This callback is invoked when our async connect() to the server has * completed. At this point we know which IP address was used locally for * the connection and can bind our nfsv4 callback server instance to it. */ void connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { struct client *client = private_data; struct sockaddr_storage ss; socklen_t len = sizeof(ss); struct sockaddr_in *in; struct sockaddr_in6 *in6; if (status != RPC_STATUS_SUCCESS) { fprintf(stderr, "connection to NFSv4 server %s failed\n", client->server); exit(10); } /* * NFSv4 CALLBACK * Now that we have a client connection we can register a callback * server port on the same IP address as was used to the outgoing * client connection. That way we know that the address used by the * server is routable, and uses the same version of ip, that the client * supports and can route to. */ if (getsockname(rpc_get_fd(rpc), (struct sockaddr *)&ss, &len) < 0) { fprintf(stderr, "getsockaddr failed\n"); exit(10); } switch (ss.ss_family) { case AF_INET: in = (struct sockaddr_in *)&ss; in->sin_port=0; break; case AF_INET6: in6 = (struct sockaddr_in6 *)&ss; in6->sin6_port=0; break; default: fprintf(stderr, "Can not handle AF_FAMILY:%d", ss.ss_family); exit(10); } client->callback_fd = socket(AF_INET, SOCK_STREAM, 0); if (client->callback_fd == -1) { fprintf(stderr, "Failed to create callback socket\n"); exit(10); } evutil_make_socket_nonblocking(client->callback_fd); if (bind(client->callback_fd, (struct sockaddr *)&ss, sizeof(ss)) < 0) { fprintf(stderr, "Failed to bind callback socket\n"); exit(10); } if (listen(client->callback_fd, 16) < 0) { fprintf(stderr, "failed to listen to callback socket\n"); exit(10); } client->listen_event = event_new(base, client->callback_fd, EV_READ|EV_PERSIST, client_accept, private_data); event_add(client->listen_event, NULL); /* * Now that we are finished setting up the callback server port * we can proceed and negotiate the nfsv4 client id. */ send_setclientid(rpc, setclientid_cb, client); } int main(int argc, char *argv[]) { struct nfs_context *nfs; struct nfs_url *url; struct client client; int i, fd; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { fprintf(stderr, "Failed to start Winsock2\n"); exit(10); } #endif #ifdef AROS aros_init_socket(); #endif if (argc < 2) { usage(); } base = event_base_new(); if (base == NULL) { fprintf(stderr, "Failed create event context\n"); exit(10); } nfs = nfs_init_context(); if (nfs == NULL) { fprintf(stderr, "failed to init context\n"); exit(10); } url = nfs_parse_url_dir(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "failed to parse url\n"); exit(10); } memset(&client, 0, sizeof(client)); client.rpc = nfs_get_rpc_context(nfs); client.is_finished = 0; client.server = url->server; client.path = &url->path[1]; // skip leading '/' srandom(time(NULL)); for (i = 0; i < NFS4_VERIFIER_SIZE; i++) { client.verifier[i] = random() & 0xff; } asprintf(&client.id, "Libnfs %s tcp pid:%d", argv[1], getpid()); asprintf(&client.owner, "open id:libnfs pid:%d", getpid()); client.callback_fd = -1; if (rpc_connect_program_async(client.rpc, url->server, NFS4_PROGRAM, NFS_V4, connect_cb, &client) != 0) { fprintf(stderr, "Failed to start connection\n"); exit(10); } /* * Set up the events we need for the outgoing client RPC channel. */ fd = rpc_get_fd(client.rpc); client.read_event = event_new(base, fd, EV_READ|EV_PERSIST, client_io, &client); client.write_event = event_new(base, fd, EV_WRITE|EV_PERSIST, client_io, &client); update_events(client.rpc, client.read_event, client.write_event); /* * Main event loop. */ event_base_dispatch(base); /* * Finished cleanly, lets deallocate all resrouces we were using. */ /* * Close the listening socket. */ close(client.callback_fd); /* * Destroy the client context. */ free(client.id); free(client.owner); free(client.fh.nfs_fh4_val); /* * Destroy all server contexts */ while (server_list) { struct server *server = server_list; server_list = server->next; free_server(server); } nfs_destroy_url(url); /* * This will implicitly close the rpc context and also destroy it. */ nfs_destroy_context(nfs); event_base_free(base); return 0; } libnfs-libnfs-4.0.0/examples/nfsclient-async.c000066400000000000000000000164531343063627400213460ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ /* Example program using the highlevel async interface. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #else #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #define SERVER "10.1.1.27" #define EXPORT "/VIRTUAL" #define NFSFILE "/BOOKS/Classics/Dracula.djvu" #define NFSDIR "/BOOKS/Classics/" #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" struct rpc_context *mount_context; struct client { char *server; char *export; uint32_t mount_port; struct nfsfh *nfsfh; int is_finished; }; void mount_export_cb(struct rpc_context *mount_context, int status, void *data, void *private_data) { struct client *client = private_data; exports export = *(exports *)data; if (status < 0) { printf("MOUNT/EXPORT failed with \"%s\"\n", rpc_get_error(mount_context)); exit(10); } printf("Got exports list from server %s\n", client->server); while (export != NULL) { printf("Export: %s\n", export->ex_dir); export = export->ex_next; } mount_context = NULL; client->is_finished = 1; } void nfs_opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct client *client = private_data; struct nfsdir *nfsdir = data; struct nfsdirent *nfsdirent; if (status < 0) { printf("opendir failed with \"%s\"\n", (char *)data); exit(10); } printf("opendir successful\n"); while((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) { printf("Inode:%d Name:%s\n", (int)nfsdirent->inode, nfsdirent->name); } nfs_closedir(nfs, nfsdir); mount_context = rpc_init_context(); if (mount_getexports_async(mount_context, client->server, mount_export_cb, client) != 0) { printf("Failed to start MOUNT/EXPORT\n"); exit(10); } } void nfs_close_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct client *client = private_data; if (status < 0) { printf("close failed with \"%s\"\n", (char *)data); exit(10); } printf("close successful\n"); printf("call opendir(%s)\n", NFSDIR); if (nfs_opendir_async(nfs, NFSDIR, nfs_opendir_cb, client) != 0) { printf("Failed to start async nfs close\n"); exit(10); } } void nfs_fstat64_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct client *client = private_data; struct nfs_stat_64 *st; if (status < 0) { printf("fstat call failed with \"%s\"\n", (char *)data); exit(10); } printf("Got reply from server for fstat(%s).\n", NFSFILE); st = (struct nfs_stat_64 *)data; printf("Mode %04o\n", (int)st->nfs_mode); printf("Size %d\n", (int)st->nfs_size); printf("Inode %04o\n", (int)st->nfs_ino); printf("Close file\n"); if (nfs_close_async(nfs, client->nfsfh, nfs_close_cb, client) != 0) { printf("Failed to start async nfs close\n"); exit(10); } } void nfs_read_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct client *client = private_data; char *read_data; int i; if (status < 0) { printf("read failed with \"%s\"\n", (char *)data); exit(10); } printf("read successful with %d bytes of data\n", status); read_data = data; for (i=0;i<16;i++) { printf("%02x ", read_data[i]&0xff); } printf("\n"); printf("Fstat file :%s\n", NFSFILE); if (nfs_fstat64_async(nfs, client->nfsfh, nfs_fstat64_cb, client) != 0) { printf("Failed to start async nfs fstat\n"); exit(10); } } void nfs_open_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct client *client = private_data; struct nfsfh *nfsfh; if (status < 0) { printf("open call failed with \"%s\"\n", (char *)data); exit(10); } nfsfh = data; client->nfsfh = nfsfh; printf("Got reply from server for open(%s). Handle:%p\n", NFSFILE, data); printf("Read first 64 bytes\n"); if (nfs_pread_async(nfs, nfsfh, 0, 64, nfs_read_cb, client) != 0) { printf("Failed to start async nfs open\n"); exit(10); } } void nfs_stat64_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct client *client = private_data; struct nfs_stat_64 *st; if (status < 0) { printf("stat call failed with \"%s\"\n", (char *)data); exit(10); } printf("Got reply from server for stat(%s).\n", NFSFILE); st = (struct nfs_stat_64 *)data; printf("Mode %04o\n", (unsigned int) st->nfs_mode); printf("Size %d\n", (int)st->nfs_size); printf("Inode %04o\n", (int)st->nfs_ino); printf("Open file for reading :%s\n", NFSFILE); if (nfs_open_async(nfs, NFSFILE, O_RDONLY, nfs_open_cb, client) != 0) { printf("Failed to start async nfs open\n"); exit(10); } } void nfs_mount_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct client *client = private_data; if (status < 0) { printf("mount/mnt call failed with \"%s\"\n", (char *)data); exit(10); } printf("Got reply from server for MOUNT/MNT procedure.\n"); printf("Stat file :%s\n", NFSFILE); if (nfs_stat64_async(nfs, NFSFILE, nfs_stat64_cb, client) != 0) { printf("Failed to start async nfs stat\n"); exit(10); } } int main(int argc _U_, char *argv[] _U_) { struct nfs_context *nfs; int ret; struct client client; struct pollfd pfds[2]; /* nfs:0 mount:1 */ #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif client.server = SERVER; client.export = EXPORT; client.is_finished = 0; nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(10); } ret = nfs_mount_async(nfs, client.server, client.export, nfs_mount_cb, &client); if (ret != 0) { printf("Failed to start async nfs mount\n"); exit(10); } for (;;) { int num_fds; pfds[0].fd = nfs_get_fd(nfs); pfds[0].events = nfs_which_events(nfs); num_fds = 1; if (mount_context != 0 && rpc_get_fd(mount_context) != -1) { pfds[1].fd = rpc_get_fd(mount_context); pfds[1].events = rpc_which_events(mount_context); num_fds = 2; } if (poll(&pfds[0], 2, -1) < 0) { printf("Poll failed"); exit(10); } if (mount_context != NULL) { if (rpc_service(mount_context, pfds[1].revents) < 0) { printf("rpc_service failed\n"); break; } } if (nfs_service(nfs, pfds[0].revents) < 0) { printf("nfs_service failed\n"); break; } if (client.is_finished) { break; } } nfs_destroy_context(nfs); if (mount_context != NULL) { rpc_destroy_context(mount_context); mount_context = NULL; } printf("nfsclient finished\n"); return 0; } libnfs-libnfs-4.0.0/examples/nfsclient-bcast.c000066400000000000000000000133741343063627400213240ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2011 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ /* Example program using the lowlevel raw broadcast interface. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_NET_IF_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-mount.h" #include "libnfs-raw-portmap.h" struct nfs_list_data { int status; struct nfs_server_list *srvrs; }; void free_nfs_srvr_list(struct nfs_server_list *srv) { while (srv != NULL) { struct nfs_server_list *next = srv->next; free(srv->addr); free(srv); srv = next; } } void pm_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { struct nfs_list_data *srv_data = private_data; struct sockaddr *sin; char hostdd[16]; struct nfs_server_list *srvr; if (status == RPC_STATUS_CANCEL) { return; } if (status != 0) { srv_data->status = -1; return; } sin = rpc_get_recv_sockaddr(rpc); if (sin == NULL) { rpc_set_error(rpc, "failed to get sockaddr in CALLIT callback"); srv_data->status = -1; return; } if (getnameinfo(sin, sizeof(struct sockaddr_in), &hostdd[0], sizeof(hostdd), NULL, 0, NI_NUMERICHOST) < 0) { rpc_set_error(rpc, "getnameinfo failed in CALLIT callback"); srv_data->status = -1; return; } srvr = malloc(sizeof(struct nfs_server_list)); if (srvr == NULL) { rpc_set_error(rpc, "Malloc failed when allocating server structure"); srv_data->status = -1; return; } srvr->addr = strdup(hostdd); if (srvr->addr == NULL) { rpc_set_error(rpc, "Strdup failed when allocating server structure"); free(srvr); srv_data->status = -1; return; } srvr->next = srv_data->srvrs; srv_data->srvrs = srvr; } int main(int argc _U_, char *argv[] _U_) { struct rpc_context *rpc; struct pollfd pfd; struct ifconf ifc; int size; struct timeval tv_start, tv_current; struct nfs_list_data data = {0, NULL}; struct nfs_server_list *srvr; char *ptr; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif rpc = rpc_init_udp_context(); if (rpc == NULL) { printf("failed to init context\n"); exit(10); } if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) { printf("failed to bind to udp %s\n", rpc_get_error(rpc)); exit(10); } /* get list of all interfaces */ size = sizeof(struct ifreq); ifc.ifc_buf = NULL; ifc.ifc_len = size; while(ifc.ifc_len > (size - sizeof(struct ifreq))) { size *= 2; free(ifc.ifc_buf); ifc.ifc_len = size; ifc.ifc_buf = malloc(size); memset(ifc.ifc_buf, 0, size); if (ioctl(rpc_get_fd(rpc), SIOCGIFCONF, (caddr_t)&ifc) < 0) { printf("ioctl SIOCGIFCONF failed\n"); exit(10); } } for (ptr =(char *)ifc.ifc_buf; ptr < ((char *)ifc.ifc_buf) + ifc.ifc_len; ) { struct ifreq *ifr; char bcdd[16]; ifr = (struct ifreq *)ptr; #ifdef HAVE_SOCKADDR_LEN if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) { ptr += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len; } else { ptr += sizeof(ifr->ifr_name) + sizeof(struct sockaddr); } #else ptr += sizeof(struct ifreq); #endif if (ifr->ifr_addr.sa_family != AF_INET) { continue; } if (ioctl(rpc_get_fd(rpc), SIOCGIFFLAGS, ifr) < 0) { printf("ioctl DRBADDR failed\n"); exit(10); } if (!(ifr->ifr_flags & IFF_UP)) { continue; } if (ifr->ifr_flags & IFF_LOOPBACK) { continue; } if (!(ifr->ifr_flags & IFF_BROADCAST)) { continue; } if (ioctl(rpc_get_fd(rpc), SIOCGIFBRDADDR, ifr) < 0) { continue; } if (getnameinfo(&ifr->ifr_broadaddr, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) { continue; } if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) { printf("failed to set udp destination %s\n", rpc_get_error(rpc)); exit(10); } if (rpc_pmap2_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, pm_cb, &data) < 0) { printf("Failed to set up callit function\n"); exit(10); } } free(ifc.ifc_buf); gettimeofday(&tv_start, NULL); for(;;) { int mpt; pfd.fd = rpc_get_fd(rpc); pfd.events = rpc_which_events(rpc); gettimeofday(&tv_current, NULL); mpt = 1000 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000) + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000); if (poll(&pfd, 1, mpt) < 0) { printf("Poll failed"); exit(10); } if (pfd.revents == 0) { break; } if (rpc_service(rpc, pfd.revents) < 0) { printf("rpc_service failed with %s\n", rpc_get_error(rpc)); break; } } for (srvr=data.srvrs; srvr; srvr = srvr->next) { printf("NFS SERVER @ %s\n", srvr->addr); } free_nfs_srvr_list(data.srvrs); rpc_destroy_context(rpc); rpc=NULL; return 0; } libnfs-libnfs-4.0.0/examples/nfsclient-listservers.c000066400000000000000000000026511343063627400226110ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2011 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ /* Example program showing sync interface to probe for all local servers */ #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #endif #include #include #include "libnfs.h" int main(int argc _U_, char *argv[] _U_) { struct nfs_server_list *srvrs; struct nfs_server_list *srv; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif #ifdef AROS aros_init_socket(); #endif srvrs = nfs_find_local_servers(); for (srv=srvrs; srv; srv = srv->next) { printf("NFS SERVER @ %s\n", srv->addr); } free_nfs_srvr_list(srvrs); return 0; } libnfs-libnfs-4.0.0/examples/nfsclient-raw.c000066400000000000000000000325571343063627400210250ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ /* Example program using the lowlevel raw interface. * This allow accurate control of the exact commands that are being used. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #endif #define SERVER "10.1.1.27" #define EXPORT "/shared" #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" #include "libnfs-raw-nfs.h" #include "libnfs-raw-portmap.h" #include "libnfs-raw-rquota.h" struct client { char *server; char *export; uint32_t mount_port; uint32_t rquota_port; int is_finished; struct nfs_fh3 rootfh; }; void rquota_getquota_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data) { struct client *client = private_data; // GETQUOTA1res *res = data; if (status == RPC_STATUS_ERROR) { printf("rquota/getquota call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("rquota/getquota call to server %s failed, status:%d\n", client->server, status); exit(10); } printf("rquota responded ok\n"); client->is_finished = 1; } void rquota_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { struct client *client = private_data; if (status != RPC_STATUS_SUCCESS) { printf("connection to RPC.RQUOTAD on server %s failed\n", client->server); exit(10); } printf("Connected to RPC.RQUOTAD on %s:%d\n", client->server, client->rquota_port); printf("Send GETQUOTA request for uid 100\n"); if (rpc_rquota1_getquota_async(rpc, rquota_getquota_cb, EXPORT, 100, client) != 0) { printf("Failed to send getquota request\n"); exit(10); } } void acl_getacl_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data) { struct client *client = private_data; GETACL3res *res = data; printf("Got NFSACL/GETACL reply\n"); if (status == RPC_STATUS_SUCCESS) { printf("Got an ACL : ACL status:%d\n", res->status); if (res->status == NFS3_OK) { int i; printf("ACL MASK 0x%08x\n", res->GETACL3res_u.resok.mask); printf("NUM ACE %d\n", res->GETACL3res_u.resok.ace_count); for (i=0; iGETACL3res_u.resok.ace.ace_len; i++) { printf("Type:0x%08x\n", res->GETACL3res_u.resok.ace.ace_val[i].type); printf("ID:%d\n", res->GETACL3res_u.resok.ace.ace_val[i].id); printf("Perm:0x%08x\n", res->GETACL3res_u.resok.ace.ace_val[i].perm); } } } printf("Disconnect socket from nfs server\n"); if (rpc_disconnect(rpc, "normal disconnect") != 0) { printf("Failed to disconnect socket to nfs\n"); exit(10); } printf("Connect to RPC.RQUOTAD on %s:%d\n", client->server, client->rquota_port); if (rpc_connect_async(rpc, client->server, client->rquota_port, rquota_connect_cb, client) != 0) { printf("Failed to start connection\n"); exit(10); } } void acl_null_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data) { struct client *client = private_data; GETACL3args args; printf("Got NFSACL/NULL reply\n"); printf("Get ACL for root handle\n"); args.dir = client->rootfh; args.mask = NFSACL_MASK_ACL_ENTRY|NFSACL_MASK_ACL_COUNT|NFSACL_MASK_ACL_DEFAULT_ENTRY|NFSACL_MASK_ACL_DEFAULT_COUNT; if (rpc_nfsacl_getacl_async(rpc, acl_getacl_cb, &args, client) != 0) { printf("Failed to send getacl request\n"); exit(10); } } void nfs_fsinfo_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data) { struct client *client = private_data; FSINFO3res *res = data; if (status == RPC_STATUS_ERROR) { printf("nfs/fsinfo call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("nfs/fsinfo call to server %s failed, status:%d\n", client->server, status); exit(10); } printf("Got reply from server for NFS/FSINFO procedure.\n"); printf("Read Max:%d\n", (int)res->FSINFO3res_u.resok.rtmax); printf("Write Max:%d\n", (int)res->FSINFO3res_u.resok.wtmax); printf("Send NFSACL/NULL request\n"); if (rpc_nfsacl_null_async(rpc, acl_null_cb, client) != 0) { printf("Failed to send acl/null request\n"); exit(10); } } void nfs_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { struct client *client = private_data; struct FSINFO3args args; if (status != RPC_STATUS_SUCCESS) { printf("connection to RPC.MOUNTD on server %s failed\n", client->server); exit(10); } printf("Connected to RPC.NFSD on %s:%d\n", client->server, client->mount_port); printf("Send FSINFO request\n"); args.fsroot = client->rootfh; if (rpc_nfs3_fsinfo_async(rpc, nfs_fsinfo_cb, &args, client) != 0) { printf("Failed to send fsinfo request\n"); exit(10); } } void mount_mnt_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; mountres3 *mnt = data; if (status == RPC_STATUS_ERROR) { printf("mount/mnt call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("mount/mnt call to server %s failed, status:%d\n", client->server, status); exit(10); } printf("Got reply from server for MOUNT/MNT procedure.\n"); client->rootfh.data.data_len = mnt->mountres3_u.mountinfo.fhandle.fhandle3_len; client->rootfh.data.data_val = malloc(client->rootfh.data.data_len); memcpy(client->rootfh.data.data_val, mnt->mountres3_u.mountinfo.fhandle.fhandle3_val, client->rootfh.data.data_len); printf("Disconnect socket from mountd server\n"); if (rpc_disconnect(rpc, "normal disconnect") != 0) { printf("Failed to disconnect socket to mountd\n"); exit(10); } printf("Connect to RPC.NFSD on %s:%d\n", client->server, 2049); if (rpc_connect_async(rpc, client->server, 2049, nfs_connect_cb, client) != 0) { printf("Failed to start connection\n"); exit(10); } } void mount_export_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; exports export = *(exports *)data; if (status == RPC_STATUS_ERROR) { printf("mount null call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("mount null call to server %s failed, status:%d\n", client->server, status); exit(10); } printf("Got reply from server for MOUNT/EXPORT procedure.\n"); while (export != NULL) { printf("Export: %s\n", export->ex_dir); export = export->ex_next; } printf("Send MOUNT/MNT command for %s\n", client->export); if (rpc_mount_mnt_async(rpc, mount_mnt_cb, client->export, client) != 0) { printf("Failed to send mnt request\n"); exit(10); } } void mount_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; if (status == RPC_STATUS_ERROR) { printf("mount null call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("mount null call to server %s failed, status:%d\n", client->server, status); exit(10); } printf("Got reply from server for MOUNT/NULL procedure.\n"); printf("Send MOUNT/EXPORT command\n"); if (rpc_mount_export_async(rpc, mount_export_cb, client) != 0) { printf("Failed to send export request\n"); exit(10); } } void mount_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { struct client *client = private_data; if (status != RPC_STATUS_SUCCESS) { printf("connection to RPC.MOUNTD on server %s failed\n", client->server); exit(10); } printf("Connected to RPC.MOUNTD on %s:%d\n", client->server, client->mount_port); printf("Send NULL request to check if RPC.MOUNTD is actually running\n"); if (rpc_mount_null_async(rpc, mount_null_cb, client) != 0) { printf("Failed to send null request\n"); exit(10); } } void pmap_getport2_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; if (status == RPC_STATUS_ERROR) { printf("portmapper getport call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("portmapper getport call to server %s failed, status:%d\n", client->server, status); exit(10); } client->mount_port = *(uint32_t *)data; printf("GETPORT returned RPC.MOUNTD is on port:%d\n", client->mount_port); if (client->mount_port == 0) { printf("RPC.MOUNTD is not available on server : %s:%d\n", client->server, client->mount_port); exit(10); } printf("Disconnect socket from portmap server\n"); if (rpc_disconnect(rpc, "normal disconnect") != 0) { printf("Failed to disconnect socket to portmapper\n"); exit(10); } printf("Connect to RPC.MOUNTD on %s:%d\n", client->server, client->mount_port); if (rpc_connect_async(rpc, client->server, client->mount_port, mount_connect_cb, client) != 0) { printf("Failed to start connection\n"); exit(10); } } void pmap_getport1_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; if (status == RPC_STATUS_ERROR) { printf("portmapper getport call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("portmapper getport call to server %s failed, status:%d\n", client->server, status); exit(10); } client->rquota_port = *(uint32_t *)data; printf("GETPORT returned RPC.RQUOTAD on port:%d\n", client->rquota_port); if (client->rquota_port == 0) { printf("RPC.RQUOTAD is not available on server : %s:%d\n", client->server, client->rquota_port); // exit(10); } printf("Send getport request asking for MOUNT port\n"); if (rpc_pmap2_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, pmap_getport2_cb, client) != 0) { printf("Failed to send getport request\n"); exit(10); } } void pmap_dump_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; struct pmap2_dump_result *dr = data; struct pmap2_mapping_list *list = dr->list; if (status == RPC_STATUS_ERROR) { printf("portmapper null call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("portmapper null call to server %s failed, status:%d\n", client->server, status); exit(10); } printf("Got reply from server for PORTMAP/DUMP procedure.\n"); while (list) { printf("Prog:%d Vers:%d Protocol:%d Port:%d\n", list->map.prog, list->map.vers, list->map.prot, list->map.port); list = list->next; } printf("Send getport request asking for MOUNT port\n"); if (rpc_pmap2_getport_async(rpc, RQUOTA_PROGRAM, RQUOTA_V1, IPPROTO_TCP, pmap_getport1_cb, client) != 0) { printf("Failed to send getport request\n"); exit(10); } } void pmap_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; if (status == RPC_STATUS_ERROR) { printf("portmapper null call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("portmapper null call to server %s failed, status:%d\n", client->server, status); exit(10); } printf("Got reply from server for PORTMAP/NULL procedure.\n"); printf("Send PMAP/DUMP command\n"); if (rpc_pmap2_dump_async(rpc, pmap_dump_cb, client) != 0) { printf("Failed to send getport request\n"); exit(10); } } void pmap_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { struct client *client = private_data; printf("pmap_connect_cb status:%d.\n", status); if (status != RPC_STATUS_SUCCESS) { printf("connection to portmapper on server %s failed\n", client->server); exit(10); } printf("Send NULL request to check if portmapper is actually running\n"); if (rpc_pmap2_null_async(rpc, pmap_null_cb, client) != 0) { printf("Failed to send null request\n"); exit(10); } } int main(int argc _U_, char *argv[] _U_) { struct rpc_context *rpc; struct pollfd pfd; struct client client; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif rpc = rpc_init_context(); if (rpc == NULL) { printf("failed to init context\n"); exit(10); } client.server = SERVER; client.export = EXPORT; client.is_finished = 0; if (rpc_connect_async(rpc, client.server, 111, pmap_connect_cb, &client) != 0) { printf("Failed to start connection\n"); exit(10); } for (;;) { pfd.fd = rpc_get_fd(rpc); pfd.events = rpc_which_events(rpc); if (poll(&pfd, 1, -1) < 0) { printf("Poll failed"); exit(10); } if (rpc_service(rpc, pfd.revents) < 0) { printf("rpc_service failed\n"); break; } if (client.is_finished) { break; } } rpc_destroy_context(rpc); rpc=NULL; printf("nfsclient finished\n"); return 0; } libnfs-libnfs-4.0.0/examples/nfsclient-sync.c000066400000000000000000000114121343063627400211730ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE /* Example program using the highlevel sync interface */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #define PRId64 "ll" #else #include #include #include #ifndef AROS #include #endif #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" struct client { char *server; char *export; uint32_t mount_port; int is_finished; }; char buf[3*1024*1024+337]; void print_usage(void) { fprintf(stderr, "Usage: nfsclient-sync [-?|--help] [--usage] \n"); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; int i, ret, res; uint64_t offset; struct client client; struct nfs_stat_64 st; struct nfsfh *nfsfh; struct nfsdir *nfsdir; struct nfsdirent *nfsdirent; struct statvfs svfs; exports export, tmp; const char *url = NULL; char *server = NULL, *path = NULL, *strp; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif #ifdef AROS aros_init_socket(); #endif url = argv[1]; if (url == NULL) { fprintf(stderr, "No URL specified.\n"); print_usage(); exit(0); } if (strncmp(url, "nfs://", 6)) { fprintf(stderr, "Invalid URL specified.\n"); print_usage(); exit(0); } server = strdup(url + 6); if (server == NULL) { fprintf(stderr, "Failed to strdup server string\n"); exit(10); } if (server[0] == '/' || server[0] == '\0') { fprintf(stderr, "Invalid server string.\n"); free(server); exit(10); } strp = strchr(server, '/'); if (strp == NULL) { fprintf(stderr, "Invalid URL specified.\n"); print_usage(); free(server); exit(0); } path = strdup(strp); if (path == NULL) { fprintf(stderr, "Failed to strdup server string\n"); free(server); exit(10); } if (path[0] != '/') { fprintf(stderr, "Invalid path.\n"); free(server); free(path); exit(10); } *strp = 0; client.server = server; client.export = path; client.is_finished = 0; nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); goto finished; } ret = nfs_mount(nfs, client.server, client.export); if (ret != 0) { printf("Failed to mount nfs share : %s\n", nfs_get_error(nfs)); goto finished; } ret = nfs_opendir(nfs, "/", &nfsdir); if (ret != 0) { printf("Failed to opendir(\"/\") %s\n", nfs_get_error(nfs)); exit(10); } while((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) { char path[1024]; if (!strcmp(nfsdirent->name, ".") || !strcmp(nfsdirent->name, "..")) { continue; } sprintf(path, "%s/%s", "/", nfsdirent->name); ret = nfs_stat64(nfs, path, &st); if (ret != 0) { fprintf(stderr, "Failed to stat(%s) %s\n", path, nfs_get_error(nfs)); continue; } switch (st.nfs_mode & S_IFMT) { #ifndef WIN32 case S_IFLNK: #endif case S_IFREG: printf("-"); break; case S_IFDIR: printf("d"); break; case S_IFCHR: printf("c"); break; case S_IFBLK: printf("b"); break; } printf("%c%c%c", "-r"[!!(st.nfs_mode & S_IRUSR)], "-w"[!!(st.nfs_mode & S_IWUSR)], "-x"[!!(st.nfs_mode & S_IXUSR)] ); printf("%c%c%c", "-r"[!!(st.nfs_mode & S_IRGRP)], "-w"[!!(st.nfs_mode & S_IWGRP)], "-x"[!!(st.nfs_mode & S_IXGRP)] ); printf("%c%c%c", "-r"[!!(st.nfs_mode & S_IROTH)], "-w"[!!(st.nfs_mode & S_IWOTH)], "-x"[!!(st.nfs_mode & S_IXOTH)] ); printf(" %2d", (int)st.nfs_nlink); printf(" %5d", (int)st.nfs_uid); printf(" %5d", (int)st.nfs_gid); printf(" %12" PRId64, st.nfs_size); printf(" %s\n", nfsdirent->name); } nfs_closedir(nfs, nfsdir); finished: free(server); free(path); if (nfs != NULL) { nfs_destroy_context(nfs); } return 0; } libnfs-libnfs-4.0.0/examples/portmap-client.c000066400000000000000000000336651343063627400212100ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2014 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ /* Example program using the lowlevel raw interface. * This allow accurate control of the exact commands that are being used. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #include #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" #include "libnfs-raw-nfs.h" #include "libnfs-raw-portmap.h" #include "libnfs-raw-rquota.h" struct client { int is_finished; }; void pmap2_dump_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; struct pmap2_dump_result *dr = data; struct pmap2_mapping_list *list = dr->list; if (status == RPC_STATUS_ERROR) { printf("PORTMAP2/DUMP call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP2/DUMP call failed, status:%d\n", status); exit(10); } printf("PORTMAP2/DUMP:\n"); while (list) { printf(" Prog:%d Vers:%d Protocol:%d Port:%d\n", list->map.prog, list->map.vers, list->map.prot, list->map.port); list = list->next; } client->is_finished = 1; } void pmap3_dump_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; struct pmap3_dump_result *dr = data; struct pmap3_mapping_list *list = dr->list; if (status == RPC_STATUS_ERROR) { printf("PORTMAP3/DUMP call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP3/DUMP call failed, status:%d\n", status); exit(10); } printf("PORTMAP3/DUMP:\n"); while (list) { printf(" Prog:%d Vers:%d Netid:%s Addr:%s Owner:%s\n", list->map.prog, list->map.vers, list->map.netid, list->map.addr, list->map.owner); list = list->next; } client->is_finished = 1; } void pmap3_getaddr_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; struct pmap3_string_result *gar = data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP3/GETADDR call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP3/GETADDR call failed, status:%d\n", status); exit(10); } printf("PORTMAP3/GETADDR:\n"); printf(" Addr:%s\n", gar->addr); client->is_finished = 1; } void pmap2_set_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; uint32_t res = *(uint32_t *)data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP2/SET call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP2/SET call failed, status:%d\n", status); exit(10); } printf("PORTMAP2/SET:\n"); printf(" Res:%d\n", res); client->is_finished = 1; } void pmap2_unset_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; uint32_t res = *(uint32_t *)data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP2/UNSET call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP2/UNSET call failed, status:%d\n", status); exit(10); } printf("PORTMAP2/UNSET:\n"); printf(" Res:%d\n", res); client->is_finished = 1; } void pmap3_set_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; uint32_t res = *(uint32_t *)data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP3/SET call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP3/SET call failed, status:%d\n", status); exit(10); } printf("PORTMAP3/SET:\n"); printf(" Res:%d\n", res); client->is_finished = 1; } void pmap3_unset_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; uint32_t res = *(uint32_t *)data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP3/UNSET call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP3/UNSET call failed, status:%d\n", status); exit(10); } printf("PORTMAP3/UNSET:\n"); printf(" Res:%d\n", res); client->is_finished = 1; } void pmap3_gettime_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; time_t t = *(uint32_t *)data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP3/GETTIME call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP3/GETTIME call failed, status:%d\n", status); exit(10); } printf("PORTMAP3/GETTIME:\n"); printf(" Time:%d %s\n", (int)t, ctime(&t)); client->is_finished = 1; } void pmap3_uaddr2taddr_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; struct pmap3_netbuf *nb = data; struct sockaddr_storage *ss; char host[256], port[6]; int i; if (status == RPC_STATUS_ERROR) { printf("PORTMAP3/UADDR2TADDR call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP3/UADDR2TADDR call failed, status:%d\n", status); exit(10); } printf("PORTMAP3/UADDR2TADDR:\n"); printf(" MaxLen:%d\n", nb->maxlen); printf(" "); for (i = 0; i < nb->maxlen; i++) { printf("%02x ", nb->buf.buf_val[i]); if (i %16 == 15) { printf("\n "); } } printf("\n"); printf(" ---\n"); ss = (struct sockaddr_storage *)&nb->buf.buf_val[0]; getnameinfo((struct sockaddr *)ss, sizeof(struct sockaddr_storage), &host[0], sizeof(host), &port[0], sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV); switch (ss->ss_family) { case AF_INET: printf(" IPv4: %s:%s\n", &host[0], &port[0]); break; case AF_INET6: printf(" IPv6: %s:%s\n", &host[0], &port[0]); break; } client->is_finished = 1; } void pmap2_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP2/NULL call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP2/NULL call failed, status:%d\n", status); exit(10); } printf("PORTMAP2/NULL responded and server is alive\n"); client->is_finished = 1; } void pmap3_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP3/NULL call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP3/NULL call failed, status:%d\n", status); exit(10); } printf("PORTMAP3/NULL responded and server is alive\n"); client->is_finished = 1; } void pmap_null_cb(struct rpc_context *rpc, int status, void *data, void *private_data) { struct client *client = private_data; if (status == RPC_STATUS_ERROR) { printf("PORTMAP/NULL call failed with \"%s\"\n", (char *)data); exit(10); } if (status != RPC_STATUS_SUCCESS) { printf("PORTMAP/NULL call failed, status:%d\n", status); exit(10); } client->is_finished = 1; } void pmap_connect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { struct client *client = private_data; if (status != RPC_STATUS_SUCCESS) { printf("connection to portmapper failed\n"); exit(10); } if (rpc_pmap2_null_async(rpc, pmap_null_cb, client) != 0) { printf("Failed to send null request\n"); exit(10); } } static void wait_until_finished(struct rpc_context *rpc, struct client *client) { struct pollfd pfd; client->is_finished = 0; for (;;) { pfd.fd = rpc_get_fd(rpc); pfd.events = rpc_which_events(rpc); if (poll(&pfd, 1, -1) < 0) { printf("Poll failed"); exit(10); } if (rpc_service(rpc, pfd.revents) < 0) { printf("rpc_service failed\n"); break; } if (client->is_finished) { break; } } } int main(int argc _U_, char *argv[] _U_) { struct rpc_context *rpc; struct client client; char *server = NULL; int i; int null2 = 0; int dump2 = 0; int null3 = 0; int set2 = 0; int unset2 = 0; int set3 = 0; int unset3 = 0; int getaddr3 = 0; int dump3 = 0; int gettime3 = 0; int u2t3 = 0; int command_found = 0; int set2prog, set2vers, set2prot, set2port; int unset2prog, unset2vers, unset2prot, unset2port; int set3prog, set3vers; char *set3netid, *set3addr, *set3owner; int unset3prog, unset3vers; char *unset3netid, *unset3addr, *unset3owner; int getaddr3prog, getaddr3vers; char *getaddr3netid, *getaddr3addr, *getaddr3owner; char *u2t3string; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif rpc = rpc_init_context(); if (rpc == NULL) { printf("failed to init context\n"); exit(10); } for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "dump2")) { dump2 = 1; command_found++; } else if (!strcmp(argv[i], "null2")) { null2 = 1; command_found++; } else if (!strcmp(argv[i], "set2")) { set2 = 1; set2prog = atoi(argv[++i]); set2vers = atoi(argv[++i]); set2prot = atoi(argv[++i]); set2port = atoi(argv[++i]); command_found++; } else if (!strcmp(argv[i], "unset2")) { unset2 = 1; unset2prog = atoi(argv[++i]); unset2vers = atoi(argv[++i]); unset2prot = atoi(argv[++i]); unset2port = atoi(argv[++i]); command_found++; } else if (!strcmp(argv[i], "dump3")) { dump3 = 1; command_found++; } else if (!strcmp(argv[i], "gettime3")) { gettime3 = 1; command_found++; } else if (!strcmp(argv[i], "u2t3")) { u2t3 = 1; u2t3string = argv[++i]; command_found++; } else if (!strcmp(argv[i], "getaddr3")) { getaddr3 = 1; getaddr3prog = atoi(argv[++i]); getaddr3vers = atoi(argv[++i]); getaddr3netid = argv[++i]; getaddr3addr = argv[++i]; getaddr3owner = argv[++i]; command_found++; } else if (!strcmp(argv[i], "set3")) { set3 = 1; set3prog = atoi(argv[++i]); set3vers = atoi(argv[++i]); set3netid = argv[++i]; set3addr = argv[++i]; set3owner = argv[++i]; command_found++; } else if (!strcmp(argv[i], "null3")) { null3 = 1; command_found++; } else { server = argv[i]; } } if (command_found == 0 || server == NULL) { fprintf(stderr, "Usage: portmap-client \n"); exit(10); } if (rpc_connect_async(rpc, server, 111, pmap_connect_cb, &client) != 0) { printf("Failed to start connection\n"); exit(10); } wait_until_finished(rpc, &client); if (null2) { if (rpc_pmap2_null_async(rpc, pmap2_null_cb, &client) != 0) { printf("Failed to send NULL2 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (dump2) { if (rpc_pmap2_dump_async(rpc, pmap2_dump_cb, &client) != 0) { printf("Failed to send DUMP2 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (null3) { if (rpc_pmap3_null_async(rpc, pmap3_null_cb, &client) != 0) { printf("Failed to send NULL3 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (dump3) { if (rpc_pmap3_dump_async(rpc, pmap3_dump_cb, &client) != 0) { printf("Failed to send DUMP3 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (gettime3) { if (rpc_pmap3_gettime_async(rpc, pmap3_gettime_cb, &client) != 0) { printf("Failed to send GETTIME3 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (u2t3) { if (rpc_pmap3_uaddr2taddr_async(rpc, u2t3string, pmap3_uaddr2taddr_cb, &client) != 0) { printf("Failed to send UADDR2TADDR3 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (getaddr3) { struct pmap3_mapping map; map.prog = getaddr3prog; map.vers = getaddr3vers; map.netid = getaddr3netid; map.addr = getaddr3addr; map.owner = getaddr3owner; if (rpc_pmap3_getaddr_async(rpc, &map, pmap3_getaddr_cb, &client) != 0) { printf("Failed to send GETADDR3 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (set2) { if (rpc_pmap2_set_async(rpc, set2prog, set2vers, set2prot, set2port, pmap2_set_cb, &client) != 0) { printf("Failed to send SET2 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (unset2) { if (rpc_pmap2_unset_async(rpc, unset2prog, unset2vers, unset2prot, unset2port, pmap2_unset_cb, &client) != 0) { printf("Failed to send UNSET2 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (set3) { struct pmap3_mapping map; map.prog = set3prog; map.vers = set3vers; map.netid = set3netid; map.addr = set3addr; map.owner = set3owner; if (rpc_pmap3_set_async(rpc, &map, pmap3_set_cb, &client) != 0) { printf("Failed to send SET3 request\n"); exit(10); } wait_until_finished(rpc, &client); } if (unset3) { struct pmap3_mapping map; map.prog = unset3prog; map.vers = unset3vers; map.netid = unset3netid; map.addr = unset3addr; map.owner = unset3owner; if (rpc_pmap3_unset_async(rpc, &map, pmap3_unset_cb, &client) != 0) { printf("Failed to send UNSET3 request\n"); exit(10); } wait_until_finished(rpc, &client); } rpc_destroy_context(rpc); rpc=NULL; return 0; } libnfs-libnfs-4.0.0/examples/portmap-server.c000066400000000000000000000507311343063627400212310ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2015 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ /* This is a very incomplete portmapper that only implements * a subset of version 2 and threee of the protocol. * A proper portmapper needs to implement these two versions fully * as well as version 4. * * See this as an example of how to build a simple RPC service * that supports both UDP and TCP using libnfs. */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #else #include #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-portmap.h" #include struct event_base *base; struct server { struct rpc_context *rpc; struct event *read_event; struct event *write_event; }; /* Socket where we listen for incomming rpc connections */ struct event *listen_event; int listen_socket = -1; /* Socket used for UDP server */ struct server udp_server; int udp_socket = -1; struct mapping { struct mapping *next; u_int prog; u_int vers; int port; char *netid; char *addr; char *owner; }; struct mapping *map; void free_map_item(struct mapping *item) { free(item->netid); free(item->addr); free(item->owner); free(item); } static void free_server(struct server *server) { if (server->rpc) { rpc_disconnect(server->rpc, NULL); rpc_destroy_context(server->rpc); } if (server->read_event) { event_free(server->read_event); } if (server->write_event) { event_free(server->write_event); } free(server); } /* * Based on the state of libnfs and its context, update libevent * accordingly regarding which events we are interested in. */ static void update_events(struct rpc_context *rpc, struct event *read_event, struct event *write_event) { int events = rpc_which_events(rpc); if (read_event) { if (events & POLLIN) { event_add(read_event, NULL); } else { event_del(read_event); } } if (write_event) { if (events & POLLOUT) { event_add(write_event, NULL); } else { event_del(write_event); } } } /* * Add a registration for program,version,netid. */ int pmap_register(int prog, int vers, char *netid, char *addr, char *owner) { struct mapping *item; char *str; int count = 0; item = malloc(sizeof(struct mapping)); item->prog = prog; item->vers = vers; item->netid = netid; item->addr = addr; item->owner = owner; /* The port are the last two dotted decimal fields in the address */ for (str = item->addr + strlen(item->addr) - 1; str >= item->addr; str--) { if (*str != '.') { if (*str < '0' || *str > '9') { break; } continue; } count++; if (count == 2) { int high, low; sscanf(str, ".%d.%d", &high, &low); item->port = high * 256 + low; break; } } item->next = map; map = item; } /* * Find and return a registration matching program,version,netid. */ struct mapping *map_lookup(int prog, int vers, char *netid) { struct mapping *tmp; for (tmp = map; tmp; tmp = tmp->next) { if (tmp->prog != prog) { continue; } if (tmp->vers != vers) { continue; } if (strcmp(tmp->netid, netid)) { continue; } return tmp; } return NULL; } /* * Remove a registration from our map or registrations. */ void map_remove(int prog, int vers, char *netid) { struct mapping *prev = NULL; struct mapping *tmp; for (tmp = map; tmp; prev = tmp, tmp = tmp->next) { if (tmp->prog != prog) { continue; } if (tmp->vers != vers) { continue; } if (strcmp(tmp->netid, netid)) { continue; } break; } if (tmp == NULL) { return; } if (prev) { prev->next = tmp->next; } else { map = tmp->next; } free_map_item(tmp); return; } /* * The NULL procedure. All protocols/versions must provide a NULL procedure * as index 0. * It is used by clients, and rpcinfo, to "ping" a service and verify that * the service is available and that it does support the indicated version. */ static int pmap2_null_proc(struct rpc_context *rpc, struct rpc_msg *call) { rpc_send_reply(rpc, call, NULL, (zdrproc_t)zdr_void, 0); return 0; } /* * v2 GETPORT. * This is the lookup function for portmapper version 2. * A client provides program, version and protocol (tcp or udp) * and portmapper returns which port that service is available on, * (or 0 if no such program is registered.) */ static int pmap2_getport_proc(struct rpc_context *rpc, struct rpc_msg *call) { PMAP2GETPORTargs *args = call->body.cbody.args; struct mapping *tmp; char *netid; uint32_t port = 0; if (args->prot == IPPROTO_TCP) { netid = "tcp"; } else { netid = "udp"; } tmp = map_lookup(args->prog, args->vers, netid); if (tmp) { port = tmp->port; } rpc_send_reply(rpc, call, &port, (zdrproc_t)zdr_uint32_t, sizeof(uint32_t)); return 0; } /* * v2 DUMP. * This RPC returns a list of all endpoints that are registered with * portmapper. */ static int pmap2_dump_proc(struct rpc_context *rpc, struct rpc_msg *call) { PMAP2DUMPres reply; struct mapping *tmp; reply.list = NULL; for (tmp = map; tmp; tmp = tmp->next) { struct pmap2_mapping_list *tmp_list; int proto; /* pmap2 only support ipv4 */ if (!strcmp(tmp->netid, "tcp")) { proto = IPPROTO_TCP; } else if (!strcmp(tmp->netid, "udp")) { proto = IPPROTO_UDP; } else { continue; } tmp_list = malloc(sizeof(struct pmap2_mapping_list)); tmp_list->map.prog = tmp->prog; tmp_list->map.vers = tmp->vers; tmp_list->map.prot = proto; tmp_list->map.port = tmp->port; tmp_list->next = reply.list; reply.list = tmp_list; } rpc_send_reply(rpc, call, &reply, (zdrproc_t)zdr_PMAP2DUMPres, sizeof(PMAP2DUMPres)); while (reply.list) { struct pmap2_mapping_list *tmp_list = reply.list->next; free(reply.list); reply.list = tmp_list; } return 0; } /* * v2 SET * This procedure is used to register and endpoint with portmapper. */ static int pmap2_set_proc(struct rpc_context *rpc, struct rpc_msg *call) { PMAP2GETPORTargs *args = call->body.cbody.args; char *prot; char *addr; uint32_t response = 1; if (args->prot == IPPROTO_TCP) { prot = "tcp"; } else { prot = "udp"; } /* Don't update if we already have a mapping */ if (map_lookup(args->prog, args->vers, prot)) { response = 0; rpc_send_reply(rpc, call, &response, (zdrproc_t)zdr_uint32_t, sizeof(uint32_t)); return 0; } asprintf(&addr, "0.0.0.0.%d.%d", args->port >> 8, args->port & 0xff); pmap_register(args->prog, args->vers, strdup(prot), addr, strdup("")); rpc_send_reply(rpc, call, &response, (zdrproc_t)zdr_uint32_t, sizeof(uint32_t)); return 0; } /* * v2 UNSET * This procedure is used to remove a registration from portmappers * list of endpoints. */ static int pmap2_unset_proc(struct rpc_context *rpc, struct rpc_msg *call) { PMAP2GETPORTargs *args = call->body.cbody.args; char *prot; char *addr; uint32_t response = 1; if (args->prot == IPPROTO_TCP) { prot = "tcp"; } else { prot = "udp"; } map_remove(args->prog, args->vers, prot); rpc_send_reply(rpc, call, &response, (zdrproc_t)zdr_uint32_t, sizeof(uint32_t)); return 0; } /* * Service table for portmapper v2. * * Service management is table driven in libnfsand this is the table * that defines which procedures we implement for portmapper v2. * If clients try to connect to the not-yet-implemented procedures here * libnfs will automatically respond with an RPC layer error that flags * PROCEDURE UNAVAILABLE. * * This table contains the procedure number, the callback function to implement * this procedure, the unmarshalling function that libnfs should use to unppack * the client payload as well as its size. * * Version 2 does not support ipv6 so this version of portmapper is * not too commonly used any more. */ struct service_proc pmap2_pt[] = { {PMAP2_NULL, pmap2_null_proc, (zdrproc_t)zdr_void, 0}, {PMAP2_SET, pmap2_set_proc, (zdrproc_t)zdr_PMAP2SETargs, sizeof(PMAP2SETargs)}, {PMAP2_UNSET, pmap2_unset_proc, (zdrproc_t)zdr_PMAP2UNSETargs, sizeof(PMAP2UNSETargs)}, {PMAP2_GETPORT, pmap2_getport_proc, (zdrproc_t)zdr_PMAP2GETPORTargs, sizeof(PMAP2GETPORTargs)}, {PMAP2_DUMP, pmap2_dump_proc, (zdrproc_t)zdr_void, 0}, //{PMAP2_CALLIT, pmap2_...}, }; /* * The NULL procedure. All protocols/versions must provide a NULL procedure * as index 0. * It is used by clients, and rpcinfo, to "ping" a service and verify that * the service is available and that it does support the indicated version. */ static int pmap3_null_proc(struct rpc_context *rpc, struct rpc_msg *call) { rpc_send_reply(rpc, call, NULL, (zdrproc_t)zdr_void, 0); return 0; } /* * v3 DUMP. * This RPC returns a list of all endpoints that are registered with * portmapper. */ static int pmap3_dump_proc(struct rpc_context *rpc, struct rpc_msg *call) { PMAP3DUMPres reply; struct mapping *tmp; reply.list = NULL; for (tmp = map; tmp; tmp = tmp->next) { struct pmap3_mapping_list *tmp_list; tmp_list = malloc(sizeof(struct pmap3_mapping_list)); tmp_list->map.prog = tmp->prog; tmp_list->map.vers = tmp->vers; tmp_list->map.netid = tmp->netid; tmp_list->map.addr = tmp->addr; tmp_list->map.owner = tmp->owner; tmp_list->next = reply.list; reply.list = tmp_list; } rpc_send_reply(rpc, call, &reply, (zdrproc_t)zdr_PMAP3DUMPres, sizeof(PMAP3DUMPres)); while (reply.list) { struct pmap3_mapping_list *tmp_list = reply.list->next; free(reply.list); reply.list = tmp_list; } return 0; } /* * Service table for portmapper v3. * * Service management is table driven in libnfsand this is the table * that defines which procedures we implement for portmapper v3. * If clients try to connect to the not-yet-implemented procedures here * libnfs will automatically respond with an RPC layer error that flags * PROCEDURE UNAVAILABLE. * * This table contains the procedure number, the callback function to implement * this procedure, the unmarshalling function that libnfs should use to unppack * the client payload as well as its size. */ struct service_proc pmap3_pt[] = { {PMAP3_NULL, pmap3_null_proc, (zdrproc_t)zdr_void, 0}, //{PMAP3_SET, pmap3_...}, //{PMAP3_UNSET, pmap3_...}, //{PMAP3_GETADDR, pmap3_...}, {PMAP3_DUMP, pmap3_dump_proc, (zdrproc_t)zdr_void, 0}, //{PMAP3_CALLIT, pmap3_...}, //{PMAP3_GETTIME, pmap3_...}, //{PMAP3_UADDR2TADDR, pmap3_...}, //{PMAP3_TADDR2UADDR, pmap3_...}, }; /* * This callback is invoked from the event system when an event we are waiting * for has become active. */ static void server_io(evutil_socket_t fd, short events, void *private_data) { struct server *server = private_data; int revents = 0; /* * Translate the libevent read/write flags to the corresponding * flags that libnfs uses. */ if (events & EV_READ) { revents |= POLLIN; } if (events & EV_WRITE) { revents |= POLLOUT; } /* * Let libnfs process the event. */ if (rpc_service(server->rpc, revents) < 0) { free_server(server); return; } /* * Update which events we are interested in. It might have changed * for example if we no longer have any data pending to send * we no longer need to wait for the socket to become writeable. */ update_events(server->rpc, server->read_event, server->write_event); } /* * This callback is invoked when we have a client connecting to our TCP * port. */ static void do_accept(evutil_socket_t s, short events, void *private_data) { struct sockaddr_storage ss; socklen_t len = sizeof(ss); struct server *server; int fd; server = malloc(sizeof(struct server)); if (server == NULL) { return; } memset(server, 0, sizeof(*server)); if ((fd = accept(s, (struct sockaddr *)&ss, &len)) < 0) { free_server(server); return; } evutil_make_socket_nonblocking(fd); server->rpc = rpc_init_server_context(fd); if (server->rpc == NULL) { close(fd); free_server(server); return; } /* * Register both v2 and v3 of the protocol to the new * server context. */ rpc_register_service(server->rpc, PMAP_PROGRAM, PMAP_V2, pmap2_pt, sizeof(pmap2_pt) / sizeof(pmap2_pt[0])); rpc_register_service(server->rpc, PMAP_PROGRAM, PMAP_V3, pmap3_pt, sizeof(pmap3_pt) / sizeof(pmap3_pt[0])); /* * Create events for read and write for this new server instance. */ server->read_event = event_new(base, fd, EV_READ|EV_PERSIST, server_io, server); server->write_event = event_new(base, fd, EV_WRITE|EV_PERSIST, server_io, server); update_events(server->rpc, server->read_event, server->write_event); } int main(int argc, char *argv[]) { struct sockaddr_in in; int one = 1; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); return 10; } #endif #ifdef AROS aros_init_socket(); #endif base = event_base_new(); if (base == NULL) { printf("Failed create event context\n"); exit(10); } /* * Portmapper listens on port 111, any address. * Just initialize it for now as we will need it several times below. */ in.sin_family = AF_INET; in.sin_port = htons(111); in.sin_addr.s_addr = htonl (INADDR_ANY); /* This is the portmapper protocol itself which we obviously * support. */ pmap_register(100000, 2, strdup("tcp"), strdup("0.0.0.0.0.111"), strdup("portmapper-service")); pmap_register(100000, 2, strdup("udp"), strdup("0.0.0.0.0.111"), strdup("portmapper-service")); pmap_register(100000, 3, strdup("tcp"), strdup("0.0.0.0.0.111"), strdup("portmapper-service")); pmap_register(100000, 3, strdup("udp"), strdup("0.0.0.0.0.111"), strdup("portmapper-service")); /* * TCP: Set up a listening socket for incoming TCP connections. * Once clients connect, inside do_accept() we will create a proper * libnfs server context for each connection. */ listen_socket = socket(AF_INET, SOCK_STREAM, 0); if (listen_socket == -1) { printf("Failed to create listening socket\n"); exit(10); } evutil_make_socket_nonblocking(listen_socket); setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (bind(listen_socket, (struct sockaddr *)&in, sizeof(in)) < 0) { printf("Failed to bind listening socket\n"); exit(10); } if (listen(listen_socket, 16) < 0) { printf("failed to listen to socket\n"); exit(10); } listen_event = event_new(base, listen_socket, EV_READ|EV_PERSIST, do_accept, NULL); event_add(listen_event, NULL); /* * UDP: Create and bind to the socket we want to use for the UDP server. */ udp_socket = socket(AF_INET, SOCK_DGRAM, 0); if (udp_socket == -1) { printf("Failed to create udp socket\n"); exit(10); } evutil_make_socket_nonblocking(udp_socket); setsockopt(udp_socket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (bind(udp_socket, (struct sockaddr *)&in, sizeof(in)) < 0) { printf("Failed to bind udp socket\n"); exit(10); } /* * UDP: Create a libnfs server context for this socket. */ memset(&udp_server, 0, sizeof(udp_server)); udp_server.rpc = rpc_init_server_context(udp_socket); /* * UDP: Register both v2 and v3 of the protocol to the * UDP server context. */ rpc_register_service(udp_server.rpc, PMAP_PROGRAM, PMAP_V2, pmap2_pt, sizeof(pmap2_pt) / sizeof(pmap2_pt[0])); rpc_register_service(udp_server.rpc, PMAP_PROGRAM, PMAP_V3, pmap3_pt, sizeof(pmap3_pt) / sizeof(pmap3_pt[0])); udp_server.read_event = event_new(base, udp_socket, EV_READ|EV_PERSIST, server_io, &udp_server); event_add(udp_server.read_event, NULL); /* * Everything is now set up. Start the event loop. */ event_base_dispatch(base); return 0; } libnfs-libnfs-4.0.0/include/000077500000000000000000000000001343063627400156765ustar00rootroot00000000000000libnfs-libnfs-4.0.0/include/Makefile.am000066400000000000000000000006311343063627400177320ustar00rootroot00000000000000nfscdir = $(includedir)/nfsc dist_nfsc_HEADERS = \ nfsc/libnfs.h \ nfsc/libnfs-raw.h \ nfsc/libnfs-zdr.h \ ../mount/libnfs-raw-mount.h \ ../portmap/libnfs-raw-portmap.h \ ../nfs/libnfs-raw-nfs.h \ ../nfs4/libnfs-raw-nfs4.h \ ../nlm/libnfs-raw-nlm.h \ ../nsm/libnfs-raw-nsm.h \ ../rquota/libnfs-raw-rquota.h dist_noinst_HEADERS = \ win32/win32_compat.h \ libnfs-private.h \ slist.h libnfs-libnfs-4.0.0/include/libnfs-private.h000066400000000000000000000502561343063627400210040ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifndef _LIBNFS_PRIVATE_H_ #define _LIBNFS_PRIVATE_H_ #ifdef HAVE_CONFIG_H #include "config.h" /* HAVE_SOCKADDR_STORAGE ? */ #endif #ifdef HAVE_NET_IF_H #include #endif #ifndef WIN32 #include /* struct sockaddr_storage */ #endif #if defined(WIN32) && !defined(IFNAMSIZ) #define IFNAMSIZ 255 #endif #include "libnfs-zdr.h" #include "../nfs/libnfs-raw-nfs.h" #include "../nfs4/libnfs-raw-nfs4.h" #ifdef __cplusplus extern "C" { #endif #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #if !defined(HAVE_SOCKADDR_STORAGE) && !defined(WIN32) /* * RFC 2553: protocol-independent placeholder for socket addresses */ #define _SS_MAXSIZE 128 #define _SS_ALIGNSIZE (sizeof(double)) #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2) #define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \ _SS_PAD1SIZE - _SS_ALIGNSIZE) struct sockaddr_storage { #ifdef HAVE_SOCKADDR_LEN unsigned char ss_len; /* address length */ unsigned char ss_family; /* address family */ #else unsigned short ss_family; #endif char __ss_pad1[_SS_PAD1SIZE]; double __ss_align; /* force desired structure storage alignment */ char __ss_pad2[_SS_PAD2SIZE]; }; #endif struct rpc_fragment { struct rpc_fragment *next; uint32_t size; char *data; }; #define RPC_CONTEXT_MAGIC 0xc6e46435 #define RPC_PARAM_UNDEFINED -1 /* * Queue is singly-linked but we hold on to the tail */ struct rpc_queue { struct rpc_pdu *head, *tail; }; #define HASHES 1024 #define NFS_RA_TIMEOUT 5 #define NFS_MAX_XFER_SIZE (1024 * 1024) #define ZDR_ENCODE_OVERHEAD 1024 #define ZDR_ENCODEBUF_MINSIZE 4096 struct rpc_endpoint { struct rpc_endpoint *next; int program; int version; struct service_proc *procs; int num_procs; }; struct rpc_context { uint32_t magic; int fd; int old_fd; int is_connected; int is_nonblocking; char *error_string; rpc_cb connect_cb; void *connect_data; struct AUTH *auth; uint32_t xid; struct rpc_queue outqueue; struct sockaddr_storage udp_src; struct rpc_queue waitpdu[HASHES]; uint32_t waitpdu_len; uint32_t inpos; char rm_buf[4]; char *inbuf; /* special fields for UDP, which can sometimes be BROADCASTed */ int is_udp; struct sockaddr_storage udp_dest; int is_broadcast; /* track the address we connect to so we can auto-reconnect on session failure */ struct sockaddr_storage s; int auto_reconnect; int num_retries; /* fragment reassembly */ struct rpc_fragment *fragments; /* parameters passable via URL */ int tcp_syncnt; int uid; int gid; uint32_t readahead; uint32_t pagecache; uint32_t pagecache_ttl; int debug; int timeout; char ifname[IFNAMSIZ]; /* Is a server context ? */ int is_server_context; struct rpc_endpoint *endpoints; }; struct rpc_pdu { struct rpc_pdu *next; uint32_t xid; ZDR zdr; uint32_t written; struct rpc_data outdata; rpc_cb cb; void *private_data; /* function to decode the zdr reply data and buffer to decode into */ zdrproc_t zdr_decode_fn; caddr_t zdr_decode_buf; uint32_t zdr_decode_bufsize; #define PDU_DISCARD_AFTER_SENDING 0x00000001 uint32_t flags; uint64_t timeout; }; void rpc_reset_queue(struct rpc_queue *q); void rpc_enqueue(struct rpc_queue *q, struct rpc_pdu *pdu); void rpc_return_to_queue(struct rpc_queue *q, struct rpc_pdu *pdu); unsigned int rpc_hash_xid(uint32_t xid); struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_bufsize); struct rpc_pdu *rpc_allocate_pdu2(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_bufsize, size_t alloc_hint); void rpc_free_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu); int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu); uint32_t rpc_get_pdu_size(char *buf); int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size); void rpc_error_all_pdus(struct rpc_context *rpc, const char *error); void rpc_set_error(struct rpc_context *rpc, const char *error_string, ...) #ifdef __GNUC__ __attribute__((format(printf, 2, 3))) #endif ; void nfs_set_error(struct nfs_context *nfs, char *error_string, ...) #ifdef __GNUC__ __attribute__((format(printf, 2, 3))) #endif ; #define RPC_LOG(rpc, level, format, ...) \ do { \ if (level <= rpc->debug) { \ fprintf(stderr, "libnfs:%d " format "\n", level, ## __VA_ARGS__); \ } \ } while (0) const char *nfs_get_server(struct nfs_context *nfs); const char *nfs_get_export(struct nfs_context *nfs); /* we dont want to expose UDP to normal applications/users this is private to libnfs to use exclusively for broadcast RPC */ int rpc_bind_udp(struct rpc_context *rpc, char *addr, int port); int rpc_set_udp_destination(struct rpc_context *rpc, char *addr, int port, int is_broadcast); struct rpc_context *rpc_init_udp_context(void); struct sockaddr *rpc_get_recv_sockaddr(struct rpc_context *rpc); void rpc_set_autoreconnect(struct rpc_context *rpc, int num_retries); void rpc_set_interface(struct rpc_context *rpc, const char *ifname); void rpc_set_tcp_syncnt(struct rpc_context *rpc, int v); void rpc_set_pagecache(struct rpc_context *rpc, uint32_t v); void rpc_set_pagecache_ttl(struct rpc_context *rpc, uint32_t v); void rpc_set_readahead(struct rpc_context *rpc, uint32_t v); void rpc_set_debug(struct rpc_context *rpc, int level); void rpc_set_timeout(struct rpc_context *rpc, int timeout); int rpc_get_timeout(struct rpc_context *rpc); int rpc_add_fragment(struct rpc_context *rpc, char *data, uint32_t size); void rpc_free_all_fragments(struct rpc_context *rpc); int rpc_is_udp_socket(struct rpc_context *rpc); uint64_t rpc_current_time(void); void *zdr_malloc(ZDR *zdrs, uint32_t size); struct nfs_cb_data; void free_nfs_cb_data(struct nfs_cb_data *data); struct nfs_specdata { uint32_t specdata1; uint32_t specdata2; }; struct nfs_time { uint32_t seconds; uint32_t nseconds; }; struct nfs_attr { uint32_t type; uint32_t mode; uint32_t uid; uint32_t gid; uint32_t nlink; uint64_t size; uint64_t used; uint64_t fsid; struct nfs_specdata rdev; struct nfs_time atime; struct nfs_time mtime; struct nfs_time ctime; }; struct nfs_fh { int len; char *val; }; struct nfs_context { struct rpc_context *rpc; char *server; char *export; struct nfs_fh rootfh; uint64_t readmax; uint64_t writemax; char *cwd; int dircache_enabled; int auto_reconnect; struct nfsdir *dircache; uint16_t mask; int auto_traverse_mounts; struct nested_mounts *nested_mounts; int version; int nfsport; int mountport; /* NFSv4 specific fields */ verifier4 verifier; char *client_name; uint64_t clientid; verifier4 setclientid_confirm; uint32_t seqid; int has_lock_owner; }; typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_attr *attr, struct nfs_cb_data *data); struct nfs_cb_data { struct nfs_context *nfs; struct nfsfh *nfsfh; char *saved_path, *path; int link_count, no_follow; nfs_cb cb; void *private_data; continue_func continue_cb; void *continue_data; void (*free_continue_data)(void *); uint64_t continue_int; struct nfs_fh fh; /* for multi-read/write calls. */ int error; int cancel; int oom; int num_calls; size_t count, org_count; uint64_t offset, max_offset, org_offset; char *buffer; int not_my_buffer; const char *usrbuf; int update_pos; }; struct nested_mounts { struct nested_mounts *next; char *path; struct nfs_fh fh; struct nfs_attr attr; }; #define MAX_DIR_CACHE 128 #define MAX_LINK_COUNT 40 struct nfsdir { struct nfs_fh fh; struct nfs_attr attr; struct nfsdir *next; struct nfsdirent *entries; struct nfsdirent *current; }; struct nfs_readahead { uint64_t fh_offset; uint32_t cur_ra; }; struct nfs_pagecache_entry { char buf[NFS_BLKSIZE]; uint64_t offset; time_t ts; }; struct nfs_pagecache { struct nfs_pagecache_entry *entries; uint32_t num_entries; time_t ttl; }; struct stateid { uint32_t seqid; char other[12]; }; struct nfsfh { struct nfs_fh fh; int is_sync; int is_append; int is_dirty; uint64_t offset; struct nfs_readahead ra; struct nfs_pagecache pagecache; /* NFSv4 */ struct stateid stateid; /* locking */ uint32_t lock_seqid; struct stateid lock_stateid; }; const struct nfs_fh *nfs_get_rootfh(struct nfs_context *nfs); int nfs_normalize_path(struct nfs_context *nfs, char *path); void nfs_free_nfsdir(struct nfsdir *nfsdir); void nfs_free_nfsfh(struct nfsfh *nfsfh); void nfs_dircache_add(struct nfs_context *nfs, struct nfsdir *nfsdir); struct nfsdir *nfs_dircache_find(struct nfs_context *nfs, struct nfs_fh *fh); void nfs_dircache_drop(struct nfs_context *nfs, struct nfs_fh *fh); char * nfs_pagecache_get(struct nfs_pagecache *pagecache, uint64_t offset); void nfs_pagecache_put(struct nfs_pagecache *pagecache, uint64_t offset, const char *buf, size_t len); int nfs3_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); int nfs3_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_chmod_async_internal(struct nfs_context *nfs, const char *path, int no_follow, int mode, nfs_cb cb, void *private_data); int nfs3_chown_async_internal(struct nfs_context *nfs, const char *path, int no_follow, int uid, int gid, nfs_cb cb, void *private_data); int nfs3_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); int nfs3_create_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data); int nfs3_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs_cb cb, void *private_data); int nfs3_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid, nfs_cb cb, void *private_data); int nfs3_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); int nfs3_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); int nfs3_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); int nfs3_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length, nfs_cb cb, void *private_data); int nfs3_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); int nfs3_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, nfs_cb cb, void *private_data); int nfs3_mkdir2_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); int nfs3_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev, nfs_cb cb, void *private_data); int nfs3_mount_async(struct nfs_context *nfs, const char *server, const char *export, nfs_cb cb, void *private_data); int nfs3_open_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data); int nfs3_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, size_t count, nfs_cb cb, void *private_data, int update_pos); int nfs3_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, size_t count, const char *buf, nfs_cb cb, void *private_data, int update_pos); int nfs3_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); int nfs3_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_stat64_async(struct nfs_context *nfs, const char *path, int no_follow, nfs_cb cb, void *private_data); int nfs3_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_symlink_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); int nfs3_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data); int nfs3_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data); int nfs3_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data); int nfs3_utimes_async_internal(struct nfs_context *nfs, const char *path, int no_follow, struct timeval *times, nfs_cb cb, void *private_data); int nfs3_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, const void *buf, nfs_cb cb, void *private_data); int nfs4_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); int nfs4_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs4_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs4_chmod_async_internal(struct nfs_context *nfs, const char *path, int no_follow, int mode, nfs_cb cb, void *private_data); int nfs4_chown_async_internal(struct nfs_context *nfs, const char *path, int no_follow, int uid, int gid, nfs_cb cb, void *private_data); int nfs4_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); int nfs4_create_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data); int nfs4_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs_cb cb, void *private_data); int nfs4_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid, nfs_cb cb, void *private_data); int nfs4_fcntl_async(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_fcntl_op cmd, void *arg, nfs_cb cb, void *private_data); int nfs4_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); int nfs4_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); int nfs4_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length, nfs_cb cb, void *private_data); int nfs4_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); int nfs4_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, nfs_cb cb, void *private_data); int nfs4_lockf_async(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_lock_op op, uint64_t count, nfs_cb cb, void *private_data); int nfs4_mkdir2_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); int nfs4_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev, nfs_cb cb, void *private_data); int nfs4_mount_async(struct nfs_context *nfs, const char *server, const char *export, nfs_cb cb, void *private_data); int nfs4_open_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data); int nfs4_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs4_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, size_t count, nfs_cb cb, void *private_data, int update_pos); int nfs4_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, size_t count, const char *buf, nfs_cb cb, void *private_data, int update_pos); int nfs4_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs4_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); int nfs4_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs4_stat64_async(struct nfs_context *nfs, const char *path, int no_follow, nfs_cb cb, void *private_data); int nfs4_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs4_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs4_symlink_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); int nfs4_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data); int nfs4_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs4_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data); int nfs4_utimes_async_internal(struct nfs_context *nfs, const char *path, int no_follow, struct timeval *times, nfs_cb cb, void *private_data); int nfs4_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, const void *buf, nfs_cb cb, void *private_data); #ifdef __cplusplus } #endif #endif /* !_LIBNFS_PRIVATE_H_ */ libnfs-libnfs-4.0.0/include/nfsc/000077500000000000000000000000001343063627400166275ustar00rootroot00000000000000libnfs-libnfs-4.0.0/include/nfsc/libnfs-raw.h000066400000000000000000002554531343063627400210620ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ /* * This is the lowlevel interface to access NFS resources. * Through this interface you have access to the full gamut of nfs and nfs * related protocol as well as the XDR encoded/decoded structures. */ #ifndef _LIBNFS_RAW_H_ #define _LIBNFS_RAW_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct rpc_data { int size; char *data; }; struct rpc_context; EXTERN struct rpc_context *rpc_init_context(void); EXTERN void rpc_destroy_context(struct rpc_context *rpc); EXTERN void rpc_set_auth(struct rpc_context *rpc, struct AUTH *auth); /* * Used for interfacing the api into an external eventsystem. * * rpc_get_fd() returns the file descriptor to poll. * * rpc_which_events() returns which events that we need to poll for. * This is a combination of the POLLIN and POLLOUT flags. * * rpc_service() is called everytime there are events that needs to be * processed. * revents is a combination of POLLIN/POLLOUT/POLLHUP/POLLERR * * This function returns 0 on success or -1 on error. If it returns -1 it * means that the socket is in an unrecoverable error state (disconnected?) * and that no further commands can be used. * When this happens the application should destroy the now errored context * re-create a new context and reconnect. * * * rpc_service() will both process the events indicated by revents and also * check for and terminate any RPCs that have timed out. * Thus, if using rpc timeouts, you will need to ensure that rpc_service() * is invoked on a regular basis so that the timeout processing can take place. * The easiest way to do this is to call rpc_service() once every 100ms from * your event system and passing revents as 0. */ EXTERN int rpc_get_fd(struct rpc_context *rpc); EXTERN int rpc_which_events(struct rpc_context *rpc); EXTERN int rpc_service(struct rpc_context *rpc, int revents); /* * Returns the number of commands in-flight. Can be used by the application * to check if there are any more responses we are awaiting from the server * or if the connection is completely idle. */ EXTERN int rpc_queue_length(struct rpc_context *rpc); /* * Set which UID/GID to use in the authenticator. * By default libnfs will use getuid()/getgid() where available * and 65534/65534 where not. */ EXTERN void rpc_set_uid(struct rpc_context *rpc, int uid); EXTERN void rpc_set_gid(struct rpc_context *rpc, int gid); /* * Create a server context. */ EXTERN struct rpc_context *rpc_init_server_context(int s); /* This is the callback functions for server contexts. * These are invoked from the library when a CALL has been received and a * service procedure has been found that matches the rpc * program/version/procedure. * * The rpc arguments are stored in call->body.cbody.args; * Example: * static int pmap2_getport_proc(struct rpc_context *rpc, struct rpc_msg *call) * { * pmap2_mapping *args = call->body.cbody.args; * ... * * struct service_proc pmap2_pt[] = { * {PMAP2_GETPORT, pmap2_getport_proc, * (zdrproc_t)zdr_pmap2_mapping, sizeof(pmap2_mapping)}, * ... * * * The return value is: * 0: Procedure was completed normally. * !0: An abnormal error has occured. It is unrecoverable and the only * meaningful action is to tear down the connection to the server. */ typedef int (*service_fn)(struct rpc_context *rpc, struct rpc_msg *call); struct service_proc { int proc; service_fn func; zdrproc_t decode_fn; int decode_buf_size; }; /* * Register a service callback table for program/version. * Can only be used with contexts created with rpc_init_server_context() */ EXTERN int rpc_register_service(struct rpc_context *rpc, int program, int version, struct service_proc *procs, int num_procs); EXTERN int rpc_send_reply(struct rpc_context *rpc, struct rpc_msg *call, void *reply, zdrproc_t encode_fn, int alloc_hint); /* * When an operation failed, this function can extract a detailed error string. */ EXTERN char *rpc_get_error(struct rpc_context *rpc); /* Utility function to get an RPC context from a NFS context. Useful for doing * low level NFSACL calls on a NFS context. */ EXTERN struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs); /* This function returns the nfs_fh structure from a nfsfh structure. This allows to use a file opened with nfs_open() together with low-level rpc functions that thake a nfs filehandle */ EXTERN struct nfs_fh *nfs_get_fh(struct nfsfh *nfsfh); /* Control what the next XID value to be used on the context will be. This can be used when multiple contexts are used to the same server to avoid that the two contexts have xid collissions. */ EXTERN void rpc_set_next_xid(struct rpc_context *rpc, uint32_t xid); /* This function can be used to set the file descriptor used for * the RPC context. It is primarily useful when emulating dup2() * and similar or where you want full control of the filedescriptor numbers * used by the rpc socket. * * ... * oldfd = rpc_get_fd(rpc); * dup2(oldfd, newfd); * rpc_set_fd(rpc, newfd); * close(oldfd); * ... */ EXTERN void rpc_set_fd(struct rpc_context *rpc, int fd); #define RPC_STATUS_SUCCESS 0 #define RPC_STATUS_ERROR 1 #define RPC_STATUS_CANCEL 2 #define RPC_STATUS_TIMEOUT 3 /* * Async connection to the tcp port at server:port. * Function returns * 0 : The connection was initiated. The callback will be invoked once the * connection establish finishes. * <0 : An error occured when trying to set up the connection. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : The tcp connection was successfully established. * data is NULL. * RPC_STATUS_ERROR : The connection failed to establish. * data is the error string. * RPC_STATUS_CANCEL : The connection attempt was aborted before it could * complete. * : data is NULL. */ EXTERN int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc_cb cb, void *private_data); /* * Async function to connect to a specific RPC program/version * Function returns * 0 : The connection was initiated. The callback will be invoked once the * connection establish finishes. * <0 : An error occured when trying to set up the connection. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : The tcp connection was successfully established. * data is NULL. * RPC_STATUS_ERROR : The connection failed to establish. * data is the error string. * RPC_STATUS_CANCEL : The connection attempt was aborted before it could * complete. * : data is NULL. */ EXTERN int rpc_connect_program_async(struct rpc_context *rpc, const char *server, int program, int version, rpc_cb cb, void *private_data); /* * Async function to connect to a specific RPC program/version. * This connects directly to the specified port without using portmapper. * * Function returns * 0 : The connection was initiated. The callback will be invoked once the * connection establish finishes. * <0 : An error occured when trying to set up the connection. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : The tcp connection was successfully established. * data is NULL. * RPC_STATUS_ERROR : The connection failed to establish. * data is the error string. * RPC_STATUS_CANCEL : The connection attempt was aborted before it could * complete. * : data is NULL. */ EXTERN int rpc_connect_port_async(struct rpc_context *rpc, const char *server, int port, int program, int version, rpc_cb cb, void *private_data); /* * When disconnecting a connection all commands in flight will be * called with a callback status RPC_STATUS_ERROR. Data will be the * error string for the disconnection. */ EXTERN int rpc_disconnect(struct rpc_context *rpc, const char *error); /* * PORTMAP v2 FUNCTIONS */ /* * Call PORTMAPPER2/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call PORTMAPPER2/GETPORT. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a (uint32_t *), containing the port returned. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap2_getport_async(struct rpc_context *rpc, int program, int version, int protocol, rpc_cb cb, void *private_data); /* * Call PORTMAPPER2/SET * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a (uint32_t *), containing status * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap2_set_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data); /* * Call PORTMAPPER2/UNSET * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a (uint32_t *), containing status * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap2_unset_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data); /* * Call PORTMAPPER2/DUMP. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is struct pmap2_dump_result. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap2_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call PORTMAPPER2/CALLIT. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a 'pmap2_call_result' pointer. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap2_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data); /* * PORTMAP v3 FUNCTIONS */ /* * Call PORTMAPPER3/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call PORTMAPPER3/SET. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is uint32_t * containing status. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct pmap3_mapping; EXTERN int rpc_pmap3_set_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data); /* * Call PORTMAPPER3/UNSET. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is uint32_t * containing status. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap3_unset_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data); /* * Call PORTMAPPER3/GETADDR. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is struct pmap3_string_result. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap3_getaddr_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data); /* * Call PORTMAPPER3/DUMP. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is struct pmap3_dump_result. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap3_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call PORTMAPPER3/CALLIT. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a 'pmap3_call_result' pointer. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap3_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data); /* * Call PORTMAPPER3/GETTIME. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a uint32_t * containing status. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap3_gettime_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call PORTMAPPER3/UADDR2TADDR. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a struct pmap3_netbuf *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_pmap3_uaddr2taddr_async(struct rpc_context *rpc, char *uaddr, rpc_cb cb, void *private_data); /* * Call PORTMAPPER3/TADDR2UADDR. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a struct pmap3_string_result *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct pmap3_netbuf; EXTERN int rpc_pmap3_taddr2uaddr_async(struct rpc_context *rpc, struct pmap3_netbuf *netbuf, rpc_cb cb, void *private_data); /* * MOUNT v3 FUNCTIONS */ EXTERN char *mountstat3_to_str(int stat); EXTERN int mountstat3_to_errno(int error); /* * Call MOUNT3/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); EXTERN int rpc_mount_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call MOUNT3/MNT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is union mountres3. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount3_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, void *private_data); EXTERN int rpc_mount_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, void *private_data); /* * Call MOUNT3/DUMP * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a mountlist. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount3_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); EXTERN int rpc_mount_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call MOUNT3/UMNT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount3_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, void *private_data); EXTERN int rpc_mount_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, void *private_data); /* * Call MOUNT3/UMNTALL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount3_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); EXTERN int rpc_mount_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call MOUNT3/EXPORT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is exports *: * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount3_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); EXTERN int rpc_mount_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * MOUNT v1 FUNCTIONS (Used with NFSv2) */ /* * Call MOUNT1/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call MOUNT1/MNT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is union mountres1. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount1_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, void *private_data); /* * Call MOUNT1/DUMP * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is a mountlist. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount1_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call MOUNT1/UMNT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount1_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, void *private_data); /* * Call MOUNT1/UMNTALL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount1_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call MOUNT1/EXPORT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is exports *: * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_mount1_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * NFS v3 FUNCTIONS */ struct nfs_fh3; EXTERN char *nfsstat3_to_str(int error); EXTERN int nfsstat3_to_errno(int error); /* * Call NFS3/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_nfs3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); EXTERN int rpc_nfs_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call NFS3/GETATTR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is GETATTR3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct GETATTR3args; EXTERN int rpc_nfs3_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct GETATTR3args *args, void *private_data); EXTERN int rpc_nfs_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data); /* * Call NFS3/PATHCONF * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is PATHCONF3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct PATHCONF3args; EXTERN int rpc_nfs3_pathconf_async(struct rpc_context *rpc, rpc_cb cb, struct PATHCONF3args *args, void *private_data); EXTERN int rpc_nfs_pathconf_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data); /* * Call NFS3/LOOKUP * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is LOOKUP3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct LOOKUP3args; EXTERN int rpc_nfs3_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct LOOKUP3args *args, void *private_data); EXTERN int rpc_nfs_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data); /* * Call NFS3/ACCESS * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is ACCESS3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct ACCESS3args; EXTERN int rpc_nfs3_access_async(struct rpc_context *rpc, rpc_cb cb, struct ACCESS3args *args, void *private_data); EXTERN int rpc_nfs_access_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, int access, void *private_data); /* * Call NFS3/READ * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is READ3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct READ3args; EXTERN int rpc_nfs3_read_async(struct rpc_context *rpc, rpc_cb cb, struct READ3args *args, void *private_data); EXTERN int rpc_nfs_read_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t offset, uint64_t count, void *private_data); /* * Call NFS3/WRITE * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is WRITE3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct WRITE3args; EXTERN int rpc_nfs3_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE3args *args, void *private_data); EXTERN int rpc_nfs_write_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *buf, uint64_t offset, uint64_t count, int stable_how, void *private_data); /* * Call NFS3/COMMIT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is COMMIT3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct COMMIT3args; EXTERN int rpc_nfs3_commit_async(struct rpc_context *rpc, rpc_cb cb, struct COMMIT3args *args, void *private_data); EXTERN int rpc_nfs_commit_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data); /* * Call NFS3/SETATTR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is SETATTR3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct SETATTR3args; EXTERN int rpc_nfs3_setattr_async(struct rpc_context *rpc, rpc_cb cb, struct SETATTR3args *args, void *private_data); EXTERN int rpc_nfs_setattr_async(struct rpc_context *rpc, rpc_cb cb, struct SETATTR3args *args, void *private_data); /* * Call NFS3/MKDIR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is MKDIR3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct MKDIR3args; EXTERN int rpc_nfs3_mkdir_async(struct rpc_context *rpc, rpc_cb cb, struct MKDIR3args *args, void *private_data); EXTERN int rpc_nfs_mkdir_async(struct rpc_context *rpc, rpc_cb cb, struct MKDIR3args *args, void *private_data); /* * Call NFS3/RMDIR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is RMDIR3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct RMDIR3args; EXTERN int rpc_nfs3_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct RMDIR3args *args, void *private_data); EXTERN int rpc_nfs_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *dir, void *private_data); /* * Call NFS3/CREATE * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is CREATE3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct CREATE3args; EXTERN int rpc_nfs3_create_async(struct rpc_context *rpc, rpc_cb cb, struct CREATE3args *args, void *private_data); EXTERN int rpc_nfs_create_async(struct rpc_context *rpc, rpc_cb cb, struct CREATE3args *args, void *private_data); /* * Call NFS3/MKNOD * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is MKNOD3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct MKNOD3args; EXTERN int rpc_nfs3_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct MKNOD3args *args, void *private_data); EXTERN int rpc_nfs_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, int mode, int major, int minor, void *private_data); /* * Call NFS3/REMOVE * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is REMOVE3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct REMOVE3args; EXTERN int rpc_nfs3_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE3args *args, void *private_data); EXTERN int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data); /* * Call NFS3/READDIR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is READDIR3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct READDIR3args; EXTERN int rpc_nfs3_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct READDIR3args *args, void *private_data); EXTERN int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data); /* * Call NFS3/READDIRPLUS * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is READDIRPLUS3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct READDIRPLUS3args; EXTERN int rpc_nfs3_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct READDIRPLUS3args *args, void *private_data); EXTERN int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data); /* * Call NFS3/FSSTAT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is FSSTAT3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct FSSTAT3args; EXTERN int rpc_nfs3_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct FSSTAT3args *args, void *private_data); EXTERN int rpc_nfs_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data); /* * Call NFS3/FSINFO * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is FSINFO3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct FSINFO3args; EXTERN int rpc_nfs3_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct FSINFO3args *args, void *private_data); EXTERN int rpc_nfs_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data); /* * Call NFS3/READLINK * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is READLINK3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct READLINK3args; EXTERN int rpc_nfs3_readlink_async(struct rpc_context *rpc, rpc_cb cb, struct READLINK3args *args, void *private_data); EXTERN int rpc_nfs_readlink_async(struct rpc_context *rpc, rpc_cb cb, struct READLINK3args *args, void *private_data); /* * Call NFS3/SYMLINK * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is SYMLINK3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct SYMLINK3args; EXTERN int rpc_nfs3_symlink_async(struct rpc_context *rpc, rpc_cb cb, struct SYMLINK3args *args, void *private_data); EXTERN int rpc_nfs_symlink_async(struct rpc_context *rpc, rpc_cb cb, struct SYMLINK3args *args, void *private_data); /* * Call NFS3/RENAME * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is RENAME3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct RENAME3args; EXTERN int rpc_nfs3_rename_async(struct rpc_context *rpc, rpc_cb cb, struct RENAME3args *args, void *private_data); EXTERN int rpc_nfs_rename_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *olddir, char *oldname, struct nfs_fh3 *newdir, char *newname, void *private_data); /* * Call NFS3/LINK * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is LINK3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct LINK3args; EXTERN int rpc_nfs3_link_async(struct rpc_context *rpc, rpc_cb cb, struct LINK3args *args, void *private_data); EXTERN int rpc_nfs_link_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *file, struct nfs_fh3 *newdir, char *newname, void *private_data); /* * NFS v2 FUNCTIONS */ /* * Call NFS2/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_nfs2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call NFS2/GETATTR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is GETATTR2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct GETATTR2args; EXTERN int rpc_nfs2_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct GETATTR2args *args, void *private_data); /* * Call NFS2/SETATTR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is SETATTR2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct SETATTR2args; EXTERN int rpc_nfs2_setattr_async(struct rpc_context *rpc, rpc_cb cb, struct SETATTR2args *args, void *private_data); /* * Call NFS2/LOOKUP * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is LOOKUP2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct LOOKUP2args; EXTERN int rpc_nfs2_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct LOOKUP2args *args, void *private_data); /* * Call NFS2/READLINK * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is READLINK2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct READLINK2args; EXTERN int rpc_nfs2_readlink_async(struct rpc_context *rpc, rpc_cb cb, struct READLINK2args *args, void *private_data); /* * Call NFS2/READ * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is READ2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct READ2args; EXTERN int rpc_nfs2_read_async(struct rpc_context *rpc, rpc_cb cb, struct READ2args *args, void *private_data); /* * Call NFS2/WRITE * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is WRITE2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct WRITE2args; EXTERN int rpc_nfs2_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE2args *args, void *private_data); /* * Call NFS2/CREATE * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is CREATE2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct CREATE2args; EXTERN int rpc_nfs2_create_async(struct rpc_context *rpc, rpc_cb cb, struct CREATE2args *args, void *private_data); /* * Call NFS2/REMOVE * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is REMOVE2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct REMOVE2args; EXTERN int rpc_nfs2_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE2args *args, void *private_data); /* * Call NFS2/RENAME * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is RENAME2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct RENAME2args; EXTERN int rpc_nfs2_rename_async(struct rpc_context *rpc, rpc_cb cb, struct RENAME2args *args, void *private_data); /* * Call NFS2/LINK * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is LINK2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct LINK2args; EXTERN int rpc_nfs2_link_async(struct rpc_context *rpc, rpc_cb cb, struct LINK2args *args, void *private_data); /* * Call NFS2/SYMLINK * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is SYMLINK2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct SYMLINK2args; EXTERN int rpc_nfs2_symlink_async(struct rpc_context *rpc, rpc_cb cb, struct SYMLINK2args *args, void *private_data); /* * Call NFS2/MKDIR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is MKDIR2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct MKDIR2args; EXTERN int rpc_nfs2_mkdir_async(struct rpc_context *rpc, rpc_cb cb, struct MKDIR2args *args, void *private_data); /* * Call NFS2/RMDIR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is RMDIR2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct RMDIR2args; EXTERN int rpc_nfs2_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct RMDIR2args *args, void *private_data); /* * Call NFS2/READDIR * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is READDIR2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct READDIR2args; EXTERN int rpc_nfs2_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct READDIR2args *args, void *private_data); /* * Call NFS2/STATFS * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is STATFS2res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct STATFS2args; EXTERN int rpc_nfs2_statfs_async(struct rpc_context *rpc, rpc_cb cb, struct STATFS2args *args, void *private_data); /* * RQUOTA FUNCTIONS */ EXTERN char *rquotastat_to_str(int error); EXTERN int rquotastat_to_errno(int error); /* * Call RQUOTA1/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_rquota1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call RQUOTA1/GETQUOTA * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is GETQUOTA1res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_rquota1_getquota_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, int uid, void *private_data); /* * Call RQUOTA1/GETACTIVEQUOTA * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is GETQUOTA1res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_rquota1_getactivequota_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, int uid, void *private_data); /* * Call RQUOTA2/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_rquota2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call RQUOTA2/GETQUOTA * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is GETQUOTA1res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_rquota2_getquota_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, int type, int uid, void *private_data); /* * Call RQUOTA2/GETACTIVEQUOTA * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is GETQUOTA1res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_rquota2_getactivequota_async(struct rpc_context *rpc, rpc_cb cb, char *exportname, int type, int uid, void *private_data); /* * NFSACL functions */ /* * Call NFSACL/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call NFSACL/GETACL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is GETACL3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct GETACL3args; EXTERN int rpc_nfsacl_getacl_async(struct rpc_context *rpc, rpc_cb cb, struct GETACL3args *args, void *private_data); /* * Call NFSACL/SETACL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is SETACL3res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct SETACL3args; EXTERN int rpc_nfsacl_setacl_async(struct rpc_context *rpc, rpc_cb cb, struct SETACL3args *args, void *private_data); /* * NLM functions */ EXTERN char *nlmstat4_to_str(int stat); /* * Call NLM/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_nlm4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call NLM/TEST * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NLM4_TESTres *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NLM4_TESTargs; EXTERN int rpc_nlm4_test_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_TESTargs *args, void *private_data); /* * Call NLM/LOCK * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NLM4_LOCKres *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NLM4_LOCKargs; EXTERN int rpc_nlm4_lock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_LOCKargs *args, void *private_data); /* * Call NLM/CANCEL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NLM4_CANCres *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NLM4_CANCargs; EXTERN int rpc_nlm4_cancel_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_CANCargs *args, void *private_data); /* * Call NLM/UNLOCK * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NLM4_UNLOCKres *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NLM4_UNLOCKargs; EXTERN int rpc_nlm4_unlock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_UNLOCKargs *args, void *private_data); /* * NSM functions */ EXTERN char *nsmstat1_to_str(int stat); /* * Call NSM/NULL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_nsm1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call NSM/STAT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NSM1_STATres *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NSM1_STATargs; EXTERN int rpc_nsm1_stat_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_STATargs *args, void *private_data); /* * Call NSM/MON * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NSM1_MONres *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NSM1_MONargs; EXTERN int rpc_nsm1_mon_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_MONargs *args, void *private_data); /* * Call NSM/UNMON * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NSM1_UNMONres *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NSM1_UNMONargs; EXTERN int rpc_nsm1_unmon_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_UNMONargs *args, void *private_data); /* * Call NSM/UNMONALL * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NSM1_UNMONALLres *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NSM1_UNMONALLargs; EXTERN int rpc_nsm1_unmonall_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_UNMONALLargs *args, void *private_data); /* * Call NSM/SIMUCRASH * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_nsm1_simucrash_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call NSM/NOTIFY * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct NSM1_NOTIFYargs; EXTERN int rpc_nsm1_notify_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_NOTIFYargs *args, void *private_data); /* * NFS v4 FUNCTIONS */ EXTERN char *nfsstat4_to_str(int error); EXTERN int nfsstat4_to_errno(int error); /* * Call NFS4/NULL * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_nfs4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data); /* * Call NFS4/COMPOUND * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is COMPOUND4res *. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ struct COMPOUND4args; EXTERN int rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb, struct COMPOUND4args *args, void *private_data); /* * Call /NULL * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * RPC_STATUS_SUCCESS : We got a successful response from the server. * data is NULL. * RPC_STATUS_ERROR : The command failed with an error. * data is the error string. * RPC_STATUS_CANCEL : The command was cancelled. * data is NULL. */ EXTERN int rpc_null_async(struct rpc_context *rpc, int program, int version, rpc_cb cb, void *private_data); #ifdef __cplusplus } #endif #endif libnfs-libnfs-4.0.0/include/nfsc/libnfs-zdr.h000066400000000000000000000150561343063627400210610ustar00rootroot00000000000000/* Copyright (C) 2012 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ /* * This file contains definitions for the built in ZDR implementation. * This is a very limited ZDR subset that can only marshal to/from a momory buffer, * i.e. zdrmem_create() buffers. * It aims to be compatible with normal rpcgen generated functions. */ /************************************************************ * Definitions copied from RFC 5531 * and slightly modified. ************************************************************/ #ifndef _LIBNFS_ZDR_H_ #define _LIBNFS_ZDR_H_ #ifdef WIN32 #ifndef CADDR_T_DEFINED #define CADDR_T_DEFINED typedef char *caddr_t; #endif #endif #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define _RPC_RPC_H 1 #define _RPC_ZDR_H 1 #define _RPC_AUTH_H 1 /* we dont need these */ typedef void CLIENT; struct svc_req { int _dummy_; }; typedef void SVCXPRT; #define ZDR_INLINE(...) NULL #define IZDR_PUT_U_LONG(...) assert(0) #define IZDR_GET_U_LONG(...) (assert(0), 0) #define IZDR_PUT_LONG(...) assert(0) #define IZDR_GET_LONG(...) (assert(0), 0) #define IZDR_PUT_BOOL(...) assert(0) #define IZDR_GET_BOOL(...) (assert(0), 0) #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif enum zdr_op { ZDR_ENCODE = 0, ZDR_DECODE = 1 }; struct zdr_mem; struct ZDR { enum zdr_op x_op; caddr_t buf; int size; int pos; struct zdr_mem *mem; }; typedef struct ZDR ZDR; typedef uint32_t u_int; typedef uint32_t enum_t; typedef uint32_t bool_t; typedef uint32_t (*zdrproc_t) (ZDR *, void *,...); #define AUTH_NONE 0 #define AUTH_NULL 0 #define AUTH_UNIX 1 struct opaque_auth { uint32_t oa_flavor; caddr_t oa_base; uint32_t oa_length; }; extern struct opaque_auth _null_auth; struct AUTH { struct opaque_auth ah_cred; struct opaque_auth ah_verf; caddr_t ah_private; }; #define RPC_MSG_VERSION 2 enum msg_type { CALL = 0, REPLY = 1 }; enum reply_stat { MSG_ACCEPTED=0, MSG_DENIED=1 }; enum accept_stat { SUCCESS = 0, PROG_UNAVAIL = 1, PROG_MISMATCH = 2, PROC_UNAVAIL = 3, GARBAGE_ARGS = 4, SYSTEM_ERR = 5 }; enum reject_stat { RPC_MISMATCH = 0, AUTH_ERROR = 1 }; enum auth_stat { AUTH_OK=0, /* * failed at remote end */ AUTH_BADCRED = 1, /* bogus credentials (seal broken) */ AUTH_REJECTEDCRED = 2, /* client should begin new session */ AUTH_BADVERF = 3, /* bogus verifier (seal broken) */ AUTH_REJECTEDVERF = 4, /* verifier expired or was replayed */ AUTH_TOOWEAK = 5, /* rejected due to security reasons */ /* * failed locally */ AUTH_INVALIDRESP = 6, /* bogus response verifier */ AUTH_FAILED = 7 /* some unknown reason */ }; struct call_body { uint32_t rpcvers; uint32_t prog; uint32_t vers; uint32_t proc; struct opaque_auth cred; struct opaque_auth verf; void *args; }; struct accepted_reply { struct opaque_auth verf; uint32_t stat; union { struct { caddr_t where; zdrproc_t proc; } results; struct { uint32_t low; uint32_t high; } mismatch_info; } reply_data; }; struct rejected_reply { enum reject_stat stat; union { struct { uint32_t low; uint32_t high; } mismatch_info; enum auth_stat stat; } reject_data; }; struct reply_body { uint32_t stat; union { struct accepted_reply areply; struct rejected_reply rreply; } reply; }; struct rpc_msg { uint32_t xid; uint32_t direction; union { struct call_body cbody; struct reply_body rbody; } body; }; #define zdrmem_create libnfs_zdrmem_create void libnfs_zdrmem_create(ZDR *zdrs, const caddr_t addr, uint32_t size, enum zdr_op xop); #define zdr_destroy libnfs_zdr_destroy void libnfs_zdr_destroy(ZDR *zdrs); #define zdr_bytes libnfs_zdr_bytes bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize); #define zdr_u_int libnfs_zdr_u_int #define zdr_uint32_t libnfs_zdr_u_int bool_t libnfs_zdr_u_int(ZDR *zdrs, uint32_t *u); #define zdr_int libnfs_zdr_int #define zdr_int32_t libnfs_zdr_int bool_t libnfs_zdr_int(ZDR *zdrs, int32_t *i); #define zdr_uint64_t libnfs_zdr_uint64_t bool_t libnfs_zdr_uint64_t(ZDR *zdrs, uint64_t *u); #define zdr_int64_t libnfs_zdr_int64_t bool_t libnfs_zdr_int64_t(ZDR *zdrs, int64_t *i); #define zdr_enum libnfs_zdr_enum bool_t libnfs_zdr_enum(ZDR *zdrs, enum_t *e); #define zdr_bool libnfs_zdr_bool bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b); #define zdr_void libnfs_zdr_void bool_t libnfs_zdr_void(ZDR *zdrs, void *); #define zdr_pointer libnfs_zdr_pointer bool_t libnfs_zdr_pointer(ZDR *zdrs, char **objp, uint32_t size, zdrproc_t proc); #define zdr_opaque libnfs_zdr_opaque bool_t libnfs_zdr_opaque(ZDR *zdrs, char *objp, uint32_t size); #define zdr_string libnfs_zdr_string bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize); #define zdr_array libnfs_zdr_array bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc); #define zdr_setpos libnfs_zdr_setpos bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos); #define zdr_getpos libnfs_zdr_getpos uint32_t libnfs_zdr_getpos(ZDR *zdrs); #define zdr_free libnfs_zdr_free void libnfs_zdr_free(zdrproc_t proc, char *objp); struct rpc_context; #define zdr_callmsg libnfs_zdr_callmsg bool_t libnfs_zdr_callmsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg); #define zdr_replymsg libnfs_zdr_replymsg bool_t libnfs_zdr_replymsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg); #define authnone_create libnfs_authnone_create struct AUTH *libnfs_authnone_create(void); #define authunix_create libnfs_authunix_create struct AUTH *libnfs_authunix_create(const char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups); #define authunix_create_default libnfs_authunix_create_default struct AUTH *libnfs_authunix_create_default(void); #define auth_destroy libnfs_auth_destroy void libnfs_auth_destroy(struct AUTH *auth); #ifdef __cplusplus } #endif #endif libnfs-libnfs-4.0.0/include/nfsc/libnfs.h000077500000000000000000001561621343063627400202730ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ /* * This is the high-level interface to access NFS resources using posix-like * functions. */ #ifndef _LIBNFS_H_ #define _LIBNFS_H_ #include #if defined(__ANDROID__) || defined(AROS) \ || ( defined(__APPLE__) && defined(__MACH__) ) #include #else #include #endif #ifdef __cplusplus extern "C" { #endif #define LIBNFS_FEATURE_READAHEAD #define LIBNFS_FEATURE_PAGECACHE #define LIBNFS_FEATURE_DEBUG #define NFS_BLKSIZE 4096 #define NFS_PAGECACHE_DEFAULT_TTL 5 struct nfs_context; struct rpc_context; struct nfs_url { char *server; char *path; char *file; }; #if defined(WIN32) #define EXTERN __declspec( dllexport ) #else #ifndef EXTERN #define EXTERN #endif #endif #ifdef WIN32 #ifdef HAVE_FUSE_H #include #else struct statvfs { uint32_t f_bsize; uint32_t f_frsize; uint64_t f_blocks; uint64_t f_bfree; uint64_t f_bavail; uint32_t f_files; uint32_t f_ffree; uint32_t f_favail; uint32_t f_fsid; uint32_t f_flag; uint32_t f_namemax; }; #endif #if !defined(__MINGW32__) struct utimbuf { time_t actime; time_t modtime; }; #endif #define R_OK 4 #define W_OK 2 #define X_OK 1 #endif /* * Used for interfacing the async version of the api into an external * eventsystem. * * nfs_get_fd() returns the file descriptor for the context we need to * listen for events from. * * nfs_which_events() returns which events that we need to poll for. * This is a combination of the POLLIN and POLLOUT flags. * * nfs_service() This function should be called once there are events triggered * for the filedescriptor. This function takes POLLIN/POLLOUT/POLLHUP/POLLERR * as arguments. * This function returns 0 on success or -1 on error. If it returns -1 it * means that the socket is in an unrecoverable error state (disconnected?) * and that no further commands can be used. * When this happens the application should destroy the now errored context * re-create a new context and reconnect. * * * If using the async interface and nfs timeouts, i.e. nfs_set_timeout(), * you will need to ensure to call nfs_service() on a regular basis as * the timeout handling is done as part of that function. * For example calling nfs_service() with revents == 0 once every 100ms * or so from your event loop. * You only need this for the async interface. The sync interface already * do this in their built-in event loops. */ EXTERN int nfs_get_fd(struct nfs_context *nfs); EXTERN int nfs_which_events(struct nfs_context *nfs); EXTERN int nfs_service(struct nfs_context *nfs, int revents); /* * Returns the number of commands in-flight. Can be used by the application * to check if there are any more responses we are awaiting for the server * or if the connection is completely idle. */ EXTERN int nfs_queue_length(struct nfs_context *nfs); /* * Used if you need different credentials than the default for the current user. */ struct AUTH; EXTERN void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth); /* * Used if you need to bind to a specific interface. * Only available on platforms that support SO_BINDTODEVICE. */ EXTERN void nfs_set_interface(struct nfs_context *nfs, const char *ifname); /* * When an operation failed, this function can extract a detailed error string. */ EXTERN char *nfs_get_error(struct nfs_context *nfs); /* * Callback for all ASYNC nfs functions */ typedef void (*nfs_cb)(int err, struct nfs_context *nfs, void *data, void *private_data); /* * Callback for all ASYNC rpc functions */ typedef void (*rpc_cb)(struct rpc_context *rpc, int status, void *data, void *private_data); /* * NFS CONTEXT. */ /* * Create an NFS context. * Function returns * NULL : Failed to create a context. * *nfs : A pointer to an nfs context. */ EXTERN struct nfs_context *nfs_init_context(void); /* * Destroy an nfs context. */ EXTERN void nfs_destroy_context(struct nfs_context *nfs); /* * URL parsing functions. * These functions all parse a URL of the form * nfs://server/path/file?argv=val[&arg=val]* * and returns a nfs_url. * * Apart from parsing the URL the functions will also update * the nfs context to reflect settings controlled via url arguments. * * Current URL arguments are : * tcp-syncnt= : Number of SYNs to send during the session establish * before failing setting up the TCP connection to the * server. * uid= : UID value to use when talking to the server. * default is 65534 on Windows and getuid() on unixen. * gid= : GID value to use when talking to the server. * default is 65534 on Windows and getgid() on unixen. * readahead= : Enable readahead for files and set the maximum amount * of readahead to bytes. * auto-traverse-mounts=<0|1> * : Should libnfs try to traverse across nested mounts * automatically or not. Default is 1 == enabled. * dircache=<0|1> : Disable/enable directory caching. Enabled by default. * autoreconnect=<-1|0|>=1> * : Control the auto-reconnect behaviour to the NFS session. * -1 : Try to reconnect forever on session failures. * Just like normal NFS clients do. * 0 : Disable auto-reconnect completely and immediately * return a failure to the application. * >=1 : Retry to connect back to the server this many * times before failing and returing an error back * to the application. * version=<3|4> : NFS version. Default is 3. * Version 4 is not yet functional. Do not use. * nfsport= : Use this port for NFS instead of using the portmapper. * mountport= : Use this port for the MOUNT protocol instead of * using portmapper. This argument is ignored for NFSv4 * as it does not use the MOUNT protocol. */ /* * Parse a complete NFS URL including, server, path and * filename. Fail if any component is missing. */ EXTERN struct nfs_url *nfs_parse_url_full(struct nfs_context *nfs, const char *url); /* * Parse an NFS URL, but do not split path and file. File * in the resulting struct remains NULL. */ EXTERN struct nfs_url *nfs_parse_url_dir(struct nfs_context *nfs, const char *url); /* * Parse an NFS URL, but do not fail if file, path or even server is missing. * Check elements of the resulting struct for NULL. */ EXTERN struct nfs_url *nfs_parse_url_incomplete(struct nfs_context *nfs, const char *url); /* * Free the URL struct returned by the nfs_parse_url_* functions. */ EXTERN void nfs_destroy_url(struct nfs_url *url); struct nfsfh; /* * Get the maximum supported READ3 size by the server */ EXTERN uint64_t nfs_get_readmax(struct nfs_context *nfs); /* * Get the maximum supported WRITE3 size by the server */ EXTERN uint64_t nfs_get_writemax(struct nfs_context *nfs); /* * MODIFY CONNECT PARAMETERS */ EXTERN void nfs_set_tcp_syncnt(struct nfs_context *nfs, int v); EXTERN void nfs_set_uid(struct nfs_context *nfs, int uid); EXTERN void nfs_set_gid(struct nfs_context *nfs, int gid); EXTERN void nfs_set_pagecache(struct nfs_context *nfs, uint32_t v); EXTERN void nfs_set_pagecache_ttl(struct nfs_context *nfs, uint32_t v); EXTERN void nfs_set_readahead(struct nfs_context *nfs, uint32_t v); EXTERN void nfs_set_debug(struct nfs_context *nfs, int level); EXTERN void nfs_set_dircache(struct nfs_context *nfs, int enabled); EXTERN void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries); /* * Set NFS version. Supported versions are * NFS_V3 (default) * NFS_V4 */ EXTERN int nfs_set_version(struct nfs_context *nfs, int version); /* * Invalidate the pagecache */ EXTERN void nfs_pagecache_invalidate(struct nfs_context *nfs, struct nfsfh *nfsfh); /* * Initialize the pagecache */ EXTERN void nfs_pagecache_init(struct nfs_context *nfs, struct nfsfh *nfsfh); /* * MOUNT THE EXPORT */ /* * Async nfs mount. * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_mount_async(struct nfs_context *nfs, const char *server, const char *exportname, nfs_cb cb, void *private_data); /* * Sync nfs mount. * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_mount(struct nfs_context *nfs, const char *server, const char *exportname); /* * UNMOUNT THE EXPORT */ /* * Async nfs umount. * For NFSv4 this is a NO-OP. * For NFSv3 this function returns unregisters the mount from the MOUNT Daemon. * * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data); /* * Sync nfs umount. * For NFSv4 this is a NO-OP. * For NFSv3 this function returns unregisters the mount from the MOUNT Daemon. * * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_umount(struct nfs_context *nfs); /* * STAT() */ /* * Async stat() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is struct stat * * -errno : An error occured. * data is the error string. */ /* This function is deprecated. Use nfs_stat64_async() instead */ struct stat; EXTERN int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync stat() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ /* This function is deprecated. Use nfs_stat64() instead */ #ifdef WIN32 EXTERN int nfs_stat(struct nfs_context *nfs, const char *path, struct __stat64 *st); #else EXTERN int nfs_stat(struct nfs_context *nfs, const char *path, struct stat *st); #endif /* nfs_stat64 * 64 bit version if stat. All fields are always 64bit. * Use these functions instead of nfs_stat[_async](), especially if you * have weird stat structures. */ /* * STAT() */ struct nfs_stat_64 { uint64_t nfs_dev; uint64_t nfs_ino; uint64_t nfs_mode; uint64_t nfs_nlink; uint64_t nfs_uid; uint64_t nfs_gid; uint64_t nfs_rdev; uint64_t nfs_size; uint64_t nfs_blksize; uint64_t nfs_blocks; uint64_t nfs_atime; uint64_t nfs_mtime; uint64_t nfs_ctime; uint64_t nfs_atime_nsec; uint64_t nfs_mtime_nsec; uint64_t nfs_ctime_nsec; uint64_t nfs_used; }; /* * Async stat() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is struct nfs_stat_64 * * -errno : An error occured. * data is the error string. */ EXTERN int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync stat() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_stat64(struct nfs_context *nfs, const char *path, struct nfs_stat_64 *st); /* * Async stat() * * Like stat except if the destination is a symbolic link, it acts on the * symbolic link itself. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is struct nfs_stat_64 * * -errno : An error occured. * data is the error string. */ EXTERN int nfs_lstat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync stat() * * Like stat except if the destination is a symbolic link, it acts on the * symbolic link itself. * * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_lstat64(struct nfs_context *nfs, const char *path, struct nfs_stat_64 *st); /* * FSTAT() */ /* * Async fstat(nfsfh *) * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is struct stat * * -errno : An error occured. * data is the error string. */ /* This function is deprecated. Use nfs_fstat64_async() instead */ EXTERN int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); /* * Sync fstat(nfsfh *) * Function returns * 0 : The operation was successful. * -errno : The command failed. */ #ifdef WIN32 EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct __stat64 *st); #else EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *st); #endif /* nfs_fstat64 * 64 bit version of fstat. All fields are always 64bit. * Use these functions instead of nfs_fstat[_async](), especially if you * have weird stat structures. */ /* * FSTAT() */ /* * Async fstat(nfsfh *) * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is struct stat * * -errno : An error occured. * data is the error string. */ EXTERN int nfs_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); /* * Sync fstat(nfsfh *) * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_fstat64(struct nfs_context *nfs, struct nfsfh *nfsfh, struct nfs_stat_64 *st); /* * UMASK() never blocks, so no special aync/async versions are available */ /* * Sync umask() * Function returns the old mask. */ EXTERN uint16_t nfs_umask(struct nfs_context *nfs, uint16_t mask); /* * OPEN() */ /* * Async open() * * mode is a combination of the flags : * O_RDONLY, O_WRONLY, O_RDWR , O_SYNC, O_APPEND, O_TRUNC, O_NOFOLLOW, * O_CREAT * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * Supported flags are * O_NOFOLLOW * O_APPEND * O_CREAT * O_RDONLY * O_WRONLY * O_RDWR * O_SYNC * O_TRUNC (Only valid with O_RDWR or O_WRONLY. Ignored otherwise.) * * When the callback is invoked, status indicates the result: * 0 : Success. * data is a struct *nfsfh; * The nfsfh is close using nfs_close(). * -errno : An error occured. * data is the error string. */ EXTERN int nfs_open_async(struct nfs_context *nfs, const char *path, int flags, nfs_cb cb, void *private_data); EXTERN int nfs_open2_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data); /* * Sync open() * Function returns * 0 : The operation was successful. *nfsfh is filled in. * -errno : The command failed. */ EXTERN int nfs_open(struct nfs_context *nfs, const char *path, int flags, struct nfsfh **nfsfh); EXTERN int nfs_open2(struct nfs_context *nfs, const char *path, int flags, int mode, struct nfsfh **nfsfh); /* * CLOSE */ /* * Async close(nfsfh) * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); /* * Sync close(nfsfh) * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_close(struct nfs_context *nfs, struct nfsfh *nfsfh); /* * PREAD() */ /* * Async pread() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * >=0 : Success. * status is numer of bytes read. * data is a pointer to the returned data. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data); /* * Sync pread() * Function returns * >=0 : numer of bytes read. * -errno : An error occured. */ EXTERN int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, void *buf); /* * READ() */ /* * Async read() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * >=0 : Success. * status is numer of bytes read. * data is a pointer to the returned data. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, nfs_cb cb, void *private_data); /* * Sync read() * Function returns * >=0 : numer of bytes read. * -errno : An error occured. */ EXTERN int nfs_read(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, void *buf); /* * PWRITE() */ /* * Async pwrite() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * >=0 : Success. * status is numer of bytes written. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, const void *buf, nfs_cb cb, void *private_data); /* * Sync pwrite() * Function returns * >=0 : numer of bytes written. * -errno : An error occured. */ EXTERN int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, const void *buf); /* * WRITE() */ /* * Async write() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * >=0 : Success. * status is numer of bytes written. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, const void *buf, nfs_cb cb, void *private_data); /* * Sync write() * Function returns * >=0 : numer of bytes written. * -errno : An error occured. */ EXTERN int nfs_write(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, const void *buf); /* * LSEEK() */ /* * Async lseek() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * >=0 : Success. * data is uint64_t * for the current position. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, nfs_cb cb, void *private_data); /* * Sync lseek() * Function returns * >=0 : numer of bytes read. * -errno : An error occured. */ EXTERN int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, uint64_t *current_offset); /* * LOCKF() */ /* * Async lockf() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ enum nfs4_lock_op { NFS4_F_LOCK = 0, NFS4_F_TLOCK = 1, NFS4_F_ULOCK = 2, NFS4_F_TEST = 3, }; EXTERN int nfs_lockf_async(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_lock_op op, uint64_t count, nfs_cb cb, void *private_data); /* * Sync lockf() * Function returns * 0 : Success. * -errno : An error occured. */ EXTERN int nfs_lockf(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_lock_op op, uint64_t count); /* * FCNTL() */ /* * Async fcntl() * Supported commands are : * NFS4_F_SETLK * NFS4_F_SETLKW * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ enum nfs4_fcntl_op { NFS4_F_SETLK = 0, NFS4_F_SETLKW, }; struct nfs4_flock { int l_type; /* F_RDLCK, F_WRLCK or F_UNLCK */ int l_whence; /* SEEK_SET, SEEK_CUR or SEEK_END */ uint32_t l_pid; uint64_t l_start; uint64_t l_len; }; EXTERN int nfs_fcntl_async(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_fcntl_op cmd, void *arg, nfs_cb cb, void *private_data); /* * Sync lockf() * Function returns * 0 : Success. * -errno : An error occured. */ EXTERN int nfs_fcntl(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_fcntl_op cmd, void *arg); /* * FSYNC() */ /* * Async fsync() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data); /* * Sync fsync() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_fsync(struct nfs_context *nfs, struct nfsfh *nfsfh); /* * TRUNCATE() */ /* * Async truncate() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data); /* * Sync truncate() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_truncate(struct nfs_context *nfs, const char *path, uint64_t length); /* * FTRUNCATE() */ /* * Async ftruncate() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length, nfs_cb cb, void *private_data); /* * Sync ftruncate() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_ftruncate(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length); /* * MKDIR() */ /* * Async mkdir() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync mkdir() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_mkdir(struct nfs_context *nfs, const char *path); /* * Async mkdir2() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_mkdir2_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); /* * Sync mkdir2() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_mkdir2(struct nfs_context *nfs, const char *path, int mode); /* * RMDIR() */ /* * Async rmdir() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync rmdir() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_rmdir(struct nfs_context *nfs, const char *path); /* * CREAT() */ /* * Async creat() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is a struct *nfsfh; * -errno : An error occured. * data is the error string. */ EXTERN int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); /* * Sync creat() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_creat(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh); /* * Async create() * * Same as nfs_creat_async but allows passing flags: * O_NOFOLLOW * O_APPEND * O_SYNC * O_EXCL * O_TRUNC * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is a struct *nfsfh; * -errno : An error occured. * data is the error string. */ EXTERN int nfs_create_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data); /* * Sync create() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_create(struct nfs_context *nfs, const char *path, int flags, int mode, struct nfsfh **nfsfh); /* * MKNOD() */ /* * Async mknod() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev, nfs_cb cb, void *private_data); /* * Sync mknod() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_mknod(struct nfs_context *nfs, const char *path, int mode, int dev); /* * UNLINK() */ /* * Async unlink() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync unlink() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_unlink(struct nfs_context *nfs, const char *path); /* * OPENDIR() */ struct nfsdir; /* * Async opendir() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When struct nfsdir * is returned, this resource is closed/freed by calling nfs_closedir() * * When the callback is invoked, status indicates the result: * 0 : Success. * data is struct nfsdir * * -errno : An error occured. * data is the error string. */ EXTERN int nfs_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync opendir() * Function returns * 0 : Success * -errno : An error occured. */ EXTERN int nfs_opendir(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir); /* * READDIR() */ struct nfsdirent { struct nfsdirent *next; char *name; uint64_t inode; /* Some extra fields we get for free through the READDIRPLUS3 call. You need libnfs-raw-nfs.h for type/mode constants */ uint32_t type; /* NF3REG, NF3DIR, NF3BLK, ... */ uint32_t mode; uint64_t size; struct timeval atime; struct timeval mtime; struct timeval ctime; uint32_t uid; uint32_t gid; uint32_t nlink; uint64_t dev; uint64_t rdev; uint64_t blksize; uint64_t blocks; uint64_t used; uint32_t atime_nsec; uint32_t mtime_nsec; uint32_t ctime_nsec; }; /* * nfs_readdir() never blocks, so no special sync/async versions are available */ EXTERN struct nfsdirent *nfs_readdir(struct nfs_context *nfs, struct nfsdir *nfsdir); /* * SEEKDIR() */ /* * This function will never block so there is no need for an async version. */ EXTERN void nfs_seekdir(struct nfs_context *nfs, struct nfsdir *nfsdir, long loc); /* * TELLDIR() */ /* * On success, nfs_telldir() will return a location as a value >= 0. * On failure, nfs_telldir() will return -1. * * This function will never block so there is no need for an async version. */ EXTERN long nfs_telldir(struct nfs_context *nfs, struct nfsdir *nfsdir); /* * REWINDDIR() */ /* * nfs_rewinddir() cancel all previous nfs_readdir() side effects. * This function will never block so there is no need for an async version. */ EXTERN void nfs_rewinddir(struct nfs_context *nfs, struct nfsdir *nfsdir); /* * CLOSEDIR() */ /* * nfs_closedir() never blocks, so no special sync/async versions are available */ EXTERN void nfs_closedir(struct nfs_context *nfs, struct nfsdir *nfsdir); /* * CHDIR() */ /* * Async chdir() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL; * -errno : An error occured. * data is the error string. */ EXTERN int nfs_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync chdir() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_chdir(struct nfs_context *nfs, const char *path); /* * GETCWD() */ /* * nfs_getcwd() never blocks, so no special sync/async versions are available */ /* * Sync getcwd() * This function returns a pointer to the current working directory. * This pointer is only stable until the next [f]chdir or when the * context is destroyed. * * Function returns * 0 : The operation was successful and *cwd is filled in. * -errno : The command failed. */ EXTERN void nfs_getcwd(struct nfs_context *nfs, const char **cwd); /* * STATVFS() */ struct nfs_statvfs_64 { uint64_t f_bsize; uint64_t f_frsize; uint64_t f_blocks; uint64_t f_bfree; uint64_t f_bavail; uint64_t f_files; uint64_t f_ffree; uint64_t f_favail; uint64_t f_fsid; uint64_t f_flag; uint64_t f_namemax; }; /* * Async statvfs() * This function is deprecated. Use nfs_statvfs64_async() instead. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is struct statvfs * * -errno : An error occured. * data is the error string. */ struct statvfs; EXTERN int nfs_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync statvfs() * This function is deprecated. Use nfs_statvfs64() instead. * * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs); /* * Async statvfs64() * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is struct nfs_statvfs_64 * * -errno : An error occured. * data is the error string. */ EXTERN int nfs_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync statvfs64() * * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_statvfs64(struct nfs_context *nfs, const char *path, struct nfs_statvfs_64 *svfs); /* * READLINK() */ /* * Async readlink() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is a char * * data is only valid during the callback and is automatically freed * when the callback returns. * -errno : An error occured. * data is the error string. */ EXTERN int nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync readlink() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_readlink(struct nfs_context *nfs, const char *path, char *buf, int bufsize); /* * Sync readlink2() * Function returns * 0 : The operation was successful. * -errno : The command failed. * *bufptr : NULL if the command failed, otherwise the contents of the symlink. * The caller must free the buffer. */ EXTERN int nfs_readlink2(struct nfs_context *nfs, const char *path, char **bufptr); /* * CHMOD() */ /* * Async chmod() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_chmod_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); /* * Sync chmod() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_chmod(struct nfs_context *nfs, const char *path, int mode); /* * Async chmod() * * Like chmod except if the destination is a symbolic link, it acts on the * symbolic link itself. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_lchmod_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); /* * Sync chmod() * * Like chmod except if the destination is a symbolic link, it acts on the * symbolic link itself. * * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_lchmod(struct nfs_context *nfs, const char *path, int mode); /* * FCHMOD() */ /* * Async fchmod() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs_cb cb, void *private_data); /* * Sync fchmod() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_fchmod(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode); /* * CHOWN() */ /* * Async chown() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_chown_async(struct nfs_context *nfs, const char *path, int uid, int gid, nfs_cb cb, void *private_data); /* * Sync chown() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_chown(struct nfs_context *nfs, const char *path, int uid, int gid); /* * Async chown() * * Like chown except if the destination is a symbolic link, it acts on the * symbolic link itself. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_lchown_async(struct nfs_context *nfs, const char *path, int uid, int gid, nfs_cb cb, void *private_data); /* * Sync chown() * * Like chown except if the destination is a symbolic link, it acts on the * symbolic link itself. * * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_lchown(struct nfs_context *nfs, const char *path, int uid, int gid); /* * FCHOWN() */ /* * Async fchown() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid, nfs_cb cb, void *private_data); /* * Sync fchown() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_fchown(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid); /* * UTIMES() */ /* * Async utimes() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_utimes_async(struct nfs_context *nfs, const char *path, struct timeval *times, nfs_cb cb, void *private_data); /* * Sync utimes() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_utimes(struct nfs_context *nfs, const char *path, struct timeval *times); /* * Async utimes() * * Like utimes except if the destination is a symbolic link, it acts on the * symbolic link itself. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_lutimes_async(struct nfs_context *nfs, const char *path, struct timeval *times, nfs_cb cb, void *private_data); /* * Sync utimes() * * Like utimes except if the destination is a symbolic link, it acts on the * symbolic link itself. * * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_lutimes(struct nfs_context *nfs, const char *path, struct timeval *times); /* * UTIME() */ /* * Async utime() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ struct utimbuf; EXTERN int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data); /* * Sync utime() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_utime(struct nfs_context *nfs, const char *path, struct utimbuf *times); /* * ACCESS() */ /* * Async access() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data); /* * Sync access() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_access(struct nfs_context *nfs, const char *path, int mode); /* * ACCESS2() */ /* * Async access2() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * >= 0 : A mask of R_OK, W_OK and X_OK indicating which permissions are * available. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* * Sync access() * Function returns * >= 0 : A mask of R_OK, W_OK and X_OK indicating which permissions are * available. * -errno : The command failed. */ EXTERN int nfs_access2(struct nfs_context *nfs, const char *path); /* * SYMLINK() */ /* * Async symlink() * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_symlink_async(struct nfs_context *nfs, const char *target, const char *linkname, nfs_cb cb, void *private_data); /* * Sync symlink() * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_symlink(struct nfs_context *nfs, const char *target, const char *linkname); /* * RENAME() */ /* * Async rename(, ) * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); /* * Sync rename(, ) * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_rename(struct nfs_context *nfs, const char *oldpath, const char *newpath); /* * LINK() */ /* * Async link(, ) * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is NULL * -errno : An error occured. * data is the error string. */ EXTERN int nfs_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); /* * Sync link(, ) * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_link(struct nfs_context *nfs, const char *oldpath, const char *newpath); /* * GETEXPORTS() */ /* * Async getexports() * NOTE: You must include 'libnfs-raw-mount.h' to get the definitions of the * returned structures. * * This function will return the list of exports from an NFS server. * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. * <0 : An error occured when trying to queue the command. * The callback will not be invoked. * * When the callback is invoked, status indicates the result: * 0 : Success. * data is a pointer to an exports pointer: * exports export = *(exports *)data; * -errno : An error occured. * data is the error string. */ EXTERN int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb cb, void *private_data); /* * Sync getexports() * Function returns * NULL : something failed * exports export : a linked list of exported directories * * returned data must be freed by calling mount_free_export_list(exportnode); */ EXTERN struct exportnode *mount_getexports(const char *server); EXTERN void mount_free_export_list(struct exportnode *exports); struct nfs_server_list { struct nfs_server_list *next; char *addr; }; /* * Sync find_local_servers() * This function will probe all local networks for NFS server. * This function will block for one second while awaiting for all nfs servers * to respond. * * Function returns * NULL : something failed * * struct nfs_server_list : a linked list of all discovered servers * * returned data must be freed by nfs_free_srvr_list(srv); */ struct nfs_server_list *nfs_find_local_servers(void); void free_nfs_srvr_list(struct nfs_server_list *srv); /* * sync nfs_set_timeout() * This function sets the timeout used for nfs rpc calls. * * Function returns nothing. * * int milliseconds : timeout to be applied in milliseconds (-1 no timeout) * timeouts must currently be set in whole seconds, * i.e. units of 1000 */ EXTERN void nfs_set_timeout(struct nfs_context *nfs, int milliseconds); /* * sync nfs_get_timeout() * This function gets the timeout used for nfs rpc calls. * * Function returns * -1 : No timeout applied * > 0 : Timeout in milliseconds */ EXTERN int nfs_get_timeout(struct nfs_context *nfs); /* * Set the client name for NFSv4. */ EXTERN void nfs4_set_client_name(struct nfs_context *nfs, const char *id); /* * Set the client verifier for NFSv4. * This an 8 byte array of random data. */ EXTERN void nfs4_set_verifier(struct nfs_context *nfs, const char *verifier); #ifdef __cplusplus } #endif #endif /* !_LIBNFS_H_ */ libnfs-libnfs-4.0.0/include/slist.h000066400000000000000000000032021343063627400172020ustar00rootroot00000000000000/* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifndef _LIBNFS_SLIST_H_ #define _LIBNFS_SLIST_H_ #define LIBNFS_LIST_ADD(list, item) \ do { \ (item)->next = (*list); \ (*list) = (item); \ } while (0); #define LIBNFS_LIST_ADD_END(list, item) \ if ((*list) == NULL) { \ LIBNFS_LIST_ADD((list), (item)); \ } else { \ void *head = (*list); \ while ((*list)->next) \ (*list) = (*list)->next; \ (*list)->next = (item); \ (item)->next = NULL; \ (*list) = head; \ } #define LIBNFS_LIST_REMOVE(list, item) \ if ((*list) == (item)) { \ (*list) = (item)->next; \ } else { \ void *head = (*list); \ while ((*list)->next && (*list)->next != (item)) \ (*list) = (*list)->next; \ if ((*list)->next != NULL) { \ (*list)->next = (*list)->next->next; \ } \ (*list) = head; \ } #endif /* !_LIBNFS_SLIST_H_ */ libnfs-libnfs-4.0.0/include/win32/000077500000000000000000000000001343063627400166405ustar00rootroot00000000000000libnfs-libnfs-4.0.0/include/win32/win32_compat.h000077500000000000000000000076531343063627400213340ustar00rootroot00000000000000/* Copyright (c) 2006 by Dan Kennedy. Copyright (c) 2006 by Juliusz Chroboczek. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*Adaptions by memphiz@xbmc.org*/ #ifndef win32_COMPAT_H_ #define win32_COMPAT_H_ #define NO_IPv6 1 #include #include #include #include #include #include #include typedef unsigned long fsblkcnt_t; typedef unsigned long fsfilcnt_t; typedef unsigned int uid_t; typedef unsigned int gid_t; typedef int socklen_t; #ifndef S_IRUSR #define S_IRUSR 0000400 #define S_IWUSR 0000200 #define S_IXUSR 0000100 #endif #ifndef S_IRWXG #define S_IRWXG 0000070 /* RWX mask for group */ #define S_IRGRP 0000040 #define S_IWGRP 0000020 #define S_IXGRP 0000010 #define S_IRWXO 0000007 /* RWX mask for other */ #define S_IROTH 0000004 #define S_IWOTH 0000002 #define S_IXOTH 0000001 #endif #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #define F_GETFL 3 #define F_SETFL 4 #ifndef S_IFLNK #define S_IFLNK 0xA000 /* Link */ #endif #ifndef F_RDLCK #define F_RDLCK 0 #define F_WRLCK 1 #define F_UNLCK 2 #endif #ifndef S_IFIFO #define S_IFIFO 0x1000 /* FIFO */ #endif #ifndef S_IFBLK #define S_IFBLK 0x3000 /* Block: Is this ever set under w32? */ #endif #ifndef S_IFSOCK #define S_IFSOCK 0x0 /* not defined in mingw either */ #endif #ifndef major #define major(a) 0 #endif #ifndef minor #define minor(a) 0 #endif #ifndef O_NONBLOCK #define O_NONBLOCK 0x40000000 #endif #ifndef O_SYNC #define O_SYNC 0 #endif #ifndef O_NOFOLLOW #define O_NOFOLLOW 00400000 #endif #define MSG_DONTWAIT 0 #define ssize_t SSIZE_T #if(_WIN32_WINNT < 0x0600) #define POLLIN 0x0001 /* There is data to read */ #define POLLPRI 0x0002 /* There is urgent data to read */ #define POLLOUT 0x0004 /* Writing now will not block */ #define POLLERR 0x0008 /* Error condition */ #define POLLHUP 0x0010 /* Hung up */ #define POLLNVAL 0x0020 /* Invalid request: fd not open */ struct pollfd { SOCKET fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ }; #endif #define close closesocket #define ioctl ioctlsocket #ifndef ESTALE #define ESTALE 116 #endif /* Wrapper macros to call misc. functions win32 is missing */ #define poll(x, y, z) win32_poll(x, y, z) #define snprintf sprintf_s #define inet_pton(x,y,z) win32_inet_pton(x,y,z) #define open(x, y, z) _open(x, y, z) #ifndef lseek #define lseek(x, y, z) _lseek(x, y, z) #endif #define read(x, y, z) _read(x, y, z) #define write(x, y, z) _write(x, y, z) int getpid(void); int win32_inet_pton(int af, const char * src, void * dst); int win32_poll(struct pollfd *fds, unsigned int nfsd, int timeout); int win32_gettimeofday(struct timeval *tv, struct timezone *tz); #ifdef __MINGW32__ # define win32_gettimeofday mingw_gettimeofday #endif #define DllExport #endif//win32_COMPAT_H_ libnfs-libnfs-4.0.0/lib/000077500000000000000000000000001343063627400150215ustar00rootroot00000000000000libnfs-libnfs-4.0.0/lib/CMakeLists.txt000066400000000000000000000012661343063627400175660ustar00rootroot00000000000000set(SOURCES init.c libnfs.c libnfs-sync.c libnfs-zdr.c nfs_v3.c nfs_v4.c pdu.c socket.c) add_library(nfs ${SOURCES}) target_link_libraries(nfs PUBLIC ${core_DEPENDS}) target_include_directories(nfs PUBLIC ../include) set_target_properties(nfs PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${SOVERSION}) add_dependencies(nfs ${core_DEPENDS}) add_definitions("-D_U_=__attribute__((unused))") install(TARGETS nfs EXPORT nfs RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib) libnfs-libnfs-4.0.0/lib/Makefile.am000066400000000000000000000016011343063627400170530ustar00rootroot00000000000000AM_CFLAGS=$(WARN_CFLAGS) lib_LTLIBRARIES = libnfs.la libnfs_la_CPPFLAGS = -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/mount \ -I$(abs_top_srcdir)/nfs \ -I$(abs_top_srcdir)/nfs4 \ -I$(abs_top_srcdir)/nlm \ -I$(abs_top_srcdir)/nsm \ -I$(abs_top_srcdir)/portmap \ -I$(abs_top_srcdir)/rquota \ -I$(abs_top_srcdir)/win32 \ "-D_U_=__attribute__((unused))" libnfs_la_SOURCES = \ init.c \ libnfs.c \ libnfs-sync.c \ libnfs-zdr.c \ nfs_v3.c \ nfs_v4.c \ pdu.c \ socket.c \ ../win32/win32_compat.c SOCURRENT=13 SOREVISION=0 SOAGE=0 libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE) libnfs_la_LIBADD = \ ../mount/libmount.la \ ../nfs/libnfs.la \ ../nfs4/libnfs4.la \ ../nlm/libnlm.la \ ../nsm/libnsm.la \ ../portmap/libportmap.la \ ../rquota/librquota.la libnfs-libnfs-4.0.0/lib/init.c000066400000000000000000000231121343063627400161270ustar00rootroot00000000000000/* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #include #include #include #include #include #include #include "slist.h" #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" uint64_t rpc_current_time(void) { #ifdef HAVE_CLOCK_GETTIME struct timespec tp; clock_gettime(CLOCK_MONOTONIC_COARSE, &tp); return (uint64_t)tp.tv_sec * 1000 + tp.tv_nsec / 1000000; #else return (uint64_t)time(NULL) * 1000; #endif } struct rpc_context *rpc_init_context(void) { struct rpc_context *rpc; static uint32_t salt = 0; unsigned int i; rpc = malloc(sizeof(struct rpc_context)); if (rpc == NULL) { return NULL; } memset(rpc, 0, sizeof(struct rpc_context)); rpc->magic = RPC_CONTEXT_MAGIC; rpc->auth = authunix_create_default(); if (rpc->auth == NULL) { free(rpc); return NULL; } // Add PID to rpc->xid for easier debugging, making sure to cast // pid to 32-bit type to avoid invalid left-shifts. rpc->xid = salt + rpc_current_time() + ((uint32_t)getpid() << 16); salt += 0x01000000; rpc->fd = -1; rpc->tcp_syncnt = RPC_PARAM_UNDEFINED; rpc->pagecache_ttl = NFS_PAGECACHE_DEFAULT_TTL; #if defined(WIN32) || defined(ANDROID) rpc->uid = 65534; rpc->gid = 65534; #else rpc->uid = getuid(); rpc->gid = getgid(); #endif rpc_reset_queue(&rpc->outqueue); for (i = 0; i < HASHES; i++) rpc_reset_queue(&rpc->waitpdu[i]); /* Default is no timeout */ rpc->timeout = -1; return rpc; } struct rpc_context *rpc_init_server_context(int s) { struct rpc_context *rpc; rpc = malloc(sizeof(struct rpc_context)); if (rpc == NULL) { return NULL; } memset(rpc, 0, sizeof(struct rpc_context)); rpc->magic = RPC_CONTEXT_MAGIC; rpc->is_server_context = 1; rpc->fd = s; rpc->is_connected = 1; rpc->is_udp = rpc_is_udp_socket(rpc); rpc_reset_queue(&rpc->outqueue); return rpc; } static uint32_t round_to_power_of_two(uint32_t x) { uint32_t power = 1; while (power < x) { power <<= 1; } return power; } void rpc_set_pagecache(struct rpc_context *rpc, uint32_t v) { assert(rpc->magic == RPC_CONTEXT_MAGIC); v = MAX(rpc->pagecache, round_to_power_of_two(v)); RPC_LOG(rpc, 2, "pagecache set to %d pages of size %d", v, NFS_BLKSIZE); rpc->pagecache = v; } void rpc_set_pagecache_ttl(struct rpc_context *rpc, uint32_t v) { if (v) { RPC_LOG(rpc, 2, "set pagecache ttl to %d seconds\n", v); } else { RPC_LOG(rpc, 2, "set pagecache ttl to infinite"); } rpc->pagecache_ttl = v; } void rpc_set_readahead(struct rpc_context *rpc, uint32_t v) { uint32_t min_pagecache; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (v) { v = MAX(NFS_BLKSIZE, round_to_power_of_two(v)); } RPC_LOG(rpc, 2, "readahead set to %d byte", v); rpc->readahead = v; min_pagecache = (2 * v) / NFS_BLKSIZE; if (rpc->pagecache < min_pagecache) { /* current pagecache implementation needs a pagecache bigger * than the readahead size to avoid collisions */ rpc_set_pagecache(rpc, min_pagecache); } } #ifdef HAVE_SO_BINDTODEVICE void rpc_set_interface(struct rpc_context *rpc, const char *ifname) { /* * This only copies the interface information into the RPC * structure. It doesn't stop whatever interface is being used. The * connection needs to be restarted for that happen. In other words, * set this before you connect. */ assert(rpc->magic == RPC_CONTEXT_MAGIC); if (ifname) { /* * Allow at one-less character just-in-case IFNAMSIZ for * the defined platform does not include the NUL-terminator. */ strncpy(rpc->ifname, ifname, sizeof(rpc->ifname) - 1); } } #endif void rpc_set_debug(struct rpc_context *rpc, int level) { assert(rpc->magic == RPC_CONTEXT_MAGIC); rpc->debug = level; } struct rpc_context *rpc_init_udp_context(void) { struct rpc_context *rpc; rpc = rpc_init_context(); if (rpc != NULL) { rpc->is_udp = 1; } return rpc; } void rpc_set_auth(struct rpc_context *rpc, struct AUTH *auth) { assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->auth != NULL) { auth_destroy(rpc->auth); } rpc->auth = auth; } static void rpc_set_uid_gid(struct rpc_context *rpc, int uid, int gid) { if (uid != rpc->uid || gid != rpc->gid) { struct AUTH *auth = libnfs_authunix_create("libnfs", uid, gid, 0, NULL); if (auth != NULL) { rpc_set_auth(rpc, auth); rpc->uid = uid; rpc->gid = gid; } } } void rpc_set_uid(struct rpc_context *rpc, int uid) { rpc_set_uid_gid(rpc, uid, rpc->gid); } void rpc_set_gid(struct rpc_context *rpc, int gid) { rpc_set_uid_gid(rpc, rpc->uid, gid); } void rpc_set_error(struct rpc_context *rpc, const char *error_string, ...) { va_list ap; char *old_error_string = rpc->error_string; assert(rpc->magic == RPC_CONTEXT_MAGIC); va_start(ap, error_string); rpc->error_string = malloc(1024); vsnprintf(rpc->error_string, 1024, error_string, ap); va_end(ap); RPC_LOG(rpc, 1, "error: %s", rpc->error_string); if (old_error_string != NULL) { free(old_error_string); } } char *rpc_get_error(struct rpc_context *rpc) { assert(rpc->magic == RPC_CONTEXT_MAGIC); return rpc->error_string; } static void rpc_purge_all_pdus(struct rpc_context *rpc, int status, const char *error) { struct rpc_queue outqueue; struct rpc_pdu *pdu; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); /* Remove all entries from each queue before cancellation to prevent * the callbacks manipulating entries that are about to be removed. * * This code assumes that the callbacks will not enqueue any new * pdus when called. */ outqueue = rpc->outqueue; rpc_reset_queue(&rpc->outqueue); while ((pdu = outqueue.head) != NULL) { outqueue.head = pdu->next; pdu->next = NULL; pdu->cb(rpc, status, (void *) error, pdu->private_data); rpc_free_pdu(rpc, pdu); } for (i = 0; i < HASHES; i++) { struct rpc_queue waitqueue = rpc->waitpdu[i]; rpc_reset_queue(&rpc->waitpdu[i]); while((pdu = waitqueue.head) != NULL) { waitqueue.head = pdu->next; pdu->next = NULL; pdu->cb(rpc, status, (void *) error, pdu->private_data); rpc_free_pdu(rpc, pdu); } } assert(!rpc->outqueue.head); for (i = 0; i < HASHES; i++) assert(!rpc->waitpdu[i].head); } void rpc_error_all_pdus(struct rpc_context *rpc, const char *error) { rpc_purge_all_pdus(rpc, RPC_STATUS_ERROR, error); } static void rpc_free_fragment(struct rpc_fragment *fragment) { if (fragment->data != NULL) { free(fragment->data); } free(fragment); } void rpc_free_all_fragments(struct rpc_context *rpc) { assert(rpc->magic == RPC_CONTEXT_MAGIC); while (rpc->fragments != NULL) { struct rpc_fragment *fragment = rpc->fragments; rpc->fragments = fragment->next; rpc_free_fragment(fragment); } } int rpc_add_fragment(struct rpc_context *rpc, char *data, uint32_t size) { struct rpc_fragment *fragment; assert(rpc->magic == RPC_CONTEXT_MAGIC); fragment = malloc(sizeof(struct rpc_fragment)); if (fragment == NULL) { return -1; } fragment->size = size; fragment->data = malloc(fragment->size); if(fragment->data == NULL) { free(fragment); return -1; } memcpy(fragment->data, data, fragment->size); LIBNFS_LIST_ADD_END(&rpc->fragments, fragment); return 0; } void rpc_destroy_context(struct rpc_context *rpc) { assert(rpc->magic == RPC_CONTEXT_MAGIC); rpc_purge_all_pdus(rpc, RPC_STATUS_CANCEL, NULL); rpc_free_all_fragments(rpc); if (rpc->auth) { auth_destroy(rpc->auth); rpc->auth =NULL; } if (rpc->fd != -1) { close(rpc->fd); } if (rpc->error_string != NULL) { free(rpc->error_string); rpc->error_string = NULL; } free(rpc->inbuf); rpc->inbuf = NULL; rpc->magic = 0; free(rpc); } void rpc_set_timeout(struct rpc_context *rpc, int timeout) { assert(rpc->magic == RPC_CONTEXT_MAGIC); rpc->timeout = timeout; } int rpc_get_timeout(struct rpc_context *rpc) { assert(rpc->magic == RPC_CONTEXT_MAGIC); return rpc->timeout; } int rpc_register_service(struct rpc_context *rpc, int program, int version, struct service_proc *procs, int num_procs) { struct rpc_endpoint *endpoint; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (!rpc->is_server_context) { rpc_set_error(rpc, "Not a server context."); return -1; } endpoint = malloc(sizeof(*endpoint)); if (endpoint == NULL) { rpc_set_error(rpc, "Out of memory: Failed to allocate endpoint " "structure"); return -1; } endpoint->program = program; endpoint->version = version; endpoint->procs = procs; endpoint->num_procs = num_procs; endpoint->next = rpc->endpoints; rpc->endpoints = endpoint; return 0; } libnfs-libnfs-4.0.0/lib/libnfs-sync.c000066400000000000000000001315021343063627400174160ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ /* * High level api to nfs filesystems */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NET_IF_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #if defined(__ANDROID__) && !defined(HAVE_SYS_STATVFS_H) #define statvfs statfs #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SOCKIO_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" #include "libnfs-raw-nfs.h" #include "libnfs-private.h" struct sync_cb_data { int is_finished; int status; uint64_t offset; void *return_data; int return_int; const char *call; }; static void wait_for_reply(struct rpc_context *rpc, struct sync_cb_data *cb_data) { struct pollfd pfd; int revents; int ret; assert(rpc->magic == RPC_CONTEXT_MAGIC); while (!cb_data->is_finished) { pfd.fd = rpc_get_fd(rpc); pfd.events = rpc_which_events(rpc); pfd.revents = 0; ret = poll(&pfd, 1, 100); if (ret < 0) { rpc_set_error(rpc, "Poll failed"); revents = -1; } else { revents = pfd.revents; } if (rpc_service(rpc, revents) < 0) { if (revents != -1) rpc_set_error(rpc, "rpc_service failed"); cb_data->status = -EIO; break; } if (rpc_get_fd(rpc) == -1) { rpc_set_error(rpc, "Socket closed"); break; } } } static void wait_for_nfs_reply(struct nfs_context *nfs, struct sync_cb_data *cb_data) { struct pollfd pfd; int revents; int ret; while (!cb_data->is_finished) { pfd.fd = nfs_get_fd(nfs); pfd.events = nfs_which_events(nfs); pfd.revents = 0; ret = poll(&pfd, 1, 100); if (ret < 0) { nfs_set_error(nfs, "Poll failed"); revents = -1; } else { revents = pfd.revents; } if (nfs_service(nfs, revents) < 0) { if (revents != -1) nfs_set_error(nfs, "nfs_service failed"); cb_data->status = -EIO; break; } } } /* * connect to the server and mount the export */ static void mount_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); return; } } int nfs_mount(struct nfs_context *nfs, const char *server, const char *export) { struct sync_cb_data cb_data; struct rpc_context *rpc = nfs_get_rpc_context(nfs); assert(rpc->magic == RPC_CONTEXT_MAGIC); cb_data.is_finished = 0; if (nfs_mount_async(nfs, server, export, mount_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_mount_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); /* Dont want any more callbacks even if the socket is closed */ rpc->connect_cb = NULL; /* Ensure that no RPCs are pending. In error case (e.g. timeout in * wait_for_nfs_reply()) we can disconnect; in success case all RPCs * are completed by definition. */ if (cb_data.status) { rpc_disconnect(rpc, "failed mount"); } return cb_data.status; } /* * unregister the mount */ static void umount_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); return; } } int nfs_umount(struct nfs_context *nfs) { struct sync_cb_data cb_data; struct rpc_context *rpc = nfs_get_rpc_context(nfs); assert(rpc->magic == RPC_CONTEXT_MAGIC); cb_data.is_finished = 0; if (nfs_umount_async(nfs, umount_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_umount_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); /* Dont want any more callbacks even if the socket is closed */ rpc->connect_cb = NULL; /* Ensure that no RPCs are pending. In error case (e.g. timeout in * wait_for_nfs_reply()) we can disconnect; in success case all RPCs * are completed by definition. */ if (cb_data.status) { rpc_disconnect(rpc, "failed mount"); } return cb_data.status; } /* * stat() */ static void stat_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "stat call failed with \"%s\"", (char *)data); return; } #ifdef WIN32 memcpy(cb_data->return_data, data, sizeof(struct __stat64)); #else memcpy(cb_data->return_data, data, sizeof(struct stat)); #endif } int #ifdef WIN32 nfs_stat(struct nfs_context *nfs, const char *path, struct __stat64 *st) #else nfs_stat(struct nfs_context *nfs, const char *path, struct stat *st) #endif { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = st; if (nfs_stat_async(nfs, path, stat_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_stat_async failed"); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } static void stat64_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "stat call failed with \"%s\"", (char *)data); return; } memcpy(cb_data->return_data, data, sizeof(struct nfs_stat_64)); } int nfs_stat64(struct nfs_context *nfs, const char *path, struct nfs_stat_64 *st) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = st; if (nfs_stat64_async(nfs, path, stat64_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_stat64_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } int nfs_lstat64(struct nfs_context *nfs, const char *path, struct nfs_stat_64 *st) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = st; if (nfs_lstat64_async(nfs, path, stat64_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_lstat64_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * open() */ static void open_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; struct nfsfh *fh, **nfsfh; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "open call failed with \"%s\"", (char *)data); return; } fh = data; nfsfh = cb_data->return_data; *nfsfh = fh; } int nfs_open(struct nfs_context *nfs, const char *path, int flags, struct nfsfh **nfsfh) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = nfsfh; if (nfs_open_async(nfs, path, flags, open_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_open_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } int nfs_open2(struct nfs_context *nfs, const char *path, int flags, int mode, struct nfsfh **nfsfh) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = nfsfh; if (nfs_open2_async(nfs, path, flags, mode, open_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_open2_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * chdir() */ static void chdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "chdir call failed with \"%s\"", (char *)data); return; } } int nfs_chdir(struct nfs_context *nfs, const char *path) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_chdir_async(nfs, path, chdir_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_chdir_async failed with %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * pread() */ static void pread_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; char *buffer; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "%s call failed with \"%s\"", cb_data->call, (char *)data); return; } buffer = cb_data->return_data; memcpy(buffer, (char *)data, status); } int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, void *buffer) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = buffer; cb_data.call = "pread"; if (nfs_pread_async(nfs, nfsfh, offset, count, pread_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_pread_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * read() */ int nfs_read(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, void *buffer) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = buffer; cb_data.call = "read"; if (nfs_read_async(nfs, nfsfh, count, pread_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_read_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * close() */ static void close_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "close call failed with \"%s\"", (char *)data); return; } } int nfs_close(struct nfs_context *nfs, struct nfsfh *nfsfh) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_close_async(nfs, nfsfh, close_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_close_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * fstat() */ int #ifdef WIN32 nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct __stat64 *st) #else nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *st) #endif { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = st; if (nfs_fstat_async(nfs, nfsfh, stat_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_fstat_async failed"); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * fstat64() */ int nfs_fstat64(struct nfs_context *nfs, struct nfsfh *nfsfh, struct nfs_stat_64 *st) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = st; if (nfs_fstat64_async(nfs, nfsfh, stat64_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_fstat64_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * pwrite() */ static void pwrite_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) nfs_set_error(nfs, "%s call failed with \"%s\"", cb_data->call, (char *)data); } int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, const void *buf) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.call = "pwrite"; if (nfs_pwrite_async(nfs, nfsfh, offset, count, buf, pwrite_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_pwrite_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * write() */ int nfs_write(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, const void *buf) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.call = "write"; if (nfs_write_async(nfs, nfsfh, count, buf, pwrite_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_write_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * fsync() */ static void fsync_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "fsync call failed with \"%s\"", (char *)data); return; } } int nfs_fsync(struct nfs_context *nfs, struct nfsfh *nfsfh) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_fsync_async(nfs, nfsfh, fsync_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_fsync_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * ftruncate() */ static void ftruncate_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "ftruncate call failed with \"%s\"", (char *)data); return; } } int nfs_ftruncate(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_ftruncate_async(nfs, nfsfh, length, ftruncate_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_ftruncate_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * truncate() */ static void truncate_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "truncate call failed with \"%s\"", (char *)data); return; } } int nfs_truncate(struct nfs_context *nfs, const char *path, uint64_t length) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_truncate_async(nfs, path, length, truncate_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_ftruncate_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * mkdir() */ static void mkdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "mkdir call failed with \"%s\"", (char *)data); return; } } int nfs_mkdir(struct nfs_context *nfs, const char *path) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_mkdir_async(nfs, path, mkdir_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_mkdir_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } int nfs_mkdir2(struct nfs_context *nfs, const char *path, int mode) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_mkdir2_async(nfs, path, mode, mkdir_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_mkdir2_async failed"); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * rmdir() */ static void rmdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "rmdir call failed with \"%s\"", (char *)data); return; } } int nfs_rmdir(struct nfs_context *nfs, const char *path) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_rmdir_async(nfs, path, rmdir_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_rmdir_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * creat() */ static void creat_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; struct nfsfh *fh, **nfsfh; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "creat call failed with \"%s\"", (char *)data); return; } fh = data; nfsfh = cb_data->return_data; *nfsfh = fh; } int nfs_create(struct nfs_context *nfs, const char *path, int flags, int mode, struct nfsfh **nfsfh) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = nfsfh; if (nfs_create_async(nfs, path, flags, mode, creat_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_create_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } int nfs_creat(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh) { return nfs_create(nfs, path, 0, mode, nfsfh); } /* * mknod() */ static void mknod_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "mknod call failed with \"%s\"", (char *)data); return; } } int nfs_mknod(struct nfs_context *nfs, const char *path, int mode, int dev) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_mknod_async(nfs, path, mode, dev, mknod_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_creat_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * unlink() */ static void unlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "unlink call failed with \"%s\"", (char *)data); return; } } int nfs_unlink(struct nfs_context *nfs, const char *path) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_unlink_async(nfs, path, unlink_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_unlink_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * opendir() */ static void opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; struct nfsdir *dir, **nfsdir; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "opendir call failed with \"%s\"", (char *)data); return; } dir = data; nfsdir = cb_data->return_data; *nfsdir = dir; } int nfs_opendir(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = nfsdir; if (nfs_opendir_async(nfs, path, opendir_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_opendir_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * lseek() */ static void lseek_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "lseek call failed with \"%s\"", nfs_get_error(nfs)); return; } if (cb_data->return_data != NULL) { memcpy(cb_data->return_data, data, sizeof(uint64_t)); } } int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, uint64_t *current_offset) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = current_offset; if (nfs_lseek_async(nfs, nfsfh, offset, whence, lseek_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_lseek_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * lockf() */ static void lockf_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "lockf call failed with \"%s\"", nfs_get_error(nfs)); return; } } int nfs_lockf(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_lock_op cmd, uint64_t count) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_lockf_async(nfs, nfsfh, cmd, count, lockf_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_lockf_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * fcntl() */ static void fcntl_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "fcntl call failed with \"%s\"", nfs_get_error(nfs)); return; } } int nfs_fcntl(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_fcntl_op cmd, void *arg) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_fcntl_async(nfs, nfsfh, cmd, arg, fcntl_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_fcntl_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * statvfs() */ static void statvfs_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "statvfs call failed with \"%s\"", (char *)data); return; } memcpy(cb_data->return_data, data, sizeof(struct statvfs)); } int nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = svfs; if (nfs_statvfs_async(nfs, path, statvfs_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_statvfs_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * statvfs64() */ static void statvfs64_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "statvfs64 call failed with \"%s\"", (char *)data); return; } memcpy(cb_data->return_data, data, sizeof(struct nfs_statvfs_64)); } int nfs_statvfs64(struct nfs_context *nfs, const char *path, struct nfs_statvfs_64 *svfs) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = svfs; if (nfs_statvfs64_async(nfs, path, statvfs64_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_statvfs64_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * readlink() */ static void readlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "readlink call failed with \"%s\"", (char *)data); return; } if (strlen(data) > (size_t)cb_data->return_int) { nfs_set_error(nfs, "Too small buffer for readlink"); cb_data->status = -ENAMETOOLONG; return; } memcpy(cb_data->return_data, data, strlen(data)+1); } int nfs_readlink(struct nfs_context *nfs, const char *path, char *buf, int bufsize) { struct sync_cb_data cb_data; cb_data.is_finished = 0; cb_data.return_data = buf; cb_data.return_int = bufsize; if (nfs_readlink_async(nfs, path, readlink_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_readlink_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } static void readlink2_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; char **bufptr; char *buf; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "readlink call failed with \"%s\"", (char *)data); return; } buf = strdup(data); if (buf == NULL) { cb_data->status = errno ? -errno : -ENOMEM; return; } bufptr = cb_data->return_data; if (bufptr) *bufptr = buf; } int nfs_readlink2(struct nfs_context *nfs, const char *path, char **bufptr) { struct sync_cb_data cb_data; *bufptr = NULL; cb_data.is_finished = 0; cb_data.return_data = bufptr; if (nfs_readlink_async(nfs, path, readlink2_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_readlink_async failed"); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * chmod() */ static void chmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "chmod call failed with \"%s\"", (char *)data); return; } } int nfs_chmod(struct nfs_context *nfs, const char *path, int mode) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_chmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_chmod_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } int nfs_lchmod(struct nfs_context *nfs, const char *path, int mode) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_lchmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_lchmod_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * fchmod() */ static void fchmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "fchmod call failed with \"%s\"", (char *)data); return; } } int nfs_fchmod(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_fchmod_async(nfs, nfsfh, mode, fchmod_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_fchmod_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * chown() */ static void chown_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "chown call failed with \"%s\"", (char *)data); return; } } int nfs_chown(struct nfs_context *nfs, const char *path, int uid, int gid) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_chown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_chown_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * lchown() */ int nfs_lchown(struct nfs_context *nfs, const char *path, int uid, int gid) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_lchown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_lchown_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * fchown() */ static void fchown_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "fchown call failed with \"%s\"", (char *)data); return; } } int nfs_fchown(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_fchown_async(nfs, nfsfh, uid, gid, fchown_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_fchown_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * utimes() */ static void utimes_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "utimes call failed with \"%s\"", (char *)data); return; } } int nfs_utimes(struct nfs_context *nfs, const char *path, struct timeval *times) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_utimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_utimes_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } int nfs_lutimes(struct nfs_context *nfs, const char *path, struct timeval *times) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_lutimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_lutimes_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * utime() */ static void utime_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "utime call failed with \"%s\"", (char *)data); return; } } int nfs_utime(struct nfs_context *nfs, const char *path, struct utimbuf *times) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_utime_async(nfs, path, times, utime_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_utimes_async failed"); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * access() */ static void access_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "access call failed with \"%s\"", (char *)data); return; } } int nfs_access(struct nfs_context *nfs, const char *path, int mode) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_access_async(nfs, path, mode, access_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_access_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * access2() */ static void access2_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "access2 call failed with \"%s\"", (char *)data); return; } } int nfs_access2(struct nfs_context *nfs, const char *path) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_access2_async(nfs, path, access2_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_access2_async failed. %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * symlink() */ static void symlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "symlink call failed with \"%s\"", (char *)data); return; } } int nfs_symlink(struct nfs_context *nfs, const char *target, const char *linkname) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_symlink_async(nfs, target, linkname, symlink_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_symlink_async failed: %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * rename() */ static void rename_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "rename call failed with \"%s\"", (char *)data); return; } } int nfs_rename(struct nfs_context *nfs, const char *oldpath, const char *newpath) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_rename_async(nfs, oldpath, newpath, rename_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_rename_async failed: %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } /* * link() */ static void link_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; cb_data->is_finished = 1; cb_data->status = status; if (status < 0) { nfs_set_error(nfs, "link call failed with \"%s\"", (char *)data); return; } } int nfs_link(struct nfs_context *nfs, const char *oldpath, const char *newpath) { struct sync_cb_data cb_data; cb_data.is_finished = 0; if (nfs_link_async(nfs, oldpath, newpath, link_cb, &cb_data) != 0) { nfs_set_error(nfs, "nfs_link_async failed: %s", nfs_get_error(nfs)); return -1; } wait_for_nfs_reply(nfs, &cb_data); return cb_data.status; } void mount_getexports_cb(struct rpc_context *mount_context, int status, void *data, void *private_data) { struct sync_cb_data *cb_data = private_data; exports export; assert(mount_context->magic == RPC_CONTEXT_MAGIC); cb_data->is_finished = 1; cb_data->status = status; cb_data->return_data = NULL; if (status != 0) { rpc_set_error(mount_context, "mount/export call failed with " "\"%s\"", (char *)data); return; } export = *(exports *)data; while (export != NULL) { exports new_export; new_export = malloc(sizeof(*new_export)); memset(new_export, 0, sizeof(*new_export)); new_export->ex_dir = strdup(export->ex_dir); new_export->ex_next = cb_data->return_data; cb_data->return_data = new_export; export = export->ex_next; } } struct exportnode * mount_getexports(const char *server) { struct sync_cb_data cb_data; struct rpc_context *rpc; cb_data.is_finished = 0; cb_data.return_data = NULL; rpc = rpc_init_context(); if (mount_getexports_async(rpc, server, mount_getexports_cb, &cb_data) != 0) { rpc_destroy_context(rpc); return NULL; } wait_for_reply(rpc, &cb_data); rpc_destroy_context(rpc); return cb_data.return_data; } void mount_free_export_list(struct exportnode *exp) { struct exportnode *tmp; while ((tmp = exp)) { exp = exp->ex_next; free(tmp->ex_dir); free(tmp); } } void free_nfs_srvr_list(struct nfs_server_list *srv) { while (srv != NULL) { struct nfs_server_list *next = srv->next; free(srv->addr); free(srv); srv = next; } } struct nfs_list_data { int status; struct nfs_server_list *srvrs; }; void callit_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { struct nfs_list_data *srv_data = private_data; struct sockaddr *sin; char hostdd[16]; struct nfs_server_list *srvr; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status == RPC_STATUS_CANCEL) { return; } if (status != 0) { srv_data->status = -1; return; } sin = rpc_get_recv_sockaddr(rpc); if (sin == NULL) { rpc_set_error(rpc, "failed to get sockaddr in CALLIT callback"); srv_data->status = -1; return; } if (getnameinfo(sin, sizeof(struct sockaddr_in), &hostdd[0], sizeof(hostdd), NULL, 0, NI_NUMERICHOST) < 0) { rpc_set_error(rpc, "getnameinfo failed in CALLIT callback"); srv_data->status = -1; return; } /* check for dupes */ for (srvr = srv_data->srvrs; srvr; srvr = srvr->next) { if (!strcmp(hostdd, srvr->addr)) { return; } } srvr = malloc(sizeof(struct nfs_server_list)); if (srvr == NULL) { rpc_set_error(rpc, "Malloc failed when allocating server " "structure"); srv_data->status = -1; return; } srvr->addr = strdup(hostdd); if (srvr->addr == NULL) { rpc_set_error(rpc, "Strdup failed when allocating server " "structure"); free(srvr); srv_data->status = -1; return; } srvr->next = srv_data->srvrs; srv_data->srvrs = srvr; } #ifdef WIN32 static int send_nfsd_probes(struct rpc_context *rpc, INTERFACE_INFO *InterfaceList, int numIfs, struct nfs_list_data *data) { int i=0; assert(rpc->magic == RPC_CONTEXT_MAGIC); for(i = 0; i < numIfs; i++) { SOCKADDR *pAddress; char bcdd[16]; unsigned long nFlags = 0; pAddress = (SOCKADDR *) & (InterfaceList[i].iiBroadcastAddress); if(pAddress->sa_family != AF_INET) continue; nFlags = InterfaceList[i].iiFlags; if (!(nFlags & IFF_UP)) { continue; } if (nFlags & IFF_LOOPBACK) { continue; } if (!(nFlags & IFF_BROADCAST)) { continue; } if (getnameinfo(pAddress, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) { continue; } if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) { return -1; } if (rpc_pmap2_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) { return -1; } } return 0; } struct nfs_server_list * nfs_find_local_servers(void) { struct rpc_context *rpc; struct nfs_list_data data = {0, NULL}; struct timeval tv_start, tv_current; int loop; struct pollfd pfd; INTERFACE_INFO InterfaceList[20]; unsigned long nBytesReturned; int nNumInterfaces = 0; rpc = rpc_init_udp_context(); if (rpc == NULL) { return NULL; } if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) { rpc_destroy_context(rpc); return NULL; } if (WSAIoctl(rpc_get_fd(rpc), SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) { return NULL; } nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO); for (loop=0; loop<3; loop++) { if (send_nfsd_probes(rpc, InterfaceList, nNumInterfaces, &data) != 0) { rpc_destroy_context(rpc); return NULL; } win32_gettimeofday(&tv_start, NULL); for(;;) { int mpt; pfd.fd = rpc_get_fd(rpc); pfd.events = rpc_which_events(rpc); win32_gettimeofday(&tv_current, NULL); mpt = 1000 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000) + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000); if (poll(&pfd, 1, mpt) < 0) { free_nfs_srvr_list(data.srvrs); rpc_destroy_context(rpc); return NULL; } if (pfd.revents == 0) { break; } if (rpc_service(rpc, pfd.revents) < 0) { break; } } } rpc_destroy_context(rpc); if (data.status != 0) { free_nfs_srvr_list(data.srvrs); return NULL; } return data.srvrs; } #else static int send_nfsd_probes(struct rpc_context *rpc, struct ifconf *ifc, struct nfs_list_data *data) { char *ptr; assert(rpc->magic == RPC_CONTEXT_MAGIC); for (ptr =(char *)(ifc->ifc_buf); ptr < (char *)(ifc->ifc_buf) + ifc->ifc_len; ) { struct ifreq ifr; char bcdd[16]; memcpy(&ifr, ptr, sizeof(struct ifreq)); #ifdef HAVE_SOCKADDR_LEN if (ifr.ifr_addr.sa_len > sizeof(struct sockaddr)) { ptr += sizeof(ifr.ifr_name) + ifr.ifr_addr.sa_len; } else { ptr += sizeof(ifr.ifr_name) + sizeof(struct sockaddr); } #else ptr += sizeof(struct ifreq); #endif if (ifr.ifr_addr.sa_family != AF_INET) { continue; } if (ioctl(rpc_get_fd(rpc), SIOCGIFFLAGS, &ifr) < 0) { return -1; } if (!(ifr.ifr_flags & IFF_UP)) { continue; } if (ifr.ifr_flags & IFF_LOOPBACK) { continue; } if (!(ifr.ifr_flags & IFF_BROADCAST)) { continue; } if (ioctl(rpc_get_fd(rpc), SIOCGIFBRDADDR, &ifr) < 0) { continue; } if (getnameinfo(&ifr.ifr_broadaddr, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) { continue; } if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) { return -1; } if (rpc_pmap2_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) { return -1; } } return 0; } struct nfs_server_list * nfs_find_local_servers(void) { struct rpc_context *rpc; struct nfs_list_data data = {0, NULL}; struct timeval tv_start, tv_current; struct ifconf ifc; int size, loop; struct pollfd pfd; rpc = rpc_init_udp_context(); if (rpc == NULL) { return NULL; } if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) { rpc_destroy_context(rpc); return NULL; } /* get list of all interfaces */ size = sizeof(struct ifreq); ifc.ifc_buf = NULL; ifc.ifc_len = size; while(ifc.ifc_len > (size - sizeof(struct ifreq))) { size *= 2; free(ifc.ifc_buf); ifc.ifc_len = size; ifc.ifc_buf = malloc(size); memset(ifc.ifc_buf, 0, size); if (ioctl(rpc_get_fd(rpc), SIOCGIFCONF, (caddr_t)&ifc) < 0) { rpc_destroy_context(rpc); free(ifc.ifc_buf); return NULL; } } for (loop=0; loop<3; loop++) { if (send_nfsd_probes(rpc, &ifc, &data) != 0) { rpc_destroy_context(rpc); free(ifc.ifc_buf); return NULL; } gettimeofday(&tv_start, NULL); for(;;) { int mpt; pfd.fd = rpc_get_fd(rpc); pfd.events = rpc_which_events(rpc); gettimeofday(&tv_current, NULL); mpt = 1000 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000) + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000); if (poll(&pfd, 1, mpt) < 0) { free_nfs_srvr_list(data.srvrs); rpc_destroy_context(rpc); return NULL; } if (pfd.revents == 0) { break; } if (rpc_service(rpc, pfd.revents) < 0) { break; } } } free(ifc.ifc_buf); rpc_destroy_context(rpc); if (data.status != 0) { free_nfs_srvr_list(data.srvrs); return NULL; } return data.srvrs; } #endif//WIN32 libnfs-libnfs-4.0.0/lib/libnfs-win32.def000066400000000000000000000107301343063627400177170ustar00rootroot00000000000000LIBRARY libnfs EXPORTS mount_free_export_list mount_getexports mount_getexports_async nfs_find_local_servers free_nfs_srvr_list nfs_access nfs_access_async nfs_chdir nfs_chmod nfs_chmod_async nfs_chown nfs_chown_async nfs_close nfs_close_async nfs_closedir nfs_creat nfs_creat_async nfs_destroy_context nfs_fchmod nfs_fchmod_async nfs_fchown nfs_fchown_async nfs_fcntl nfs_fcntl_async nfs_fstat nfs_fstat_async nfs_fsync nfs_fsync_async nfs_ftruncate nfs_ftruncate_async nfs_get_error nfs_get_fd nfs_get_readmax nfs_get_writemax nfs_getcwd nfs_get_timeout nfs_init_context nfs_link nfs_link_async nfs_lockf nfs_lockf_async nfs_lseek nfs_lseek_async nfs_mkdir nfs_mkdir_async nfs_mkdir2 nfs_mkdir2_async nfs_mknod nfs_mknod_async nfs_mount nfs_mount_async nfs_open nfs_open_async nfs_open2 nfs_open2_async nfs_opendir nfs_opendir_async nfs_parse_url_full nfs_parse_url_dir nfs_parse_url_incomplete nfs_destroy_url nfs_pagecache_invalidate nfs_pread nfs_pread_async nfs_pwrite nfs_pwrite_async nfs_read nfs_read_async nfs_readdir nfs_readlink nfs_readlink_async nfs_readlink2 nfs_rename nfs_rename_async nfs_rmdir nfs_rmdir_async nfs_service nfs_set_auth nfs_set_autoreconnect nfs_set_debug nfs_set_dircache nfs_set_gid nfs_set_pagecache nfs_set_pagecache_ttl nfs_set_readahead nfs_set_tcp_syncnt nfs_set_timeout nfs_set_uid nfs_set_version nfs_stat nfs_stat_async nfs_stat64 nfs_stat64_async nfs_statvfs nfs_statvfs_async nfs_statvfs64 nfs_statvfs64_async nfs_symlink nfs_symlink_async nfs_truncate nfs_truncate_async nfs_umount nfs_umount_async nfs_unlink nfs_unlink_async nfs_utime nfs_utime_async nfs_utimes nfs_utimes_async nfs_which_events nfs_write nfs_write_async nfsstat3_to_errno nfsstat3_to_str nfsstat4_to_errno nfsstat4_to_str nfs4_set_client_name nfs4_set_verifier win32_poll rpc_connect_async rpc_connect_port_async rpc_connect_program_async rpc_destroy_context rpc_disconnect rpc_get_error rpc_get_fd rpc_init_context rpc_init_server_context rpc_pmap2_null_async rpc_pmap2_getport_async rpc_pmap2_set_async rpc_pmap2_unset_async rpc_pmap2_dump_async rpc_pmap2_callit_async rpc_pmap3_null_async rpc_pmap3_set_async rpc_pmap3_unset_async rpc_pmap3_getaddr_async rpc_pmap3_dump_async rpc_pmap3_callit_async rpc_pmap3_gettime_async rpc_pmap3_uaddr2taddr_async rpc_pmap3_taddr2uaddr_async rpc_mount_null_async rpc_mount_mnt_async rpc_mount_dump_async rpc_mount_umnt_async rpc_mount_umntall_async rpc_mount_export_async rpc_mount1_null_async rpc_mount1_mnt_async rpc_mount1_dump_async rpc_mount1_umnt_async rpc_mount1_umntall_async rpc_mount1_export_async rpc_mount3_null_async rpc_mount3_mnt_async rpc_mount3_dump_async rpc_mount3_umnt_async rpc_mount3_umntall_async rpc_mount3_export_async rpc_nfsacl_null_async rpc_nfsacl_getacl_async rpc_nfsacl_setacl_async rpc_nfs_null_async rpc_nfs_getattr_async rpc_nfs_pathconf_async rpc_nfs_lookup_async rpc_nfs_access_async rpc_nfs_read_async rpc_nfs_write_async rpc_nfs_commit_async rpc_nfs_setattr_async rpc_nfs_mkdir_async rpc_nfs_rmdir_async rpc_nfs_create_async rpc_nfs_mknod_async rpc_nfs_remove_async rpc_nfs_readdir_async rpc_nfs_readdirplus_async rpc_nfs_fsstat_async rpc_nfs_fsinfo_async rpc_nfs_readlink_async rpc_nfs_symlink_async rpc_nfs_rename_async rpc_nfs_link_async rpc_nfs2_null_async rpc_nfs2_getattr_async rpc_nfs2_setattr_async rpc_nfs2_lookup_async rpc_nfs2_readlink_async rpc_nfs2_read_async rpc_nfs2_write_async rpc_nfs2_create_async rpc_nfs2_remove_async rpc_nfs2_rename_async rpc_nfs2_link_async rpc_nfs2_symlink_async rpc_nfs2_mkdir_async rpc_nfs2_rmdir_async rpc_nfs2_readdir_async rpc_nfs2_statfs_async rpc_nfs3_null_async rpc_nfs3_getattr_async rpc_nfs3_pathconf_async rpc_nfs3_lookup_async rpc_nfs3_access_async rpc_nfs3_read_async rpc_nfs3_write_async rpc_nfs3_commit_async rpc_nfs3_setattr_async rpc_nfs3_mkdir_async rpc_nfs3_rmdir_async rpc_nfs3_create_async rpc_nfs3_mknod_async rpc_nfs3_remove_async rpc_nfs3_readdir_async rpc_nfs3_readdirplus_async rpc_nfs3_fsstat_async rpc_nfs3_fsinfo_async rpc_nfs3_readlink_async rpc_nfs3_symlink_async rpc_nfs3_rename_async rpc_nfs3_link_async rpc_nfs4_compound_async rpc_nfs4_null_async rpc_nlm4_null_async rpc_nlm4_test_async rpc_nlm4_lock_async rpc_nlm4_cancel_async rpc_nlm4_unlock_async rpc_nsm1_null_async rpc_nsm1_stat_async rpc_nsm1_mon_async rpc_nsm1_unmon_async rpc_nsm1_unmonall_async rpc_nsm1_simucrash_async rpc_nsm1_notify_async rpc_null_async rpc_register_service rpc_rquota1_null_async rpc_rquota1_getquota_async rpc_rquota1_getactivequota_async rpc_send_reply rpc_service rpc_set_fd rpc_set_gid rpc_set_uid rpc_which_events libnfs-libnfs-4.0.0/lib/libnfs-zdr.c000066400000000000000000000320471343063627400172450ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2012 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ /* * This file contains definitions for the built in ZDR implementation. * This is a very limited ZDR subset that can only marshal to/from a momory buffer, * i.e. zdrmem_create() buffers. * It aims to be compatible with normal rpcgen generated functions. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 #include #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" struct zdr_mem { struct zdr_mem *next; uint32_t size; char buf[1]; }; struct opaque_auth _null_auth; bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos) { zdrs->pos = pos; return TRUE; } uint32_t libnfs_zdr_getpos(ZDR *zdrs) { return zdrs->pos; } void libnfs_zdrmem_create(ZDR *zdrs, const caddr_t addr, uint32_t size, enum zdr_op xop) { zdrs->x_op = xop; zdrs->buf = addr; zdrs->size = size; zdrs->pos = 0; zdrs->mem = NULL; } void *zdr_malloc(ZDR *zdrs, uint32_t size) { struct zdr_mem *mem; int mem_size; mem_size = offsetof(struct zdr_mem, buf) + size; mem = malloc(mem_size); mem->next = zdrs->mem; mem->size = size; zdrs->mem = mem; return &mem->buf[0]; } void libnfs_zdr_destroy(ZDR *zdrs) { while (zdrs->mem != NULL) { struct zdr_mem *mem = zdrs->mem->next; free(zdrs->mem); zdrs->mem = mem; } } bool_t libnfs_zdr_u_int(ZDR *zdrs, uint32_t *u) { if (zdrs->pos + 4 > zdrs->size) { return FALSE; } switch (zdrs->x_op) { case ZDR_ENCODE: *(uint32_t *)(void *)&zdrs->buf[zdrs->pos] = htonl(*u); zdrs->pos += 4; return TRUE; case ZDR_DECODE: *u = ntohl(*(uint32_t *)(void *)&zdrs->buf[zdrs->pos]); zdrs->pos += 4; return TRUE; } return FALSE; } bool_t libnfs_zdr_int(ZDR *zdrs, int32_t *i) { return libnfs_zdr_u_int(zdrs, (uint32_t *)i); } bool_t libnfs_zdr_uint64_t(ZDR *zdrs, uint64_t *u) { if (zdrs->pos + 8 > zdrs->size) { return FALSE; } switch (zdrs->x_op) { case ZDR_ENCODE: *(uint32_t *)(void *)&zdrs->buf[zdrs->pos] = htonl((*u >> 32)); zdrs->pos += 4; *(uint32_t *)(void *)&zdrs->buf[zdrs->pos] = htonl((*u & 0xffffffff)); zdrs->pos += 4; return TRUE; case ZDR_DECODE: *u = ntohl(*(uint32_t *)(void *)&zdrs->buf[zdrs->pos]); zdrs->pos += 4; *u <<= 32; *u |= (uint32_t)ntohl(*(uint32_t *)(void *)&zdrs->buf[zdrs->pos]); zdrs->pos += 4; return TRUE; } return FALSE; } bool_t libnfs_zdr_int64_t(ZDR *zdrs, int64_t *i) { return libnfs_zdr_uint64_t(zdrs, (uint64_t *)i); } bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize) { uint32_t zero = 0; int pad; if (!libnfs_zdr_u_int(zdrs, size)) { return FALSE; } if (zdrs->pos + (int)*size > zdrs->size) { return FALSE; } switch (zdrs->x_op) { case ZDR_ENCODE: memcpy(&zdrs->buf[zdrs->pos], *bufp, *size); zdrs->pos += *size; pad = (4 - (zdrs->pos & 0x03)) & 0x03; if (pad) { /* Make valgrind happy again */ memcpy(&zdrs->buf[zdrs->pos], &zero, pad); zdrs->pos += pad; } return TRUE; case ZDR_DECODE: if (*bufp != NULL) { memcpy(*bufp, &zdrs->buf[zdrs->pos], *size); } else { *bufp = &zdrs->buf[zdrs->pos]; } zdrs->pos += *size; zdrs->pos = (zdrs->pos + 3) & ~3; return TRUE; } return FALSE; } bool_t libnfs_zdr_enum(ZDR *zdrs, enum_t *e) { bool_t ret; int32_t i = *e; ret = libnfs_zdr_u_int(zdrs, (uint32_t *)&i); *e = i; return ret; } bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b) { return libnfs_zdr_u_int(zdrs, (uint32_t *)b); } bool_t libnfs_zdr_void(ZDR *zdrs, void *v) { return TRUE; } bool_t libnfs_zdr_pointer(ZDR *zdrs, char **objp, uint32_t size, zdrproc_t proc) { bool_t more_data; more_data = (*objp != NULL); if (!libnfs_zdr_bool(zdrs, &more_data)) { return FALSE; } if (more_data == 0) { *objp = NULL; return TRUE; } if (zdrs->x_op == ZDR_DECODE) { *objp = zdr_malloc(zdrs, size); if (*objp == NULL) { return FALSE; } memset(*objp, 0, size); } return proc(zdrs, *objp); } bool_t libnfs_zdr_opaque(ZDR *zdrs, char *objp, uint32_t size) { switch (zdrs->x_op) { case ZDR_ENCODE: memcpy(&zdrs->buf[zdrs->pos], objp, size); zdrs->pos += size; if (zdrs->pos & 3) { memset(&zdrs->buf[zdrs->pos], 0x00, 4 - (zdrs->pos & 3)); } zdrs->pos = (zdrs->pos + 3) & ~3; return TRUE; case ZDR_DECODE: memcpy(objp, &zdrs->buf[zdrs->pos], size); zdrs->pos += size; zdrs->pos = (zdrs->pos + 3) & ~3; return TRUE; } return FALSE; } bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize) { uint32_t size; if (zdrs->x_op == ZDR_ENCODE) { size = strlen(*strp); } if (!libnfs_zdr_u_int(zdrs, &size)) { return FALSE; } if (zdrs->pos + (int)size > zdrs->size) { return FALSE; } switch (zdrs->x_op) { case ZDR_ENCODE: return libnfs_zdr_opaque(zdrs, *strp, size); case ZDR_DECODE: /* If the we string is null terminated we can just return it * in place. */ if (zdrs->size > zdrs->pos + (int)size && zdrs->buf[zdrs->pos + size] == 0) { if (*strp == NULL) { *strp = &zdrs->buf[zdrs->pos]; (*strp)[size] = 0; zdrs->pos += size; zdrs->pos = (zdrs->pos + 3) & ~3; return TRUE; } (*strp)[size] = 0; return libnfs_zdr_opaque(zdrs, *strp, size); } /* Crap. The string is not null terminated in the rx buffer. * we have to allocate a buffer so we can add the null byte. */ *strp = zdr_malloc(zdrs, size + 1); if (*strp == NULL) { return FALSE; } (*strp)[size] = 0; return libnfs_zdr_opaque(zdrs, *strp, size); } return FALSE; } bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc) { int i; if (!libnfs_zdr_u_int(zdrs, size)) { return FALSE; } if (zdrs->x_op == ZDR_DECODE) { *arrp = zdr_malloc(zdrs, *size * elsize); if (*arrp == NULL) { return FALSE; } memset(*arrp, 0, *size * elsize); } for (i = 0; i < (int)*size; i++) { if (!proc(zdrs, *arrp + i * elsize)) { return FALSE; } } return TRUE; } void libnfs_zdr_free(zdrproc_t proc, char *objp) { } static bool_t libnfs_opaque_auth(ZDR *zdrs, struct opaque_auth *auth) { if (!libnfs_zdr_u_int(zdrs, &auth->oa_flavor)) { return FALSE; } if (!libnfs_zdr_bytes(zdrs, &auth->oa_base, &auth->oa_length, auth->oa_length)) { return FALSE; } return TRUE; } static bool_t libnfs_rpc_call_body(struct rpc_context *rpc, ZDR *zdrs, struct call_body *cmb) { if (!libnfs_zdr_u_int(zdrs, &cmb->rpcvers)) { rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode " "RPCVERS"); return FALSE; } if (!libnfs_zdr_u_int(zdrs, &cmb->prog)) { rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode " "PROG"); return FALSE; } if (!libnfs_zdr_u_int(zdrs, &cmb->vers)) { rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode " "VERS"); return FALSE; } if (!libnfs_zdr_u_int(zdrs, &cmb->proc)) { rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode " "PROC"); return FALSE; } if (!libnfs_opaque_auth(zdrs, &cmb->cred)) { rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode " "CRED"); return FALSE; } if (!libnfs_opaque_auth(zdrs, &cmb->verf)) { rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode " "VERF"); return FALSE; } return TRUE; } static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar) { if (!libnfs_opaque_auth(zdrs, &ar->verf)) { return FALSE; } if (!libnfs_zdr_u_int(zdrs, &ar->stat)) { return FALSE; } switch (ar->stat) { case SUCCESS: if (!ar->reply_data.results.proc(zdrs, ar->reply_data.results.where)) { return FALSE; } return TRUE; case PROG_MISMATCH: if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.low)) { return FALSE; } if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.high)) { return FALSE; } return TRUE; default: return TRUE; } return FALSE; } static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *rr) { if (!libnfs_zdr_u_int(zdrs, (uint32_t *)&rr->stat)) { return FALSE; } switch (rr->stat) { case RPC_MISMATCH: if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.low)) { return FALSE; } if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.high)) { return FALSE; } return TRUE; case AUTH_ERROR: if (!libnfs_zdr_u_int(zdrs, (uint32_t *)&rr->reject_data.stat)) { return FALSE; } return TRUE; default: return TRUE; } return FALSE; } static bool_t libnfs_rpc_reply_body(struct rpc_context *rpc, ZDR *zdrs, struct reply_body *rmb) { if (!libnfs_zdr_u_int(zdrs, &rmb->stat)) { rpc_set_error(rpc, "libnfs_rpc_reply_body failed to decode " "STAT"); return FALSE; } switch (rmb->stat) { case MSG_ACCEPTED: if (!libnfs_accepted_reply(zdrs, &rmb->reply.areply)) { rpc_set_error(rpc, "libnfs_rpc_reply_body failed to " "decode ACCEPTED"); return FALSE; } return TRUE; case MSG_DENIED: if (!libnfs_rejected_reply(zdrs, &rmb->reply.rreply)) { rpc_set_error(rpc, "libnfs_rpc_reply_body failed to " "decode DENIED"); return FALSE; } return TRUE; } rpc_set_error(rpc, "libnfs_rpc_reply_body failed to " "decode. Neither ACCEPTED nor DENIED"); return FALSE; } static bool_t libnfs_rpc_msg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg) { int ret; if (!libnfs_zdr_u_int(zdrs, &msg->xid)) { rpc_set_error(rpc, "libnfs_rpc_msg failed to decode XID"); return FALSE; } if (!libnfs_zdr_u_int(zdrs, &msg->direction)) { rpc_set_error(rpc, "libnfs_rpc_msg failed to decode DIRECTION"); return FALSE; } switch (msg->direction) { case CALL: ret = libnfs_rpc_call_body(rpc, zdrs, &msg->body.cbody); if (!ret) { rpc_set_error(rpc, "libnfs_rpc_msg failed to encode " "CALL, ret=%d: %s", ret, rpc_get_error(rpc)); } return ret; case REPLY: ret = libnfs_rpc_reply_body(rpc, zdrs, &msg->body.rbody); if (!ret) { rpc_set_error(rpc, "libnfs_rpc_msg failed to decode " "REPLY, ret=%d: %s", ret, rpc_get_error(rpc)); } return ret; default: rpc_set_error(rpc, "libnfs_rpc_msg failed to decode. " "Neither CALL not REPLY"); return FALSE; } } bool_t libnfs_zdr_callmsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg) { return libnfs_rpc_msg(rpc, zdrs, msg); } bool_t libnfs_zdr_replymsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg) { return libnfs_rpc_msg(rpc, zdrs, msg); } struct AUTH *authnone_create(void) { struct AUTH *auth; auth = malloc(sizeof(struct AUTH)); auth->ah_cred.oa_flavor = AUTH_NONE; auth->ah_cred.oa_length = 0; auth->ah_cred.oa_base = NULL; auth->ah_verf.oa_flavor = AUTH_NONE; auth->ah_verf.oa_length = 0; auth->ah_verf.oa_base = NULL; auth->ah_private = NULL; return auth; } struct AUTH *libnfs_authunix_create(const char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups) { struct AUTH *auth; int size; uint32_t *buf; int idx; size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4; auth = malloc(sizeof(struct AUTH)); memset(auth, 0x00, sizeof(struct AUTH)); auth->ah_cred.oa_flavor = AUTH_UNIX; auth->ah_cred.oa_length = size; auth->ah_cred.oa_base = malloc(size); memset(auth->ah_cred.oa_base, 0x00, size); buf = (uint32_t *)(void *)auth->ah_cred.oa_base; idx = 0; buf[idx++] = htonl((uint32_t)rpc_current_time()); buf[idx++] = htonl(strlen(host)); memcpy(&buf[2], host, strlen(host)); idx += (strlen(host) + 3) >> 2; buf[idx++] = htonl(uid); buf[idx++] = htonl(gid); buf[idx++] = htonl(len); while (len-- > 0) { buf[idx++] = htonl(*groups++); } auth->ah_verf.oa_flavor = AUTH_NONE; auth->ah_verf.oa_length = 0; auth->ah_verf.oa_base = NULL; auth->ah_private = NULL; return auth; } struct AUTH *libnfs_authunix_create_default(void) { #ifdef WIN32 return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL); #else return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL); #endif } void libnfs_auth_destroy(struct AUTH *auth) { if (auth->ah_cred.oa_base) { free(auth->ah_cred.oa_base); } if (auth->ah_verf.oa_base) { free(auth->ah_verf.oa_base); } free(auth); } libnfs-libnfs-4.0.0/lib/libnfs.c000077500000000000000000001507721343063627400164610ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ /* * High level api to nfs filesystems */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #endif #ifdef HAVE_UTIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #if defined(__ANDROID__) && !defined(HAVE_SYS_STATVFS_H) #define statvfs statfs #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef HAVE_SYS_SYSMACROS_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #include #include #include #include #include #include "slist.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" #include "libnfs-raw-portmap.h" #include "libnfs-private.h" void nfs_free_nfsdir(struct nfsdir *nfsdir) { while (nfsdir->entries) { struct nfsdirent *dirent = nfsdir->entries->next; if (nfsdir->entries->name != NULL) { free(nfsdir->entries->name); } free(nfsdir->entries); nfsdir->entries = dirent; } free(nfsdir->fh.val); free(nfsdir); } void nfs_dircache_add(struct nfs_context *nfs, struct nfsdir *nfsdir) { int i = 0; LIBNFS_LIST_ADD(&nfs->dircache, nfsdir); for (nfsdir = nfs->dircache; nfsdir; nfsdir = nfsdir->next, i++) { if (i > MAX_DIR_CACHE) { LIBNFS_LIST_REMOVE(&nfs->dircache, nfsdir); nfs_free_nfsdir(nfsdir); break; } } } struct nfsdir * nfs_dircache_find(struct nfs_context *nfs, struct nfs_fh *fh) { struct nfsdir *nfsdir; for (nfsdir = nfs->dircache; nfsdir; nfsdir = nfsdir->next) { if (nfsdir->fh.len == fh->len && !memcmp(nfsdir->fh.val, fh->val, fh->len)) { LIBNFS_LIST_REMOVE(&nfs->dircache, nfsdir); return nfsdir; } } return NULL; } void nfs_dircache_drop(struct nfs_context *nfs, struct nfs_fh *fh) { struct nfsdir *cached; cached = nfs_dircache_find(nfs, fh); if (cached) { nfs_free_nfsdir(cached); } } static uint32_t nfs_pagecache_hash(struct nfs_pagecache *pagecache, uint64_t offset) { return (2654435761UL * (1 + ((uint32_t)(offset) / NFS_BLKSIZE))) & (pagecache->num_entries - 1); } void nfs_pagecache_invalidate(struct nfs_context *nfs, struct nfsfh *nfsfh) { if (nfsfh->pagecache.entries) { RPC_LOG(nfs->rpc, 2, "invalidating pagecache"); memset(nfsfh->pagecache.entries, 0x00, sizeof(struct nfs_pagecache_entry) * nfsfh->pagecache.num_entries); } } void nfs_pagecache_put(struct nfs_pagecache *pagecache, uint64_t offset, const char *buf, size_t len) { time_t ts = pagecache->ttl ? (time_t)(rpc_current_time() / 1000) : 1; if (!pagecache->num_entries) return; while (len > 0) { uint64_t page_offset = offset & ~(NFS_BLKSIZE - 1); uint32_t entry = nfs_pagecache_hash(pagecache, page_offset); struct nfs_pagecache_entry *e = &pagecache->entries[entry]; size_t n = MIN(NFS_BLKSIZE - offset % NFS_BLKSIZE, len); /* we can only write to the cache if we add a full page or * partially update a page that is still valid */ if (n == NFS_BLKSIZE || (e->ts && e->offset == page_offset && (!pagecache->ttl || ts - e->ts <= pagecache->ttl))) { e->ts = ts; e->offset = page_offset; memcpy(e->buf + offset % NFS_BLKSIZE, buf, n); } buf += n; offset += n; len -= n; } } char * nfs_pagecache_get(struct nfs_pagecache *pagecache, uint64_t offset) { uint32_t entry; struct nfs_pagecache_entry *e; entry = nfs_pagecache_hash(pagecache, offset); e = &pagecache->entries[entry]; if (offset != e->offset) { return NULL; } if (!e->ts) { return NULL; } if (pagecache->ttl && (time_t)(rpc_current_time() / 1000) - e->ts > pagecache->ttl) { return NULL; } return e->buf; } void nfs_pagecache_init(struct nfs_context *nfs, struct nfsfh *nfsfh) { /* init page cache */ if (nfs->rpc->pagecache) { nfsfh->pagecache.num_entries = nfs->rpc->pagecache; nfsfh->pagecache.ttl = nfs->rpc->pagecache_ttl; nfsfh->pagecache.entries = malloc(sizeof(struct nfs_pagecache_entry) * nfsfh->pagecache.num_entries); nfs_pagecache_invalidate(nfs, nfsfh); RPC_LOG(nfs->rpc, 2, "init pagecache entries %d pagesize %d\n", nfsfh->pagecache.num_entries, NFS_BLKSIZE); } } void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth) { rpc_set_auth(nfs->rpc, auth); } int nfs_get_fd(struct nfs_context *nfs) { return rpc_get_fd(nfs->rpc); } int nfs_queue_length(struct nfs_context *nfs) { return rpc_queue_length(nfs->rpc); } int nfs_which_events(struct nfs_context *nfs) { return rpc_which_events(nfs->rpc); } int nfs_service(struct nfs_context *nfs, int revents) { return rpc_service(nfs->rpc, revents); } char * nfs_get_error(struct nfs_context *nfs) { return rpc_get_error(nfs->rpc); }; #ifdef HAVE_SO_BINDTODEVICE void nfs_set_interface(struct nfs_context *nfs, const char *ifname) { rpc_set_interface(nfs_get_rpc_context(nfs), ifname); } #endif static int nfs_set_context_args(struct nfs_context *nfs, const char *arg, const char *val) { if (!strcmp(arg, "tcp-syncnt")) { rpc_set_tcp_syncnt(nfs_get_rpc_context(nfs), atoi(val)); } else if (!strcmp(arg, "uid")) { rpc_set_uid(nfs_get_rpc_context(nfs), atoi(val)); } else if (!strcmp(arg, "gid")) { rpc_set_gid(nfs_get_rpc_context(nfs), atoi(val)); } else if (!strcmp(arg, "readahead")) { rpc_set_readahead(nfs_get_rpc_context(nfs), atoi(val)); } else if (!strcmp(arg, "pagecache")) { rpc_set_pagecache(nfs_get_rpc_context(nfs), atoi(val)); } else if (!strcmp(arg, "debug")) { rpc_set_debug(nfs_get_rpc_context(nfs), atoi(val)); } else if (!strcmp(arg, "auto-traverse-mounts")) { nfs->auto_traverse_mounts = atoi(val); } else if (!strcmp(arg, "dircache")) { nfs_set_dircache(nfs, atoi(val)); } else if (!strcmp(arg, "autoreconnect")) { nfs_set_autoreconnect(nfs, atoi(val)); #ifdef HAVE_SO_BINDTODEVICE } else if (!strcmp(arg, "if")) { nfs_set_interface(nfs, val); #endif } else if (!strcmp(arg, "version")) { if (nfs_set_version(nfs, atoi(val)) < 0) { nfs_set_error(nfs, "NFS version %d is not supported", atoi(val)); return -1; } } else if (!strcmp(arg, "nfsport")) { nfs->nfsport = atoi(val); } else if (!strcmp(arg, "mountport")) { nfs->mountport = atoi(val); } return 0; } static struct nfs_url * nfs_parse_url(struct nfs_context *nfs, const char *url, int dir, int incomplete) { struct nfs_url *urls; char *strp, *flagsp, *strp2; if (strncmp(url, "nfs://", 6)) { nfs_set_error(nfs, "Invalid URL specified"); return NULL; } urls = malloc(sizeof(struct nfs_url)); if (urls == NULL) { nfs_set_error(nfs, "Out of memory"); return NULL; } memset(urls, 0x00, sizeof(struct nfs_url)); urls->server = strdup(url + 6); if (urls->server == NULL) { nfs_destroy_url(urls); nfs_set_error(nfs, "Out of memory"); return NULL; } if (urls->server[0] == '/' || urls->server[0] == '\0' || urls->server[0] == '?') { if (incomplete) { flagsp = strchr(urls->server, '?'); goto flags; } nfs_destroy_url(urls); nfs_set_error(nfs, "Invalid server string"); return NULL; } strp = strchr(urls->server, '/'); if (strp == NULL) { if (incomplete) { flagsp = strchr(urls->server, '?'); goto flags; } nfs_destroy_url(urls); nfs_set_error(nfs, "Incomplete or invalid URL specified."); return NULL; } urls->path = strdup(strp); if (urls->path == NULL) { nfs_destroy_url(urls); nfs_set_error(nfs, "Out of memory"); return NULL; } *strp = 0; if (dir) { flagsp = strchr(urls->path, '?'); goto flags; } strp = strrchr(urls->path, '/'); if (strp == NULL) { if (incomplete) { flagsp = strchr(urls->path, '?'); goto flags; } nfs_destroy_url(urls); nfs_set_error(nfs, "Incomplete or invalid URL specified."); return NULL; } urls->file = strdup(strp); if (urls->path == NULL) { nfs_destroy_url(urls); nfs_set_error(nfs, "Out of memory"); return NULL; } *strp = 0; flagsp = strchr(urls->file, '?'); flags: if (flagsp) { *flagsp = 0; } if (urls->file && !strlen(urls->file)) { free(urls->file); urls->file = NULL; if (!incomplete) { nfs_destroy_url(urls); nfs_set_error(nfs, "Incomplete or invalid URL " "specified."); return NULL; } } while (flagsp != NULL && *(flagsp+1) != 0) { strp = flagsp + 1; flagsp = strchr(strp, '&'); if (flagsp) { *flagsp = 0; } strp2 = strchr(strp, '='); if (strp2) { *strp2 = 0; strp2++; nfs_set_context_args(nfs, strp, strp2); } } if (urls->server && strlen(urls->server) <= 1) { free(urls->server); urls->server = NULL; } return urls; } struct nfs_url * nfs_parse_url_full(struct nfs_context *nfs, const char *url) { return nfs_parse_url(nfs, url, 0, 0); } struct nfs_url * nfs_parse_url_dir(struct nfs_context *nfs, const char *url) { return nfs_parse_url(nfs, url, 1, 0); } struct nfs_url * nfs_parse_url_incomplete(struct nfs_context *nfs, const char *url) { return nfs_parse_url(nfs, url, 0, 1); } void nfs_destroy_url(struct nfs_url *url) { if (url) { free(url->server); free(url->path); free(url->file); } free(url); } #define MAX_CLIENT_NAME 64 struct nfs_context * nfs_init_context(void) { struct nfs_context *nfs; int i; uint64_t v; verifier4 verifier; char client_name[MAX_CLIENT_NAME]; nfs = malloc(sizeof(struct nfs_context)); if (nfs == NULL) { return NULL; } memset(nfs, 0, sizeof(struct nfs_context)); nfs->rpc = rpc_init_context(); if (nfs->rpc == NULL) { free(nfs); return NULL; } nfs->cwd = strdup("/"); nfs->mask = 022; nfs->auto_traverse_mounts = 1; nfs->dircache_enabled = 1; /* Default is never give up, never surrender */ nfs->auto_reconnect = -1; nfs->version = NFS_V3; /* NFSv4 parameters */ /* We need a "random" initial verifier */ v = rpc_current_time() << 32 | getpid(); for (i = 0; i < NFS4_VERIFIER_SIZE; i++) { verifier[i] = v & 0xff; v >>= 8; } nfs4_set_verifier(nfs, verifier); snprintf(client_name, MAX_CLIENT_NAME, "Libnfs pid:%d %d", getpid(), (int)time(NULL)); nfs4_set_client_name(nfs, client_name); return nfs; } void nfs4_set_client_name(struct nfs_context *nfs, const char *client_name) { nfs->client_name = strdup(client_name); } void nfs4_set_verifier(struct nfs_context *nfs, const char *verifier) { memcpy(nfs->verifier, verifier, NFS4_VERIFIER_SIZE); } void nfs_destroy_context(struct nfs_context *nfs) { while (nfs->nested_mounts) { struct nested_mounts *mnt = nfs->nested_mounts; LIBNFS_LIST_REMOVE(&nfs->nested_mounts, mnt); free(mnt->path); free(mnt->fh.val); free(mnt); } rpc_destroy_context(nfs->rpc); nfs->rpc = NULL; free(nfs->server); nfs->server = NULL; free(nfs->export); nfs->export = NULL; free(nfs->cwd); nfs->cwd = NULL; free(nfs->rootfh.val); nfs->rootfh.len = 0; nfs->rootfh.val = NULL; free(nfs->client_name); nfs->client_name = NULL; while (nfs->dircache) { struct nfsdir *nfsdir = nfs->dircache; LIBNFS_LIST_REMOVE(&nfs->dircache, nfsdir); nfs_free_nfsdir(nfsdir); } free(nfs); } struct rpc_cb_data { char *server; uint32_t program; uint32_t version; rpc_cb cb; void *private_data; }; void free_rpc_cb_data(struct rpc_cb_data *data) { free(data->server); data->server = NULL; free(data); } static int rpc_connect_port_internal(struct rpc_context *rpc, int port, struct rpc_cb_data *data); static void rpc_connect_program_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct rpc_cb_data *data = private_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); /* Dont want any more callbacks even if the socket is closed */ rpc->connect_cb = NULL; if (status != RPC_STATUS_SUCCESS) { data->cb(rpc, status, command_data, data->private_data); free_rpc_cb_data(data); return; } data->cb(rpc, status, NULL, data->private_data); free_rpc_cb_data(data); } static void rpc_connect_program_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct rpc_cb_data *data = private_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); /* Dont want any more callbacks even if the socket is closed */ rpc->connect_cb = NULL; if (status != RPC_STATUS_SUCCESS) { data->cb(rpc, status, command_data, data->private_data); free_rpc_cb_data(data); return; } if (rpc_null_async(rpc, data->program, data->version, rpc_connect_program_5_cb, data) != 0) { data->cb(rpc, RPC_STATUS_ERROR, command_data, data->private_data); free_rpc_cb_data(data); return; } } static void rpc_connect_program_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct rpc_cb_data *data = private_data; struct pmap3_string_result *gar; uint32_t rpc_port = 0; char *ptr; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status != RPC_STATUS_SUCCESS) { data->cb(rpc, status, command_data, data->private_data); free_rpc_cb_data(data); return; } switch (rpc->s.ss_family) { case AF_INET: rpc_port = *(uint32_t *)(void *)command_data; break; case AF_INET6: /* ouch. portmapper and ipv6 are not great */ gar = command_data; if (gar->addr == NULL) { break; } ptr = strrchr(gar->addr, '.'); if (ptr == NULL) { break; } rpc_port = atoi(ptr + 1); *ptr = 0; ptr = strrchr(gar->addr, '.'); if (ptr == NULL) { break; } rpc_port += 256 * atoi(ptr + 1); break; } if (rpc_port == 0) { rpc_set_error(rpc, "RPC error. Program is not available on %s", data->server); data->cb(rpc, RPC_STATUS_ERROR, rpc_get_error(rpc), data->private_data); free_rpc_cb_data(data); return; } rpc_disconnect(rpc, "normal disconnect"); if (rpc_connect_port_internal(rpc, rpc_port, data)) { data->cb(rpc, RPC_STATUS_ERROR, command_data, data->private_data); free_rpc_cb_data(data); return; } } static void rpc_connect_program_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct rpc_cb_data *data = private_data; struct pmap3_mapping map; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status != RPC_STATUS_SUCCESS) { data->cb(rpc, status, command_data, data->private_data); free_rpc_cb_data(data); return; } switch (rpc->s.ss_family) { case AF_INET: if (rpc_pmap2_getport_async(rpc, data->program, data->version, IPPROTO_TCP, rpc_connect_program_3_cb, private_data) != 0) { data->cb(rpc, RPC_STATUS_ERROR, command_data, data->private_data); free_rpc_cb_data(data); return; } break; case AF_INET6: map.prog=data->program; map.vers=data->version; map.netid=""; map.addr=""; map.owner=""; if (rpc_pmap3_getaddr_async(rpc, &map, rpc_connect_program_3_cb, private_data) != 0) { data->cb(rpc, RPC_STATUS_ERROR, command_data, data->private_data); free_rpc_cb_data(data); return; } break; } } static void rpc_connect_program_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct rpc_cb_data *data = private_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); /* Dont want any more callbacks even if the socket is closed */ rpc->connect_cb = NULL; if (status != RPC_STATUS_SUCCESS) { data->cb(rpc, status, command_data, data->private_data); free_rpc_cb_data(data); return; } switch (rpc->s.ss_family) { case AF_INET: if (rpc_pmap2_null_async(rpc, rpc_connect_program_2_cb, data) != 0) { data->cb(rpc, RPC_STATUS_ERROR, command_data, data->private_data); free_rpc_cb_data(data); return; } break; case AF_INET6: if (rpc_pmap3_null_async(rpc, rpc_connect_program_2_cb, data) != 0) { data->cb(rpc, RPC_STATUS_ERROR, command_data, data->private_data); free_rpc_cb_data(data); return; } break; } } static int rpc_connect_port_internal(struct rpc_context *rpc, int port, struct rpc_cb_data *data) { if (rpc_connect_async(rpc, data->server, port, rpc_connect_program_4_cb, data) != 0) { return -1; } return 0; } int rpc_connect_port_async(struct rpc_context *rpc, const char *server, int port, int program, int version, rpc_cb cb, void *private_data) { struct rpc_cb_data *data; data = malloc(sizeof(struct rpc_cb_data)); if (data == NULL) { return -1; } memset(data, 0, sizeof(struct rpc_cb_data)); data->server = strdup(server); data->program = program; data->version = version; data->cb = cb; data->private_data = private_data; if (rpc_connect_port_internal(rpc, port, data)) { rpc_set_error(rpc, "Failed to start connection. %s", rpc_get_error(rpc)); free_rpc_cb_data(data); return -1; } return 0; } int rpc_connect_program_async(struct rpc_context *rpc, const char *server, int program, int version, rpc_cb cb, void *private_data) { struct rpc_cb_data *data; data = malloc(sizeof(struct rpc_cb_data)); if (data == NULL) { return -1; } memset(data, 0, sizeof(struct rpc_cb_data)); data->server = strdup(server); data->program = program; data->version = version; data->cb = cb; data->private_data = private_data; if (rpc_connect_async(rpc, server, 111, rpc_connect_program_1_cb, data) != 0) { rpc_set_error(rpc, "Failed to start connection. %s", rpc_get_error(rpc)); free_rpc_cb_data(data); return -1; } return 0; } void free_nfs_cb_data(struct nfs_cb_data *data) { if (data->continue_data != NULL) { assert(data->free_continue_data); data->free_continue_data(data->continue_data); } free(data->saved_path); free(data->fh.val); if (!data->not_my_buffer) { free(data->buffer); } free(data); } void nfs_free_nfsfh(struct nfsfh *nfsfh) { if (nfsfh->fh.val != NULL) { free(nfsfh->fh.val); nfsfh->fh.len = 0; nfsfh->fh.val = NULL; } free(nfsfh->pagecache.entries); free(nfsfh); } /* * Async call for mounting an nfs share and geting the root filehandle */ int nfs_mount_async(struct nfs_context *nfs, const char *server, const char *export, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_mount_async(nfs, server, export, cb, private_data); case NFS_V4: return nfs4_mount_async(nfs, server, export, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } /* * Async call for umounting an nfs share */ int nfs_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_umount_async(nfs, cb, private_data); case NFS_V4: /* umount is a no-op in v4 */ (*cb)(0, nfs, NULL, private_data); return 0; default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_normalize_path(struct nfs_context *nfs, char *path) { char *str; int len; /* // -> / */ while ((str = strstr(path, "//"))) { while(*str) { *str = *(str + 1); str++; } } /* /./ -> / */ while ((str = strstr(path, "/./"))) { while(*(str + 1)) { *str = *(str + 2); str++; } } /* ^/../ -> error */ if (!strncmp(path, "/../", 4)) { nfs_set_error(nfs, "Absolute path starts with '/../' " "during normalization"); return -1; } /* ^[^/] -> error */ if (path[0] != '/') { nfs_set_error(nfs, "Absolute path does not start with '/'"); return -1; } /* /string/../ -> / */ while ((str = strstr(path, "/../"))) { char *tmp; if (!strncmp(path, "/../", 4)) { nfs_set_error(nfs, "Absolute path starts with '/../' " "during normalization"); return -1; } tmp = str - 1; while (*tmp != '/') { tmp--; } str += 3; while((*(tmp++) = *(str++)) != '\0') ; } /* /$ -> \0 */ len = strlen(path); if (len > 1) { if (path[len - 1] == '/') { path[len - 1] = '\0'; len--; } } if (path[0] == '\0') { nfs_set_error(nfs, "Absolute path became '' " "during normalization"); return -1; } /* /.$ -> \0 */ if (len >= 2) { if (!strcmp(&path[len - 2], "/.")) { path[len - 2] = '\0'; len -= 2; } } /* ^/..$ -> error */ if (!strcmp(path, "/..")) { nfs_set_error(nfs, "Absolute path is '/..' " "during normalization"); return -1; } /* /string/..$ -> / */ if (len >= 3) { if (!strcmp(&path[len - 3], "/..")) { char *tmp = &path[len - 3]; while (*--tmp != '/') ; *tmp = '\0'; } } return 0; } int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_stat_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv4", __FUNCTION__); return -1; } } int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_stat64_async(nfs, path, 0, cb, private_data); case NFS_V4: return nfs4_stat64_async(nfs, path, 0, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_lstat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_stat64_async(nfs, path, 1, cb, private_data); case NFS_V4: return nfs4_stat64_async(nfs, path, 1, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_open2_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_open_async(nfs, path, flags, mode, cb, private_data); case NFS_V4: return nfs4_open_async(nfs, path, flags, mode, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_open_async(struct nfs_context *nfs, const char *path, int flags, nfs_cb cb, void *private_data) { return nfs_open2_async(nfs, path, flags, 0666 & ~nfs->mask, cb, private_data); } int nfs_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_chdir_async(nfs, path, cb, private_data); case NFS_V4: return nfs4_chdir_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_pread_async_internal(nfs, nfsfh, offset, (size_t)count, cb, private_data, 0); case NFS_V4: return nfs4_pread_async_internal(nfs, nfsfh, offset, (size_t)count, cb, private_data, 0); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_pread_async_internal(nfs, nfsfh, nfsfh->offset, (size_t)count, cb, private_data, 1); case NFS_V4: return nfs4_pread_async_internal(nfs, nfsfh, nfsfh->offset, (size_t)count, cb, private_data, 1); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, const void *buf, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_pwrite_async_internal(nfs, nfsfh, offset, (size_t)count, buf, cb, private_data, 0); case NFS_V4: return nfs4_pwrite_async_internal(nfs, nfsfh, offset, (size_t)count, buf, cb, private_data, 0); default: nfs_set_error(nfs, "%s does not support NFSv%d.", __FUNCTION__, nfs->version); return -1; } } int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, const void *buf, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_write_async(nfs, nfsfh, count, buf, cb, private_data); case NFS_V4: return nfs4_write_async(nfs, nfsfh, count, buf, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_close_async(nfs, nfsfh, cb, private_data); case NFS_V4: return nfs4_close_async(nfs, nfsfh, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_fstat_async(nfs, nfsfh, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv4", __FUNCTION__); return -1; } } int nfs_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_fstat64_async(nfs, nfsfh, cb, private_data); case NFS_V4: return nfs4_fstat64_async(nfs, nfsfh, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_fsync_async(nfs, nfsfh, cb, private_data); case NFS_V4: return nfs4_fsync_async(nfs, nfsfh, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_ftruncate_async(nfs, nfsfh, length, cb, private_data); case NFS_V4: return nfs4_ftruncate_async(nfs, nfsfh, length, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_truncate_async(nfs, path, length, cb, private_data); case NFS_V4: return nfs4_truncate_async(nfs, path, length, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_mkdir2_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_mkdir2_async(nfs, path, mode, cb, private_data); case NFS_V4: return nfs4_mkdir2_async(nfs, path, mode, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { return nfs_mkdir2_async(nfs, path, 0755, cb, private_data); } int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_rmdir_async(nfs, path, cb, private_data); case NFS_V4: return nfs4_rmdir_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_create_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_create_async(nfs, path, flags, mode, cb, private_data); case NFS_V4: return nfs4_create_async(nfs, path, flags, mode, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { return nfs_create_async(nfs, path, 0, mode, cb, private_data); } int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_unlink_async(nfs, path, cb, private_data); case NFS_V4: return nfs4_unlink_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_mknod_async(nfs, path, mode, dev, cb, private_data); case NFS_V4: return nfs4_mknod_async(nfs, path, mode, dev, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_opendir_async(nfs, path, cb, private_data); case NFS_V4: return nfs4_opendir_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv4", __FUNCTION__); return -1; } } struct nfsdirent * nfs_readdir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir) { struct nfsdirent *nfsdirent = nfsdir->current; if (nfsdir->current != NULL) { nfsdir->current = nfsdir->current->next; } return nfsdirent; } long nfs_telldir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir) { long i; struct nfsdirent *tmp; for (i = 0, tmp = nfsdir->entries; tmp; i++, tmp = tmp->next) { if (tmp == nfsdir->current) { return i; } } return -1; } void nfs_seekdir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir, long loc) { if (loc < 0) { return; } for (nfsdir->current = nfsdir->entries; nfsdir && loc--; nfsdir = nfsdir->next) { } } void nfs_rewinddir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir) { nfsdir->current = nfsdir->entries; } void nfs_closedir(struct nfs_context *nfs, struct nfsdir *nfsdir) { if (nfs && nfs->dircache_enabled) { nfs_dircache_add(nfs, nfsdir); } else { nfs_free_nfsdir(nfsdir); } } void nfs_getcwd(struct nfs_context *nfs, const char **cwd) { if (cwd) { *cwd = nfs->cwd; } } int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_lseek_async(nfs, nfsfh, offset, whence, cb, private_data); case NFS_V4: return nfs4_lseek_async(nfs, nfsfh, offset, whence, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_lockf_async(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_lock_op op, uint64_t count, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V4: return nfs4_lockf_async(nfs, nfsfh, op, count, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_fcntl_async(struct nfs_context *nfs, struct nfsfh *nfsfh, enum nfs4_fcntl_op cmd, void *arg, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V4: return nfs4_fcntl_async(nfs, nfsfh, cmd, arg, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_statvfs_async(nfs, path, cb, private_data); case NFS_V4: return nfs4_statvfs_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_statvfs64_async(nfs, path, cb, private_data); case NFS_V4: return nfs4_statvfs64_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_readlink_async(nfs, path, cb, private_data); case NFS_V4: return nfs4_readlink_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_chmod_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_chmod_async_internal(nfs, path, 0, mode, cb, private_data); case NFS_V4: return nfs4_chmod_async_internal(nfs, path, 0, mode, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_lchmod_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_chmod_async_internal(nfs, path, 1, mode, cb, private_data); case NFS_V4: return nfs4_chmod_async_internal(nfs, path, 1, mode, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_fchmod_async(nfs, nfsfh, mode, cb, private_data); case NFS_V4: return nfs4_fchmod_async(nfs, nfsfh, mode, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_chown_async(struct nfs_context *nfs, const char *path, int uid, int gid, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_chown_async_internal(nfs, path, 0, uid, gid, cb, private_data); case NFS_V4: return nfs4_chown_async_internal(nfs, path, 0, uid, gid, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_lchown_async(struct nfs_context *nfs, const char *path, int uid, int gid, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_chown_async_internal(nfs, path, 1, uid, gid, cb, private_data); case NFS_V4: return nfs4_chown_async_internal(nfs, path, 1, uid, gid, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_fchown_async(nfs, nfsfh, uid, gid, cb, private_data); case NFS_V4: return nfs4_fchown_async(nfs, nfsfh, uid, gid, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_utimes_async(struct nfs_context *nfs, const char *path, struct timeval *times, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_utimes_async_internal(nfs, path, 0, times, cb, private_data); case NFS_V4: return nfs4_utimes_async_internal(nfs, path, 0, times, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_lutimes_async(struct nfs_context *nfs, const char *path, struct timeval *times, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_utimes_async_internal(nfs, path, 1, times, cb, private_data); case NFS_V4: return nfs4_utimes_async_internal(nfs, path, 1, times, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_utime_async(nfs, path, times, cb, private_data); case NFS_V4: return nfs4_utime_async(nfs, path, times, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv4", __FUNCTION__); return -1; } } int nfs_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_access_async(nfs, path, mode, cb, private_data); case NFS_V4: return nfs4_access_async(nfs, path, mode, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_access2_async(nfs, path, cb, private_data); case NFS_V4: return nfs4_access2_async(nfs, path, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv4", __FUNCTION__); return -1; } } int nfs_symlink_async(struct nfs_context *nfs, const char *target, const char *newpath, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_symlink_async(nfs, target, newpath, cb, private_data); case NFS_V4: return nfs4_symlink_async(nfs, target, newpath, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_rename_async(nfs, oldpath, newpath, cb, private_data); case NFS_V4: return nfs4_rename_async(nfs, oldpath, newpath, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } int nfs_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data) { switch (nfs->version) { case NFS_V3: return nfs3_link_async(nfs, oldpath, newpath, cb, private_data); case NFS_V4: return nfs4_link_async(nfs, oldpath, newpath, cb, private_data); default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); return -1; } } /* * Get the maximum supported READ3 size by the server */ uint64_t nfs_get_readmax(struct nfs_context *nfs) { return nfs->readmax; } /* * Get the maximum supported WRITE3 size by the server */ uint64_t nfs_get_writemax(struct nfs_context *nfs) { return nfs->writemax; } void nfs_set_tcp_syncnt(struct nfs_context *nfs, int v) { rpc_set_tcp_syncnt(nfs->rpc, v); } void nfs_set_uid(struct nfs_context *nfs, int uid) { rpc_set_uid(nfs->rpc, uid); } void nfs_set_gid(struct nfs_context *nfs, int gid) { rpc_set_gid(nfs->rpc, gid); } void nfs_set_pagecache(struct nfs_context *nfs, uint32_t v) { rpc_set_pagecache(nfs->rpc, v); } void nfs_set_pagecache_ttl(struct nfs_context *nfs, uint32_t v) { rpc_set_pagecache_ttl(nfs->rpc, v); } void nfs_set_readahead(struct nfs_context *nfs, uint32_t v) { rpc_set_readahead(nfs->rpc, v); } void nfs_set_debug(struct nfs_context *nfs, int level) { rpc_set_debug(nfs->rpc, level); } void nfs_set_dircache(struct nfs_context *nfs, int enabled) { nfs->dircache_enabled = enabled; } void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries) { nfs->auto_reconnect = num_retries; } int nfs_set_version(struct nfs_context *nfs, int version) { switch (version) { case NFS_V3: case NFS_V4: nfs->version = version; break; default: nfs_set_error(nfs, "NFS version %d is not supported", version); return -1; } return 0; } void nfs_set_error(struct nfs_context *nfs, char *error_string, ...) { va_list ap; char *str = NULL; va_start(ap, error_string); str = malloc(1024); vsnprintf(str, 1024, error_string, ap); if (nfs->rpc->error_string != NULL) { free(nfs->rpc->error_string); } nfs->rpc->error_string = str; va_end(ap); } struct mount_cb_data { rpc_cb cb; void *private_data; char *server; }; static void free_mount_cb_data(struct mount_cb_data *data) { if (data->server != NULL) { free(data->server); data->server = NULL; } free(data); } static void mount_export_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct mount_cb_data *data = private_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status != RPC_STATUS_SUCCESS) { data->cb(rpc, -EFAULT, command_data, data->private_data); free_mount_cb_data(data); return; } data->cb(rpc, 0, command_data, data->private_data); if (rpc_disconnect(rpc, "normal disconnect") != 0) { rpc_set_error(rpc, "Failed to disconnect\n"); } free_mount_cb_data(data); } static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct mount_cb_data *data = private_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); /* Dont want any more callbacks even if the socket is closed */ rpc->connect_cb = NULL; if (status != RPC_STATUS_SUCCESS) { data->cb(rpc, -EFAULT, command_data, data->private_data); free_mount_cb_data(data); return; } if (rpc_mount3_export_async(rpc, mount_export_5_cb, data) != 0) { data->cb(rpc, -ENOMEM, command_data, data->private_data); free_mount_cb_data(data); return; } } int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb cb, void *private_data) { struct mount_cb_data *data; assert(rpc->magic == RPC_CONTEXT_MAGIC); data = malloc(sizeof(struct mount_cb_data)); if (data == NULL) { return -1; } memset(data, 0, sizeof(struct mount_cb_data)); data->cb = cb; data->private_data = private_data; data->server = strdup(server); if (data->server == NULL) { free_mount_cb_data(data); return -1; } if (rpc_connect_program_async(rpc, data->server, MOUNT_PROGRAM, MOUNT_V3, mount_export_4_cb, data) != 0) { rpc_set_error(rpc, "Failed to start connection. %s", rpc_get_error(rpc)); free_mount_cb_data(data); return -1; } return 0; } struct rpc_context * nfs_get_rpc_context(struct nfs_context *nfs) { assert(nfs->rpc->magic == RPC_CONTEXT_MAGIC); return nfs->rpc; } const char * nfs_get_server(struct nfs_context *nfs) { return nfs->server; } const char * nfs_get_export(struct nfs_context *nfs) { return nfs->export; } const struct nfs_fh * nfs_get_rootfh(struct nfs_context *nfs) { return &nfs->rootfh; } struct nfs_fh * nfs_get_fh(struct nfsfh *nfsfh) { return &nfsfh->fh; } uint16_t nfs_umask(struct nfs_context *nfs, uint16_t mask) { uint16_t tmp = nfs->mask; nfs->mask = mask; return tmp; } /* * Sets timeout for nfs apis */ void nfs_set_timeout(struct nfs_context *nfs,int timeout) { rpc_set_timeout(nfs->rpc,timeout); } /* * Gets timeout for nfs apis */ int nfs_get_timeout(struct nfs_context *nfs) { return rpc_get_timeout(nfs->rpc); } int rpc_null_async(struct rpc_context *rpc, int program, int version, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, program, version, 0, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu " "for NULL call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu " "for NULL call"); return -1; } return 0; } libnfs-libnfs-4.0.0/lib/nfs_v3.c000066400000000000000000004454261343063627400164020ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2017 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ /* * High level api to nfsv3 filesystems */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #endif #ifdef HAVE_INTTYPES_H #include #else #define PRIu64 "llu" #endif #ifdef HAVE_UTIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #if defined(__ANDROID__) && !defined(HAVE_SYS_STATVFS_H) #define statvfs statfs #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef MAJOR_IN_MKDEV #include #endif #ifdef HAVE_SYS_SYSMACROS_H #include #endif #include #include #include #include #include #include #include #include #include #include #include "libnfs-zdr.h" #include "slist.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" #include "libnfs-private.h" static dev_t specdata3_to_rdev(struct specdata3 *rdev) { #ifdef makedev return makedev(rdev->specdata1, rdev->specdata2); #else return 0; #endif } struct mount_attr_cb { int wait_count; struct nfs_cb_data *data; }; struct mount_attr_item_cb { struct mount_attr_cb *ma; struct nested_mounts *mnt; }; struct nfs_mcb_data { struct nfs_cb_data *data; uint64_t offset; size_t count; }; static int check_nfs3_error(struct nfs_context *nfs, int status, struct nfs_cb_data *data, void *command_data) { if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); return 1; } if (status == RPC_STATUS_CANCEL) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); return 1; } if (status == RPC_STATUS_TIMEOUT) { data->cb(-EINTR, nfs, "Command timed out", data->private_data); return 1; } return 0; } static int nfs3_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_attr *attr, struct nfs_cb_data *data, struct nfs_fh *fh); /* * Functions to first look up a path, component by component, and then finally * call a specific function once the filehandle for the final component is * found. */ static void nfs3_lookup_path_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; READLINK3res *res; char *path, *newpath; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: READLINK of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } path = res->READLINK3res_u.resok.data; /* Handle absolute paths, ensuring that the path lies within the * export. */ if (path[0] == '/') { if (strstr(path, nfs->export) == path) { char *ptr = path + strlen(nfs->export); if (*ptr == '/') { newpath = strdup(ptr); } else if (*ptr == '\0') { newpath = strdup("/"); } else { data->cb(-ENOENT, nfs, "Symbolic link points " "outside export", data->private_data); free_nfs_cb_data(data); return; } } else { data->cb(-ENOENT, nfs, "Symbolic link points outside " "export", data->private_data); free_nfs_cb_data(data); return; } if (!newpath) goto nomem; } else { /* Handle relative paths, both the case where the current * component is an intermediate component and when it is the * final component. */ if (data->path[0]) { /* Since path points to a component and saved_path * always starts with '/', path[-1] is valid. */ data->path[-1] = '\0'; newpath = malloc(strlen(data->saved_path) + strlen(path) + strlen(data->path) + 6); if (!newpath) goto nomem; sprintf(newpath, "%s/../%s/%s", data->saved_path, path, data->path); } else { newpath = malloc(strlen(data->saved_path) + strlen(path) + 5); if (!newpath) goto nomem; sprintf(newpath, "%s/../%s", data->saved_path, path); } } free(data->saved_path); data->saved_path = newpath; if (nfs_normalize_path(nfs, data->saved_path) != 0) { data->cb(-ENOENT, nfs, "Symbolic link resolves to invalid " "path", data->private_data); free_nfs_cb_data(data); return; } data->path = data->saved_path; nfs3_lookup_path_async_internal(nfs, NULL, data, &nfs->rootfh); return; nomem: data->cb(-ENOMEM, nfs, "Failed to allocate memory for path", data->private_data); free_nfs_cb_data(data); } static void fattr3_to_nfs_attr(struct nfs_attr *attr, fattr3 *fa3) { attr->type = fa3->type; attr->mode = fa3->mode; attr->uid = fa3->uid; attr->gid = fa3->gid; attr->nlink = fa3->nlink; attr->size = fa3->size; attr->used = fa3->used; attr->fsid = fa3->fsid; attr->rdev.specdata1 = fa3->rdev.specdata1; attr->rdev.specdata2 = fa3->rdev.specdata2; attr->atime.seconds = fa3->atime.seconds; attr->atime.nseconds = fa3->atime.nseconds; attr->mtime.seconds = fa3->mtime.seconds; attr->mtime.nseconds = fa3->mtime.nseconds; attr->ctime.seconds = fa3->ctime.seconds; attr->ctime.nseconds = fa3->ctime.nseconds; } static void nfs3_lookup_path_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; LOOKUP3res *res; struct nfs_attr attr; struct nfs_fh fh; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: Lookup of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } memset(&attr, 0, sizeof(attr)); if (res->LOOKUP3res_u.resok.obj_attributes.attributes_follow) { fattr3_to_nfs_attr(&attr, &res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes); } /* This function will always invoke the callback and cleanup * for failures. So no need to check the return value. */ fh.val = res->LOOKUP3res_u.resok.object.data.data_val; fh.len = res->LOOKUP3res_u.resok.object.data.data_len; nfs3_lookup_path_async_internal(nfs, &attr, data, &fh); } static int nfs3_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_attr *attr, struct nfs_cb_data *data, struct nfs_fh *fh) { char *path, *slash; LOOKUP3args args; while (*data->path == '/') { data->path++; } path = data->path; slash = strchr(path, '/'); if (attr && attr->type == NF3LNK) { if (data->continue_int & O_NOFOLLOW) { data->cb(-ELOOP, nfs, "Symbolic link encountered", data->private_data); free_nfs_cb_data(data); return -1; } if (!data->no_follow || *path != '\0') { READLINK3args rl_args; if (data->link_count++ >= MAX_LINK_COUNT) { data->cb(-ELOOP, nfs, "Too many levels of " "symbolic links", data->private_data); free_nfs_cb_data(data); return -1; } rl_args.symlink.data.data_len = fh->len; rl_args.symlink.data.data_val = fh->val; if (rpc_nfs3_readlink_async(nfs->rpc, nfs3_lookup_path_2_cb, &rl_args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to " "send READLINK call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } if (slash != NULL) { *slash = '/'; } return 0; } } if (slash != NULL) { /* Clear slash so that path is a zero terminated string for * the current path component. Set it back to '/' again later * when we are finished referencing this component so that * data->saved_path will still point to the full * normalized path. */ *slash = 0; data->path = slash+1; } else { while (*data->path != 0) { data->path++; } } if (*path == 0) { data->fh.len = fh->len; data->fh.val = malloc(data->fh.len); if (data->fh.val == NULL) { nfs_set_error(nfs, "Out of memory: Failed to " "allocate fh for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } memcpy(data->fh.val, fh->val, data->fh.len); if (slash != NULL) { *slash = '/'; } data->continue_cb(nfs, attr, data); return 0; } memset(&args, 0, sizeof(LOOKUP3args)); args.what.dir.data.data_len = fh->len; args.what.dir.data.data_val = fh->val; args.what.name = path; if (rpc_nfs3_lookup_async(nfs->rpc, nfs3_lookup_path_1_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send lookup " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } if (slash != NULL) { *slash = '/'; } return 0; } static void nfs3_lookup_path_getattr_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; GETATTR3res *res; struct nfs_attr attr; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: GETATTR of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } fattr3_to_nfs_attr(&attr, &res->GETATTR3res_u.resok.obj_attributes); /* This function will always invoke the callback and cleanup * for failures. So no need to check the return value. */ nfs3_lookup_path_async_internal(nfs, &attr, data, &nfs->rootfh); } /* This function will free continue_data on error */ static int nfs3_lookuppath_async(struct nfs_context *nfs, const char *path, int no_follow, nfs_cb cb, void *private_data, continue_func continue_cb, void *continue_data, void (*free_continue_data)(void *), uint64_t continue_int) { struct nfs_cb_data *data; struct GETATTR3args args; struct nfs_fh *fh; if (path == NULL || path[0] == '\0') { path = "."; } data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory: failed to allocate " "nfs_cb_data structure"); if (continue_data) { free_continue_data(continue_data); } return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->continue_cb = continue_cb; data->continue_data = continue_data; data->free_continue_data = free_continue_data; data->continue_int = continue_int; data->private_data = private_data; data->no_follow = no_follow; if (path[0] == '/') { data->saved_path = strdup(path); } else { data->saved_path = malloc(strlen(path) + strlen(nfs->cwd) + 2); if (data->saved_path == NULL) { nfs_set_error(nfs, "Out of memory: failed to " "allocate path string"); free_nfs_cb_data(data); return -1; } sprintf(data->saved_path, "%s/%s", nfs->cwd, path); } if (data->saved_path == NULL) { nfs_set_error(nfs, "Out of memory: failed to copy path " "string"); free_nfs_cb_data(data); return -1; } if (nfs_normalize_path(nfs, data->saved_path) != 0) { free_nfs_cb_data(data); return -1; } data->path = data->saved_path; fh = &nfs->rootfh; if (data->path[0]) { struct nested_mounts *mnt; /* Make sure we match on longest nested export. * TODO: If we make sure the list is sorted we can skip this * check and end the loop on first match. */ size_t max_match_len = 0; /* Do we need to switch to a different nested export ? */ for (mnt = nfs->nested_mounts; mnt; mnt = mnt->next) { if (strlen(mnt->path) < max_match_len) continue; if (strncmp(mnt->path, data->saved_path, strlen(mnt->path))) continue; if (data->saved_path[strlen(mnt->path)] != '\0' && data->saved_path[strlen(mnt->path)] != '/') continue; data->saved_path = strdup(data->path + strlen(mnt->path)); free(data->path); data->path = data->saved_path; fh = &mnt->fh; max_match_len = strlen(mnt->path); } /* This function will always invoke the callback and cleanup * for failures. So no need to check the return value. */ nfs3_lookup_path_async_internal(nfs, NULL, data, fh); return 0; } /* We have a request for "", so just perform a GETATTR3 so we can * return the attributes to the caller. */ memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = fh->len; args.object.data.data_val = fh->val; if (rpc_nfs3_getattr_async(nfs->rpc, nfs3_lookup_path_getattr_cb, &args, data) != 0) { free_nfs_cb_data(data); return -1; } return 0; } static void nfs3_mount_8_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct mount_attr_item_cb *ma_item = private_data; struct mount_attr_cb *ma = ma_item->ma; struct nfs_cb_data *data = ma->data; struct nfs_context *nfs = data->nfs; GETATTR3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status != RPC_STATUS_SUCCESS) { goto finished; } res = command_data; if (res->status != NFS3_OK) goto finished; fattr3_to_nfs_attr(&ma_item->mnt->attr, &res->GETATTR3res_u.resok.obj_attributes); finished: free(ma_item); ma->wait_count--; if (ma->wait_count > 0) return; free(ma); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static void nfs3_mount_7_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct mount_attr_cb *ma = NULL; struct nested_mounts *mnt; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } if (!nfs->nested_mounts) goto finished; /* nested mount traversals are best-effort only, so any * failures just means that we don't get traversal for that * particular mount. We do not fail the call from the application. */ ma = malloc(sizeof(struct mount_attr_cb)); if (ma == NULL) goto finished; memset(ma, 0, sizeof(struct mount_attr_cb)); ma->data = data; for(mnt = nfs->nested_mounts; mnt; mnt = mnt->next) { struct mount_attr_item_cb *ma_item; struct GETATTR3args args; ma_item = malloc(sizeof(struct mount_attr_item_cb)); if (ma_item == NULL) goto finished; ma_item->mnt = mnt; ma_item->ma = ma; memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = mnt->fh.len; args.object.data.data_val = mnt->fh.val; if (rpc_nfs3_getattr_async(rpc, nfs3_mount_8_cb, &args, ma_item) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); free(ma_item); continue; } ma->wait_count++; } finished: if (ma && ma->wait_count) return; free(ma); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static void nfs3_mount_6_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; FSINFO3res *res = command_data; struct GETATTR3args args; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: FSINFO of %s failed with %s(%d)", nfs->export, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs->readmax = res->FSINFO3res_u.resok.rtmax; nfs->writemax = res->FSINFO3res_u.resok.wtmax; /* The server supports sizes up to rtmax and wtmax, so it is legal * to use smaller transfers sizes. */ if (nfs->readmax > NFS_MAX_XFER_SIZE) nfs->readmax = NFS_MAX_XFER_SIZE; else if (nfs->readmax < NFSMAXDATA2) { nfs_set_error(nfs, "server max rsize of %" PRIu64, nfs->readmax); data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } if (nfs->writemax > NFS_MAX_XFER_SIZE) nfs->writemax = NFS_MAX_XFER_SIZE; else if (nfs->writemax < NFSMAXDATA2) { nfs_set_error(nfs, "server max wsize of %" PRIu64, nfs->writemax); data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = nfs->rootfh.len; args.object.data.data_val = nfs->rootfh.val; if (rpc_nfs3_getattr_async(rpc, nfs3_mount_7_cb, &args, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } } static void nfs3_mount_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct FSINFO3args args; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } /* NFS TCP: As we are connected now we can pass on the auto-reconnect * settings to the RPC layer. */ rpc_set_autoreconnect(rpc, nfs->auto_reconnect); args.fsroot.data.data_len = nfs->rootfh.len; args.fsroot.data.data_val = nfs->rootfh.val; if (rpc_nfs3_fsinfo_async(rpc, nfs3_mount_6_cb, &args, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } } struct mount_discovery_cb { int wait_count; int error; int status; struct nfs_cb_data *data; }; struct mount_discovery_item_cb { struct mount_discovery_cb *md_cb; char *path; }; static void nfs3_mount_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct mount_discovery_item_cb *md_item_cb = private_data; struct mount_discovery_cb *md_cb = md_item_cb->md_cb; struct nfs_cb_data *data = md_cb->data; struct nfs_context *nfs = data->nfs; mountres3 *res; struct nested_mounts *mnt; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status == RPC_STATUS_ERROR) { nfs_set_error(nfs, "MOUNT failed with RPC_STATUS_ERROR"); md_cb->error = -EFAULT; goto finished; } if (status == RPC_STATUS_CANCEL) { nfs_set_error(nfs, "MOUNT failed with RPC_STATUS_CANCEL"); md_cb->status = RPC_STATUS_CANCEL; goto finished; } if (status == RPC_STATUS_TIMEOUT) { nfs_set_error(nfs, "MOUNT timed out"); md_cb->status = RPC_STATUS_TIMEOUT; goto finished; } res = command_data; if (res->fhs_status != MNT3_OK) { nfs_set_error(nfs, "RPC error: Mount failed with error " "%s(%d) %s(%d)", mountstat3_to_str(res->fhs_status), res->fhs_status, strerror(-mountstat3_to_errno(res->fhs_status)), -mountstat3_to_errno(res->fhs_status)); md_cb->error = mountstat3_to_errno(res->fhs_status); goto finished; } mnt = malloc(sizeof(*mnt)); if (mnt == NULL) { nfs_set_error(nfs, "Out of memory. Could not allocate memory " "to store mount handle"); md_cb->error = -ENOMEM; goto finished; } memset(mnt, 0, sizeof(*mnt)); mnt->fh.len = res->mountres3_u.mountinfo.fhandle.fhandle3_len; mnt->fh.val = malloc(mnt->fh.len); if (mnt->fh.val == NULL) { free(mnt); goto finished; } memcpy(mnt->fh.val, res->mountres3_u.mountinfo.fhandle.fhandle3_val, mnt->fh.len); mnt->path = md_item_cb->path; md_item_cb->path = NULL; LIBNFS_LIST_ADD(&nfs->nested_mounts, mnt); finished: free(md_item_cb->path); free(md_item_cb); md_cb->wait_count--; if (md_cb->wait_count > 0) return; rpc_disconnect(rpc, "normal disconnect"); if (md_cb->status == RPC_STATUS_CANCEL) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); free(md_cb); free_nfs_cb_data(data); return; } if (md_cb->error) { data->cb(md_cb->error, nfs, command_data, data->private_data); free(md_cb); free_nfs_cb_data(data); return; } if (nfs->nfsport) { if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport, NFS_PROGRAM, NFS_V3, nfs3_mount_5_cb, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free(md_cb); free_nfs_cb_data(data); return; } return; } if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM, NFS_V3, nfs3_mount_5_cb, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free(md_cb); free_nfs_cb_data(data); return; } free(md_cb); } static void nfs3_mount_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; exports res; int len; struct mount_discovery_cb *md_cb = NULL; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } /* Iterate over all exports and check if there are any mounts nested * below the current mount. */ len = strlen(nfs->export); if (!len) { data->cb(-EFAULT, nfs, "Export is empty", data->private_data); free_nfs_cb_data(data); return; } res = *(exports *)command_data; while (res) { struct mount_discovery_item_cb *md_item_cb; if (strncmp(nfs->export, res->ex_dir, len)) { res = res->ex_next; continue; } if (res->ex_dir[len - 1] != '/' && res->ex_dir[len] != '/') { res = res->ex_next; continue; } /* There is no need to fail the whole mount if anything * below fails. Just clean up and continue. At worst it * just mean that we might not be able to access any nested * mounts. */ md_item_cb = malloc(sizeof(*md_item_cb)); if (md_item_cb == NULL) continue; memset(md_item_cb, 0, sizeof(*md_item_cb)); md_item_cb->path = strdup(res->ex_dir + len - (nfs->export[len -1] == '/')); if (md_item_cb->path == NULL) { free(md_item_cb); continue; } if (md_cb == NULL) { md_cb = malloc(sizeof(*md_cb)); if (md_cb == NULL) { free(md_item_cb->path); free(md_item_cb); continue; } memset(md_cb, 0, sizeof(*md_cb)); md_cb->data = data; md_cb->status = RPC_STATUS_SUCCESS; md_cb->error = 0; } md_item_cb->md_cb = md_cb; if (rpc_mount3_mnt_async(rpc, nfs3_mount_4_cb, res->ex_dir, md_item_cb) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); if (md_cb->wait_count == 0) { free(md_cb); md_cb = NULL; } free(md_item_cb->path); free(md_item_cb); continue; } md_cb->wait_count++; res = res->ex_next; } if (md_cb) return; /* We did not have any nested mounts to check so we can proceed straight * to reconnecting to NFSd. */ rpc_disconnect(rpc, "normal disconnect"); if (nfs->nfsport) { if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport, NFS_PROGRAM, NFS_V3, nfs3_mount_5_cb, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } return; } if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM, NFS_V3, nfs3_mount_5_cb, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } } static void nfs3_mount_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; mountres3 *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->fhs_status != MNT3_OK) { nfs_set_error(nfs, "RPC error: Mount failed with error " "%s(%d) %s(%d)", mountstat3_to_str(res->fhs_status), res->fhs_status, strerror(-mountstat3_to_errno(res->fhs_status)), -mountstat3_to_errno(res->fhs_status)); data->cb(mountstat3_to_errno(res->fhs_status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs->rootfh.len = res->mountres3_u.mountinfo.fhandle.fhandle3_len; nfs->rootfh.val = malloc(nfs->rootfh.len); if (nfs->rootfh.val == NULL) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } memcpy(nfs->rootfh.val, res->mountres3_u.mountinfo.fhandle.fhandle3_val, nfs->rootfh.len); if (nfs->auto_traverse_mounts) { if (rpc_mount3_export_async(rpc, nfs3_mount_3_cb, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } return; } rpc_disconnect(rpc, "normal disconnect"); if (nfs->nfsport) { if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport, NFS_PROGRAM, NFS_V3, nfs3_mount_5_cb, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } return; } if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM, NFS_V3, nfs3_mount_5_cb, data) != 0) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } } static void nfs3_mount_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } if (rpc_mount3_mnt_async(rpc, nfs3_mount_2_cb, nfs->export, data) != 0) { nfs_set_error(nfs, "%s: %s.", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } } int nfs3_mount_async(struct nfs_context *nfs, const char *server, const char *export, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; char *new_server, *new_export; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory. failed to allocate " "memory for nfs mount data"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); new_server = strdup(server); new_export = strdup(export); if (nfs->server != NULL) { free(nfs->server); } nfs->server = new_server; if (nfs->export != NULL) { free(nfs->export); } nfs->export = new_export; data->nfs = nfs; data->cb = cb; data->private_data = private_data; if (nfs->mountport) { if (rpc_connect_port_async(nfs->rpc, server, nfs->mountport, MOUNT_PROGRAM, MOUNT_V3, nfs3_mount_1_cb, data) != 0) { nfs_set_error(nfs, "Failed to start connection. %s", nfs_get_error(nfs)); free_nfs_cb_data(data); return -1; } return 0; } if (rpc_connect_program_async(nfs->rpc, server, MOUNT_PROGRAM, MOUNT_V3, nfs3_mount_1_cb, data) != 0) { nfs_set_error(nfs, "Failed to start connection. %s", nfs_get_error(nfs)); free_nfs_cb_data(data); return -1; } return 0; } static void nfs3_umount_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } rpc_disconnect(rpc, "umount"); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static void nfs3_umount_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } if (rpc_mount3_umnt_async(rpc, nfs3_umount_2_cb, nfs->export, data) != 0) { nfs_set_error(nfs, "%s: %s.", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } } int nfs3_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory. failed to allocate " "memory for nfs mount data"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; rpc_disconnect(nfs->rpc, "umount"); if (nfs->mountport) { if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->mountport, MOUNT_PROGRAM, MOUNT_V3, nfs3_umount_1_cb, data) != 0) { nfs_set_error(nfs, "Failed to start connection. %s", nfs_get_error(nfs)); free_nfs_cb_data(data); return -1; } return 0; } if (rpc_connect_program_async(nfs->rpc, nfs->server, MOUNT_PROGRAM, MOUNT_V3, nfs3_umount_1_cb, data) != 0) { nfs_set_error(nfs, "Failed to start connection. %s", nfs_get_error(nfs)); free_nfs_cb_data(data); return -1; } return 0; } struct nfs_link_data { char *oldpath; struct nfs_fh oldfh; char *newparent; char *newobject; struct nfs_fh newdir; }; static void free_nfs_link_data(void *mem) { struct nfs_link_data *data = mem; free(data->oldpath); free(data->oldfh.val); free(data->newparent); free(data->newobject); free(data->newdir.val); free(data); } static void nfs3_link_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { LINK3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfs_link_data *link_data = data->continue_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: LINK %s -> %s/%s failed with " "%s(%d)", link_data->oldpath, link_data->newparent, link_data->newobject, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &link_data->newdir); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_link_continue_2_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct nfs_link_data *link_data = data->continue_data; LINK3args args; /* steal the filehandle */ link_data->newdir = data->fh; data->fh.val = NULL; memset(&args, 0, sizeof(LINK3args)); args.file.data.data_len = link_data->oldfh.len; args.file.data.data_val = link_data->oldfh.val; args.link.dir.data.data_len = link_data->newdir.len; args.link.dir.data.data_val = link_data->newdir.val; args.link.name = link_data->newobject; if (rpc_nfs3_link_async(nfs->rpc, nfs3_link_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send LINK " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } static int nfs3_link_continue_1_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct nfs_link_data *link_data = data->continue_data; /* steal the filehandle */ link_data->oldfh = data->fh; data->fh.val = NULL; if (nfs3_lookuppath_async(nfs, link_data->newparent, 0, data->cb, data->private_data, nfs3_link_continue_2_internal, link_data, free_nfs_link_data, 0) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); data->continue_data = NULL; free_nfs_cb_data(data); return -1; } data->continue_data = NULL; free_nfs_cb_data(data); return 0; } int nfs3_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data) { char *ptr; struct nfs_link_data *link_data; link_data = malloc(sizeof(struct nfs_link_data)); if (link_data == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for link data"); return -1; } memset(link_data, 0, sizeof(struct nfs_link_data)); link_data->oldpath = strdup(oldpath); if (link_data->oldpath == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for oldpath"); free_nfs_link_data(link_data); return -1; } link_data->newobject = strdup(newpath); if (link_data->newobject == NULL) { nfs_set_error(nfs, "Out of memory, failed to strdup " "newpath"); free_nfs_link_data(link_data); return -1; } ptr = strrchr(link_data->newobject, '/'); if (ptr == NULL) { link_data->newparent = NULL; } else { *ptr = 0; link_data->newparent = link_data->newobject; ptr++; link_data->newobject = strdup(ptr); } if (link_data->newobject == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for newobject"); free_nfs_link_data(link_data); return -1; } if (nfs3_lookuppath_async(nfs, link_data->oldpath, 0, cb, private_data, nfs3_link_continue_1_internal, link_data, free_nfs_link_data, 0) != 0) { return -1; } return 0; } struct nfs_rename_data { char *oldparent; char *oldobject; struct nfs_fh olddir; char *newparent; char *newobject; struct nfs_fh newdir; }; static void free_nfs_rename_data(void *mem) { struct nfs_rename_data *data = mem; free(data->oldparent); free(data->oldobject); free(data->olddir.val); free(data->newparent); free(data->newobject); free(data->newdir.val); free(data); } static void nfs3_rename_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { RENAME3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfs_rename_data *rename_data = data->continue_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: RENAME %s/%s -> %s/%s failed " "with %s(%d)", rename_data->oldparent, rename_data->oldobject, rename_data->newparent, rename_data->newobject, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct nfs_rename_data *rename_data = data->continue_data; RENAME3args args; /* Drop the destination directory from the cache */ nfs_dircache_drop(nfs, &data->fh); /* steal the filehandle */ rename_data->newdir = data->fh; data->fh.val = NULL; args.from.dir.data.data_len = rename_data->olddir.len; args.from.dir.data.data_val = rename_data->olddir.val; args.from.name = rename_data->oldobject; args.to.dir.data.data_len = rename_data->newdir.len; args.to.dir.data.data_val = rename_data->newdir.val; args.to.name = rename_data->newobject; if (rpc_nfs3_rename_async(nfs->rpc, nfs3_rename_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send RENAME " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } static int nfs3_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct nfs_rename_data *rename_data = data->continue_data; /* Drop the source directory from the cache */ nfs_dircache_drop(nfs, &data->fh); /* steal the filehandle */ rename_data->olddir = data->fh; data->fh.val = NULL; if (nfs3_lookuppath_async(nfs, rename_data->newparent, 0, data->cb, data->private_data, nfs3_rename_continue_2_internal, rename_data, free_nfs_rename_data, 0) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); data->continue_data = NULL; free_nfs_cb_data(data); return -1; } data->continue_data = NULL; free_nfs_cb_data(data); return 0; } int nfs3_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data) { char *ptr; struct nfs_rename_data *rename_data; rename_data = malloc(sizeof(struct nfs_rename_data)); if (rename_data == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for rename data"); return -1; } memset(rename_data, 0, sizeof(struct nfs_rename_data)); rename_data->oldobject = strdup(oldpath); if (rename_data->oldobject == NULL) { nfs_set_error(nfs, "Out of memory, failed to strdup " "oldpath"); free_nfs_rename_data(rename_data); return -1; } ptr = strrchr(rename_data->oldobject, '/'); if (ptr == NULL) { rename_data->oldparent = NULL; } else { *ptr = 0; rename_data->oldparent = rename_data->oldobject; ptr++; rename_data->oldobject = strdup(ptr); } if (rename_data->oldobject == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for oldobject"); free_nfs_rename_data(rename_data); return -1; } rename_data->newobject = strdup(newpath); if (rename_data->newobject == NULL) { nfs_set_error(nfs, "Out of memory, failed to strdup " "newpath"); free_nfs_rename_data(rename_data); return -1; } ptr = strrchr(rename_data->newobject, '/'); if (ptr == NULL) { rename_data->newparent = NULL; } else { *ptr = 0; rename_data->newparent = rename_data->newobject; ptr++; rename_data->newobject = strdup(ptr); } if (rename_data->newobject == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for newobject"); free_nfs_rename_data(rename_data); return -1; } if (nfs3_lookuppath_async(nfs, rename_data->oldparent, 0, cb, private_data, nfs3_rename_continue_1_internal, rename_data, free_nfs_rename_data, 0) != 0) { return -1; } return 0; } struct nfs_symlink_data { char *target; char *linkparent; char *linkobject; }; static void free_nfs_symlink_data(void *mem) { struct nfs_symlink_data *data = mem; free(data->target); free(data->linkparent); free(data->linkobject); free(data); } static void nfs3_symlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { SYMLINK3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfs_symlink_data *symlink_data = data->continue_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: SYMLINK %s/%s -> %s failed with " "%s(%d)", symlink_data->linkparent, symlink_data->linkobject, symlink_data->target, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_symlink_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct nfs_symlink_data *symlink_data = data->continue_data; SYMLINK3args args; memset(&args, 0, sizeof(SYMLINK3args)); args.where.dir.data.data_len = data->fh.len; args.where.dir.data.data_val = data->fh.val; args.where.name = symlink_data->linkobject; args.symlink.symlink_attributes.mode.set_it = 1; args.symlink.symlink_attributes.mode.set_mode3_u.mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH; args.symlink.symlink_data = symlink_data->target; if (rpc_nfs3_symlink_async(nfs->rpc, nfs3_symlink_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send SYMLINK " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_symlink_async(struct nfs_context *nfs, const char *target, const char *linkname, nfs_cb cb, void *private_data) { char *ptr; struct nfs_symlink_data *symlink_data; symlink_data = malloc(sizeof(struct nfs_symlink_data)); if (symlink_data == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for symlink data"); return -1; } memset(symlink_data, 0, sizeof(struct nfs_symlink_data)); symlink_data->target = strdup(target); if (symlink_data->target == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for target"); free_nfs_symlink_data(symlink_data); return -1; } symlink_data->linkobject = strdup(linkname); if (symlink_data->linkobject == NULL) { nfs_set_error(nfs, "Out of memory, failed to strdup " "linkname"); free_nfs_symlink_data(symlink_data); return -1; } ptr = strrchr(symlink_data->linkobject, '/'); if (ptr == NULL) { symlink_data->linkparent = NULL; } else { *ptr = 0; symlink_data->linkparent = symlink_data->linkobject; ptr++; symlink_data->linkobject = strdup(ptr); } if (symlink_data->linkobject == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "mode buffer for new path"); free_nfs_symlink_data(symlink_data); return -1; } if (nfs3_lookuppath_async(nfs, symlink_data->linkparent, 0, cb, private_data, nfs3_symlink_continue_internal, symlink_data, free_nfs_symlink_data, 0) != 0) { return -1; } return 0; } static void nfs3_access2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { ACCESS3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; unsigned int result = 0; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: ACCESS of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } if (res->ACCESS3res_u.resok.access & ACCESS3_READ) { result |= R_OK; } if (res->ACCESS3res_u.resok.access & (ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE)) { result |= W_OK; } if (res->ACCESS3res_u.resok.access & (ACCESS3_LOOKUP | ACCESS3_EXECUTE)) { result |= X_OK; } data->cb(result, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_access2_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { ACCESS3args args; memset(&args, 0, sizeof(ACCESS3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; args.access = ACCESS3_READ | ACCESS3_LOOKUP | ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE | ACCESS3_EXECUTE; if (rpc_nfs3_access_async(nfs->rpc, nfs3_access2_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_access2_continue_internal, NULL, NULL, 0) != 0) { return -1; } return 0; } static void nfs3_access_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { ACCESS3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; unsigned int mode = 0; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: ACCESS of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } if ((data->continue_int & R_OK) && (res->ACCESS3res_u.resok.access & ACCESS3_READ)) { mode |= R_OK; } if ((data->continue_int & W_OK) && (res->ACCESS3res_u.resok.access & (ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE))) { mode |= W_OK; } if ((data->continue_int & X_OK) && (res->ACCESS3res_u.resok.access & (ACCESS3_LOOKUP | ACCESS3_EXECUTE))) { mode |= X_OK; } if (data->continue_int != mode) { nfs_set_error(nfs, "NFS: ACCESS denied. Required access " "%c%c%c. Allowed access %c%c%c", data->continue_int&R_OK?'r':'-', data->continue_int&W_OK?'w':'-', data->continue_int&X_OK?'x':'-', mode&R_OK?'r':'-', mode&W_OK?'w':'-', mode&X_OK?'x':'-'); data->cb(-EACCES, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_access_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { int nfsmode = 0; ACCESS3args args; if (data->continue_int & R_OK) { nfsmode |= ACCESS3_READ; } if (data->continue_int & W_OK) { nfsmode |= ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE; } if (data->continue_int & X_OK) { nfsmode |= ACCESS3_LOOKUP | ACCESS3_EXECUTE; } memset(&args, 0, sizeof(ACCESS3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; args.access = nfsmode; if (rpc_nfs3_access_async(nfs->rpc, nfs3_access_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_access_continue_internal, NULL, NULL, mode & (R_OK | W_OK | X_OK)) != 0) { return -1; } return 0; } static void nfs3_utimes_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; SETATTR3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_utimes_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { SETATTR3args args; struct timeval *utimes_data = data->continue_data; memset(&args, 0, sizeof(SETATTR3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; if (utimes_data != NULL) { args.new_attributes.atime.set_it = SET_TO_CLIENT_TIME; args.new_attributes.atime.set_atime_u.atime.seconds = utimes_data[0].tv_sec; args.new_attributes.atime.set_atime_u.atime.nseconds = utimes_data[0].tv_usec * 1000; args.new_attributes.mtime.set_it = SET_TO_CLIENT_TIME; args.new_attributes.mtime.set_mtime_u.mtime.seconds = utimes_data[1].tv_sec; args.new_attributes.mtime.set_mtime_u.mtime.nseconds = utimes_data[1].tv_usec * 1000; } else { args.new_attributes.atime.set_it = SET_TO_SERVER_TIME; args.new_attributes.mtime.set_it = SET_TO_SERVER_TIME; } if (rpc_nfs3_setattr_async(nfs->rpc, nfs3_utimes_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send SETATTR " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_utimes_async_internal(struct nfs_context *nfs, const char *path, int no_follow, struct timeval *times, nfs_cb cb, void *private_data) { struct timeval *new_times = NULL; if (times != NULL) { new_times = malloc(sizeof(struct timeval)*2); if (new_times == NULL) { nfs_set_error(nfs, "Failed to allocate memory " "for timeval structure"); return -1; } memcpy(new_times, times, sizeof(struct timeval)*2); } if (nfs3_lookuppath_async(nfs, path, no_follow, cb, private_data, nfs3_utimes_continue_internal, new_times, free, 0) != 0) { return -1; } return 0; } int nfs3_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data) { struct timeval *new_times = NULL; if (times != NULL) { new_times = malloc(sizeof(struct timeval)*2); if (new_times == NULL) { nfs_set_error(nfs, "Failed to allocate memory " "for timeval structure"); return -1; } new_times[0].tv_sec = times->actime; new_times[0].tv_usec = 0; new_times[1].tv_sec = times->modtime; new_times[1].tv_usec = 0; } if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_utimes_continue_internal, new_times, free, 0) != 0) { return -1; } return 0; } static void nfs3_chown_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; SETATTR3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } struct nfs_chown_data { uid_t uid; gid_t gid; }; static int nfs3_chown_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { SETATTR3args args; struct nfs_chown_data *chown_data = data->continue_data; memset(&args, 0, sizeof(SETATTR3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; if (chown_data->uid != (uid_t)-1) { args.new_attributes.uid.set_it = 1; args.new_attributes.uid.set_uid3_u.uid = chown_data->uid; } if (chown_data->gid != (gid_t)-1) { args.new_attributes.gid.set_it = 1; args.new_attributes.gid.set_gid3_u.gid = chown_data->gid; } if (rpc_nfs3_setattr_async(nfs->rpc, nfs3_chown_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send SETATTR " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_chown_async_internal(struct nfs_context *nfs, const char *path, int no_follow, int uid, int gid, nfs_cb cb, void *private_data) { struct nfs_chown_data *chown_data; chown_data = malloc(sizeof(struct nfs_chown_data)); if (chown_data == NULL) { nfs_set_error(nfs, "Failed to allocate memory for " "chown data structure"); return -1; } chown_data->uid = uid; chown_data->gid = gid; if (nfs3_lookuppath_async(nfs, path, no_follow, cb, private_data, nfs3_chown_continue_internal, chown_data, free, 0) != 0) { return -1; } return 0; } int nfs3_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; struct nfs_chown_data *chown_data; chown_data = malloc(sizeof(struct nfs_chown_data)); if (chown_data == NULL) { nfs_set_error(nfs, "Failed to allocate memory for " "fchown data structure"); return -1; } chown_data->uid = uid; chown_data->gid = gid; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory. failed to allocate " "memory for fchown data"); free(chown_data); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->continue_data = chown_data; data->free_continue_data = free; data->fh.len = nfsfh->fh.len; data->fh.val = malloc(data->fh.len); if (data->fh.val == NULL) { nfs_set_error(nfs, "Out of memory: Failed to allocate fh"); free_nfs_cb_data(data); return -1; } memcpy(data->fh.val, nfsfh->fh.val, data->fh.len); if (nfs3_chown_continue_internal(nfs, NULL, data) != 0) { return -1; } return 0; } static void nfs3_chmod_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; SETATTR3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: SETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_chmod_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { SETATTR3args args; memset(&args, 0, sizeof(SETATTR3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; args.new_attributes.mode.set_it = 1; args.new_attributes.mode.set_mode3_u.mode = (mode3)data->continue_int; if (rpc_nfs3_setattr_async(nfs->rpc, nfs3_chmod_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send SETATTR " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_chmod_async_internal(struct nfs_context *nfs, const char *path, int no_follow, int mode, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, no_follow, cb, private_data, nfs3_chmod_continue_internal, NULL, NULL, mode) != 0) { return -1; } return 0; } int nfs3_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory. failed to allocate " "memory for fchmod data"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->continue_int = mode; data->fh.len = nfsfh->fh.len; data->fh.val = malloc(data->fh.len); if (data->fh.val == NULL) { nfs_set_error(nfs, "Out of memory: Failed to allocate fh"); free_nfs_cb_data(data); return -1; } memcpy(data->fh.val, nfsfh->fh.val, data->fh.len); if (nfs3_chmod_continue_internal(nfs, NULL, data) != 0) { return -1; } return 0; } static void nfs3_readlink_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { READLINK3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: READLINK of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } data->cb(0, nfs, res->READLINK3res_u.resok.data, data->private_data); free_nfs_cb_data(data); } static int nfs3_readlink_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { READLINK3args args; args.symlink.data.data_val = data->fh.val; args.symlink.data.data_len = data->fh.len; if (rpc_nfs3_readlink_async(nfs->rpc, nfs3_readlink_1_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send READLINK " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, 1, cb, private_data, nfs3_readlink_continue_internal, NULL, NULL, 0) != 0) { return -1; } return 0; } static void nfs3_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { FSSTAT3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct statvfs svfs; struct nfs_statvfs_64 svfs64; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: FSSTAT of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } if (data->continue_int == 0) { /* statvfs */ svfs.f_bsize = NFS_BLKSIZE; svfs.f_frsize = NFS_BLKSIZE; svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/NFS_BLKSIZE; svfs.f_bfree = res->FSSTAT3res_u.resok.fbytes/NFS_BLKSIZE; svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/NFS_BLKSIZE; svfs.f_files = (uint32_t)res->FSSTAT3res_u.resok.tfiles; svfs.f_ffree = (uint32_t)res->FSSTAT3res_u.resok.ffiles; #if !defined(__ANDROID__) svfs.f_favail = (uint32_t)res->FSSTAT3res_u.resok.afiles; svfs.f_fsid = 0; svfs.f_flag = 0; svfs.f_namemax = 256; #endif data->cb(0, nfs, &svfs, data->private_data); } else { /* statvfs64 */ svfs64.f_bsize = NFS_BLKSIZE; svfs64.f_frsize = NFS_BLKSIZE; svfs64.f_blocks = res->FSSTAT3res_u.resok.tbytes/NFS_BLKSIZE; svfs64.f_bfree = res->FSSTAT3res_u.resok.fbytes/NFS_BLKSIZE; svfs64.f_bavail = res->FSSTAT3res_u.resok.abytes/NFS_BLKSIZE; svfs64.f_files = res->FSSTAT3res_u.resok.tfiles; svfs64.f_ffree = res->FSSTAT3res_u.resok.ffiles; svfs64.f_favail = res->FSSTAT3res_u.resok.afiles; svfs64.f_fsid = 0; svfs64.f_flag = 0; svfs64.f_namemax = 256; data->cb(0, nfs, &svfs64, data->private_data); } free_nfs_cb_data(data); } static int nfs3_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { FSSTAT3args args; args.fsroot.data.data_len = data->fh.len; args.fsroot.data.data_val = data->fh.val; if (rpc_nfs3_fsstat_async(nfs->rpc, nfs3_statvfs_1_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send FSSTAT " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_statvfs_continue_internal, NULL, NULL, 0) != 0) { return -1; } return 0; } int nfs3_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_statvfs_continue_internal, NULL, NULL, 1) != 0) { return -1; } return 0; } static void nfs3_lseek_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { GETATTR3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; int64_t size = 0; int64_t offset = (int64_t) data->offset; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: GETATTR failed with " "%s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free(data); return; } size = (int64_t)res->GETATTR3res_u.resok.obj_attributes.size; if (offset < 0 && -offset > (int64_t)size) { data->cb(-EINVAL, nfs, &data->nfsfh->offset, data->private_data); } else { data->nfsfh->offset = data->offset + size; data->cb(0, nfs, &data->nfsfh->offset, data->private_data); } free(data); } int nfs3_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; struct GETATTR3args args; if (whence == SEEK_SET) { if (offset < 0) { cb(-EINVAL, nfs, &nfsfh->offset, private_data); } else { nfsfh->offset = offset; cb(0, nfs, &nfsfh->offset, private_data); } return 0; } if (whence == SEEK_CUR) { if (offset < 0 && nfsfh->offset < (uint64_t)(-offset)) { cb(-EINVAL, nfs, &nfsfh->offset, private_data); } else { nfsfh->offset += offset; cb(0, nfs, &nfsfh->offset, private_data); } return 0; } data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "Out Of Memory: Failed to malloc nfs " "cb data"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->nfsfh = nfsfh; data->offset = offset; data->cb = cb; data->private_data = private_data; memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = nfsfh->fh.len; args.object.data.data_val = nfsfh->fh.val; if (rpc_nfs3_getattr_async(nfs->rpc, nfs3_lseek_1_cb, &args, data) != 0) { free(data); return -1; } return 0; } /* ReadDirPlus Emulation Callback data */ struct rdpe_cb_data { int getattrcount; int status; struct nfs_cb_data *data; }; /* ReadDirPlus Emulation LOOKUP Callback data */ struct rdpe_lookup_cb_data { struct rdpe_cb_data *rdpe_cb_data; struct nfsdirent *nfsdirent; }; /* Workaround for servers lacking READDIRPLUS. * Use READDIR instead and a GETATTR-loop */ static void nfs3_opendir_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { LOOKUP3res *res = command_data; struct rdpe_lookup_cb_data *rdpe_lookup_cb_data = private_data; struct rdpe_cb_data *rdpe_cb_data = rdpe_lookup_cb_data->rdpe_cb_data; struct nfs_cb_data *data = rdpe_cb_data->data; struct nfsdir *nfsdir = data->continue_data; struct nfs_context *nfs = data->nfs; struct nfsdirent *nfsdirent = rdpe_lookup_cb_data->nfsdirent; assert(rpc->magic == RPC_CONTEXT_MAGIC); free(rdpe_lookup_cb_data); rdpe_cb_data->getattrcount--; if (status == RPC_STATUS_ERROR) { nfs_set_error(nfs, "LOOKUP during READDIRPLUS emulation " "failed with RPC_STATUS_ERROR"); rdpe_cb_data->status = RPC_STATUS_ERROR; } if (status == RPC_STATUS_CANCEL) { nfs_set_error(nfs, "LOOKUP during READDIRPLUS emulation " "failed with RPC_STATUS_CANCEL"); rdpe_cb_data->status = RPC_STATUS_CANCEL; } if (status == RPC_STATUS_TIMEOUT) { nfs_set_error(nfs, "LOOKUP during READDIRPLUS emulation " "timed out"); rdpe_cb_data->status = RPC_STATUS_CANCEL; } if (status == RPC_STATUS_SUCCESS && res->status == NFS3_OK) { if (res->LOOKUP3res_u.resok.obj_attributes.attributes_follow) { fattr3 *attributes = &res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes; nfsdirent->type = attributes->type; nfsdirent->mode = attributes->mode; switch (nfsdirent->type) { case NF3REG: nfsdirent->mode |= S_IFREG; break; case NF3DIR: nfsdirent->mode |= S_IFDIR; break; case NF3BLK: nfsdirent->mode |= S_IFBLK; break; case NF3CHR: nfsdirent->mode |= S_IFCHR; break; case NF3LNK: nfsdirent->mode |= S_IFLNK; break; case NF3SOCK: nfsdirent->mode |= S_IFSOCK; break; case NF3FIFO: nfsdirent->mode |= S_IFIFO; break; }; nfsdirent->size = attributes->size; nfsdirent->atime.tv_sec = attributes->atime.seconds; nfsdirent->atime.tv_usec = attributes->atime.nseconds/1000; nfsdirent->atime_nsec = attributes->atime.nseconds; nfsdirent->mtime.tv_sec = attributes->mtime.seconds; nfsdirent->mtime.tv_usec = attributes->mtime.nseconds/1000; nfsdirent->mtime_nsec = attributes->mtime.nseconds; nfsdirent->ctime.tv_sec = attributes->ctime.seconds; nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000; nfsdirent->ctime_nsec = attributes->ctime.nseconds; nfsdirent->uid = attributes->uid; nfsdirent->gid = attributes->gid; nfsdirent->nlink = attributes->nlink; nfsdirent->dev = attributes->fsid; nfsdirent->rdev = specdata3_to_rdev(&attributes->rdev); nfsdirent->blksize = NFS_BLKSIZE; nfsdirent->blocks = (attributes->used + 512 - 1) / 512; nfsdirent->used = attributes->used; } } if (rdpe_cb_data->getattrcount == 0) { if (rdpe_cb_data->status != RPC_STATUS_SUCCESS) { nfs_set_error(nfs, "READDIRPLUS emulation " "failed: %s", rpc_get_error(rpc)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); nfs_free_nfsdir(nfsdir); } else { data->cb(0, nfs, nfsdir, data->private_data); } free(rdpe_cb_data); data->continue_data = NULL; free_nfs_cb_data(data); } } static int lookup_missing_attributes(struct nfs_context *nfs, struct nfsdir *nfsdir, struct nfs_cb_data *data) { struct rdpe_cb_data *rdpe_cb_data = NULL; struct nfsdirent *nfsdirent; for (nfsdirent = nfsdir->entries; nfsdirent; nfsdirent = nfsdirent->next) { struct rdpe_lookup_cb_data *rdpe_lookup_cb_data; LOOKUP3args args; /* If type == 0 we assume it is a case of the server not * giving us the attributes for this entry during READIR[PLUS] * so we fallback to LOOKUP3 */ if (nfsdirent->type != 0) { continue; } if (rdpe_cb_data == NULL) { rdpe_cb_data = malloc(sizeof(struct rdpe_cb_data)); rdpe_cb_data->getattrcount = 0; rdpe_cb_data->status = RPC_STATUS_SUCCESS; rdpe_cb_data->data = data; } rdpe_lookup_cb_data = malloc(sizeof(struct rdpe_lookup_cb_data)); rdpe_lookup_cb_data->rdpe_cb_data = rdpe_cb_data; rdpe_lookup_cb_data->nfsdirent = nfsdirent; memset(&args, 0, sizeof(LOOKUP3args)); args.what.dir.data.data_len = data->fh.len; args.what.dir.data.data_val = data->fh.val; args.what.name = nfsdirent->name; if (rpc_nfs3_lookup_async(nfs->rpc, nfs3_opendir_3_cb, &args, rdpe_lookup_cb_data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send " "READDIR LOOKUP call"); /* if we have already commands in flight, we cant just * stop, we have to wait for the commands in flight to * complete */ continue; } rdpe_cb_data->getattrcount++; } if (rdpe_cb_data != NULL) { return rdpe_cb_data->getattrcount; } return 0; } static void nfs3_opendir_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { READDIR3res *res = command_data; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsdir *nfsdir = data->continue_data; struct nfsdirent *nfsdirent; struct entry3 *entry; uint64_t cookie = 0; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: READDIR of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } entry =res->READDIR3res_u.resok.reply.entries; while (entry != NULL) { nfsdirent = malloc(sizeof(struct nfsdirent)); if (nfsdirent == NULL) { data->cb(-ENOMEM, nfs, "Failed to allocate dirent", data->private_data); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } memset(nfsdirent, 0, sizeof(struct nfsdirent)); nfsdirent->name = strdup(entry->name); if (nfsdirent->name == NULL) { data->cb(-ENOMEM, nfs, "Failed to allocate " "dirent->name", data->private_data); free(nfsdirent); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } nfsdirent->inode = entry->fileid; nfsdirent->next = nfsdir->entries; nfsdir->entries = nfsdirent; cookie = entry->cookie; entry = entry->nextentry; } if (res->READDIR3res_u.resok.reply.eof == 0) { READDIR3args args; args.dir.data.data_len = data->fh.len; args.dir.data.data_val = data->fh.val; args.cookie = cookie; memcpy(&args.cookieverf, res->READDIR3res_u.resok.cookieverf, sizeof(cookieverf3)); args.count = 8192; if (rpc_nfs3_readdir_async(nfs->rpc, nfs3_opendir_2_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send " "READDIR call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } return; } if (res->READDIR3res_u.resok.dir_attributes.attributes_follow) fattr3_to_nfs_attr(&nfsdir->attr, &res->READDIR3res_u.resok.dir_attributes.post_op_attr_u.attributes); /* steal the dirhandle */ nfsdir->current = nfsdir->entries; if (lookup_missing_attributes(nfs, nfsdir, data) == 0) { data->cb(0, nfs, nfsdir, data->private_data); data->continue_data = NULL; free_nfs_cb_data(data); return; } } static void nfs3_opendir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { READDIRPLUS3res *res = command_data; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsdir *nfsdir = data->continue_data; struct entryplus3 *entry; uint64_t cookie = 0; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } if (status == RPC_STATUS_SUCCESS && res->status == NFS3ERR_NOTSUPP) { READDIR3args args; args.dir.data.data_len = data->fh.len; args.dir.data.data_val = data->fh.val; args.cookie = cookie; memset(&args.cookieverf, 0, sizeof(cookieverf3)); args.count = 8192; if (rpc_nfs3_readdir_async(nfs->rpc, nfs3_opendir_2_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send " "READDIR call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } return; } if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: READDIRPLUS of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } entry =res->READDIRPLUS3res_u.resok.reply.entries; while (entry != NULL) { struct nfsdirent *nfsdirent; struct nfs_attr attr; int has_attr = 0; memset(&attr, 0, sizeof(attr)); nfsdirent = malloc(sizeof(struct nfsdirent)); if (nfsdirent == NULL) { data->cb(-ENOMEM, nfs, "Failed to allocate dirent", data->private_data); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } memset(nfsdirent, 0, sizeof(struct nfsdirent)); nfsdirent->name = strdup(entry->name); if (nfsdirent->name == NULL) { data->cb(-ENOMEM, nfs, "Failed to allocate " "dirent->name", data->private_data); free(nfsdirent); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } nfsdirent->inode = entry->fileid; if (entry->name_attributes.attributes_follow) { fattr3_to_nfs_attr(&attr, &entry->name_attributes.post_op_attr_u.attributes); has_attr = 1; } if (!has_attr) { struct nested_mounts *mnt; int splen = strlen(data->saved_path); /* A single '/' is a special case, treat it as * zero-length below. */ if (splen == 1) splen = 0; /* No name attributes. Is it a nested mount then?*/ for(mnt = nfs->nested_mounts; mnt; mnt = mnt->next) { if (strncmp(data->saved_path, mnt->path, splen)) continue; if (mnt->path[splen] != '/') continue; if (strcmp(mnt->path + splen + 1, entry->name)) continue; attr = mnt->attr; has_attr = 1; break; } } if (has_attr) { struct specdata3 sd3 = { attr.rdev.specdata1, attr.rdev.specdata2 }; nfsdirent->type = attr.type; nfsdirent->mode = attr.mode; switch (nfsdirent->type) { case NF3REG: nfsdirent->mode |= S_IFREG; break; case NF3DIR: nfsdirent->mode |= S_IFDIR; break; case NF3BLK: nfsdirent->mode |= S_IFBLK; break; case NF3CHR: nfsdirent->mode |= S_IFCHR; break; case NF3LNK: nfsdirent->mode |= S_IFLNK; break; case NF3SOCK: nfsdirent->mode |= S_IFSOCK; break; case NF3FIFO: nfsdirent->mode |= S_IFIFO; break; }; nfsdirent->size = attr.size; nfsdirent->atime.tv_sec = attr.atime.seconds; nfsdirent->atime.tv_usec = attr.atime.nseconds/1000; nfsdirent->atime_nsec = attr.atime.nseconds; nfsdirent->mtime.tv_sec = attr.mtime.seconds; nfsdirent->mtime.tv_usec = attr.mtime.nseconds/1000; nfsdirent->mtime_nsec = attr.mtime.nseconds; nfsdirent->ctime.tv_sec = attr.ctime.seconds; nfsdirent->ctime.tv_usec = attr.ctime.nseconds/1000; nfsdirent->ctime_nsec = attr.ctime.nseconds; nfsdirent->uid = attr.uid; nfsdirent->gid = attr.gid; nfsdirent->nlink = attr.nlink; nfsdirent->dev = attr.fsid; nfsdirent->rdev = specdata3_to_rdev(&sd3); nfsdirent->blksize = NFS_BLKSIZE; nfsdirent->blocks = (attr.used + 512 - 1) / 512; nfsdirent->used = attr.used; } nfsdirent->next = nfsdir->entries; nfsdir->entries = nfsdirent; cookie = entry->cookie; entry = entry->nextentry; } if (res->READDIRPLUS3res_u.resok.reply.eof == 0) { READDIRPLUS3args args; args.dir.data.data_len = data->fh.len; args.dir.data.data_val = data->fh.val; args.cookie = cookie; memcpy(&args.cookieverf, res->READDIRPLUS3res_u.resok.cookieverf, sizeof(cookieverf3)); args.dircount = 8192; args.maxcount = 8192; if (rpc_nfs3_readdirplus_async(nfs->rpc, nfs3_opendir_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send " "READDIRPLUS call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); return; } return; } if (res->READDIRPLUS3res_u.resok.dir_attributes.attributes_follow) { fattr3_to_nfs_attr(&nfsdir->attr, &res->READDIRPLUS3res_u.resok.dir_attributes.post_op_attr_u.attributes); } /* steal the dirhandle */ nfsdir->current = nfsdir->entries; if (lookup_missing_attributes(nfs, nfsdir, data) == 0) { data->cb(0, nfs, nfsdir, data->private_data); /* We can not free data->continue_data here */ data->continue_data = NULL; free_nfs_cb_data(data); return; } } static int nfs3_opendir_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr, struct nfs_cb_data *data) { READDIRPLUS3args args; struct nfsdir *nfsdir = data->continue_data; struct nfsdir *cached; cached = nfs_dircache_find(nfs, &data->fh); if (cached) { if (attr && attr->mtime.seconds == cached->attr.mtime.seconds && attr->mtime.nseconds == cached->attr.mtime.nseconds) { cached->current = cached->entries; data->cb(0, nfs, cached, data->private_data); free_nfs_cb_data(data); return 0; } else { /* cache must be stale */ nfs_free_nfsdir(cached); } } nfsdir->fh.len = data->fh.len; nfsdir->fh.val = malloc(nfsdir->fh.len); if (nfsdir->fh.val == NULL) { nfs_set_error(nfs, "OOM when allocating fh for nfsdir"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } memcpy(nfsdir->fh.val, data->fh.val, data->fh.len); args.dir.data.data_len = data->fh.len; args.dir.data.data_val = data->fh.val; args.cookie = 0; memset(&args.cookieverf, 0, sizeof(cookieverf3)); args.dircount = 8192; args.maxcount = 8192; if (rpc_nfs3_readdirplus_async(nfs->rpc, nfs3_opendir_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send " "READDIRPLUS call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { struct nfsdir *nfsdir; nfsdir = malloc(sizeof(struct nfsdir)); if (nfsdir == NULL) { nfs_set_error(nfs, "failed to allocate buffer for nfsdir"); return -1; } memset(nfsdir, 0, sizeof(struct nfsdir)); if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_opendir_continue_internal, nfsdir, free, 0) != 0) { return -1; } return 0; } struct mknod_cb_data { char *path; int mode; int major; int minor; }; static void free_mknod_cb_data(void *ptr) { struct mknod_cb_data *data = ptr; free(data->path); free(data); } static void nfs3_mknod_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { MKNOD3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); str = &str[strlen(str) + 1]; if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: MKNOD of %s/%s failed with " "%s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_mknod_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct mknod_cb_data *cb_data = data->continue_data; char *str = cb_data->path; MKNOD3args args; memset(&args, 0, sizeof(args)); str = &str[strlen(str) + 1]; args.where.dir.data.data_len = data->fh.len; args.where.dir.data.data_val = data->fh.val; args.where.name = str; switch (cb_data->mode & S_IFMT) { case S_IFCHR: args.what.type = NF3CHR; args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_it = 1; args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); args.what.mknoddata3_u.chr_device.spec.specdata1 = cb_data->major; args.what.mknoddata3_u.chr_device.spec.specdata2 = cb_data->minor; break; case S_IFBLK: args.what.type = NF3BLK; args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_it = 1; args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); args.what.mknoddata3_u.blk_device.spec.specdata1 = cb_data->major; args.what.mknoddata3_u.blk_device.spec.specdata2 = cb_data->minor; break; case S_IFSOCK: args.what.type = NF3SOCK; args.what.mknoddata3_u.sock_attributes.mode.set_it = 1; args.what.mknoddata3_u.sock_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); break; case S_IFIFO: args.what.type = NF3FIFO; args.what.mknoddata3_u.pipe_attributes.mode.set_it = 1; args.what.mknoddata3_u.pipe_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); break; default: nfs_set_error(nfs, "Invalid file type for " "NFS3/MKNOD call"); data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } if (rpc_nfs3_mknod_async(nfs->rpc, nfs3_mknod_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev, nfs_cb cb, void *private_data) { char *ptr; struct mknod_cb_data *cb_data; cb_data = malloc(sizeof(struct mknod_cb_data)); if (cb_data == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "mode buffer for cb data"); return -1; } ptr = strrchr(path, '/'); if (ptr) { cb_data->path = strdup(path); if (cb_data->path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for mknod path"); return -1; } ptr = strrchr(cb_data->path, '/'); *ptr = 0; } else { cb_data->path = malloc(strlen(path) + 2); if (cb_data->path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for mknod path"); return -1; } sprintf(cb_data->path, "%c%s", '\0', path); } cb_data->mode = mode; cb_data->major = major(dev); cb_data->minor = minor(dev); /* data->path now points to the parent directory and beyond the * null terminator is the new node to create */ if (nfs3_lookuppath_async(nfs, cb_data->path, 0, cb, private_data, nfs3_mknod_continue_internal, cb_data, free_mknod_cb_data, 0) != 0) { return -1; } return 0; } static void nfs3_unlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { REMOVE3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); str = &str[strlen(str) + 1]; if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: REMOVE of %s/%s failed with " "%s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_unlink_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { char *str = data->continue_data; struct REMOVE3args args; str = &str[strlen(str) + 1]; args.object.dir.data.data_len = data->fh.len; args.object.dir.data.data_val = data->fh.val; args.object.name = str; if (rpc_nfs3_remove_async(nfs->rpc, nfs3_unlink_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send REMOVE " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { char *new_path; char *ptr; ptr = strrchr(path, '/'); if (ptr) { new_path = strdup(path); if (new_path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for unlink path"); return -1; } ptr = strrchr(new_path, '/'); *ptr = 0; } else { new_path = malloc(strlen(path) + 2); if (new_path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for unlink path"); return -1; } sprintf(new_path, "%c%s", '\0', path); } /* new_path now points to the parent directory and beyond the * null terminator is the object to unlink */ if (nfs3_lookuppath_async(nfs, new_path, 0, cb, private_data, nfs3_unlink_continue_internal, new_path, free, 0) != 0) { return -1; } return 0; } struct create_cb_data { char *path; int flags; int mode; }; static void free_create_cb_data(void *ptr) { struct create_cb_data *data = ptr; free(data->path); free(data); } static void nfs3_create_trunc_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *nfsfh = data->nfsfh; SETATTR3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); nfs_free_nfsfh(nfsfh); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); nfs_free_nfsfh(nfsfh); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, nfsfh, data->private_data); free_nfs_cb_data(data); } static void nfs3_create_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { LOOKUP3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *nfsfh; struct create_cb_data *cb_data = data->continue_data; char *str = cb_data->path; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } str = &str[strlen(str) + 1]; res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: CREATE of %s/%s failed with " "%s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfsfh = malloc(sizeof(struct nfsfh)); if (nfsfh == NULL) { nfs_set_error(nfs, "NFS: Failed to allocate nfsfh structure"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } memset(nfsfh, 0, sizeof(struct nfsfh)); if (cb_data->flags & O_SYNC) { nfsfh->is_sync = 1; } if (cb_data->flags & O_APPEND) { nfsfh->is_append = 1; } /* copy the filehandle */ nfsfh->fh.len = res->LOOKUP3res_u.resok.object.data.data_len; nfsfh->fh.val = malloc(nfsfh->fh.len); if (nfsfh->fh.val == NULL) { nfs_set_error(nfs, "Out of memory: Failed to allocate " "fh structure"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); free(nfsfh); return; } memcpy(nfsfh->fh.val, res->LOOKUP3res_u.resok.object.data.data_val, nfsfh->fh.len); /* Try to truncate it if we were requested to */ if (cb_data->flags & O_TRUNC) { SETATTR3args args; data->nfsfh = nfsfh; memset(&args, 0, sizeof(SETATTR3args)); args.object.data.data_len = nfsfh->fh.len; args.object.data.data_val = nfsfh->fh.val; args.new_attributes.size.set_it = 1; args.new_attributes.size.set_size3_u.size = 0; if (rpc_nfs3_setattr_async(nfs->rpc, nfs3_create_trunc_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send " "SETATTR call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); nfs_free_nfsfh(nfsfh); return; } return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, nfsfh, data->private_data); free_nfs_cb_data(data); } static void nfs3_create_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { CREATE3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct create_cb_data *cb_data = data->continue_data; char *str = cb_data->path; LOOKUP3args args; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } str = &str[strlen(str) + 1]; res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: CREATE of %s/%s failed with " "%s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } memset(&args, 0, sizeof(LOOKUP3args)); args.what.dir.data.data_len = data->fh.len; args.what.dir.data.data_val = data->fh.val; args.what.name = str; if (rpc_nfs3_lookup_async(nfs->rpc, nfs3_create_2_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send lookup " "call for %s/%s", data->saved_path, str); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } return; } static int nfs3_create_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct create_cb_data *cb_data = data->continue_data; char *str = cb_data->path; CREATE3args args; str = &str[strlen(str) + 1]; memset(&args, 0, sizeof(CREATE3args)); args.where.dir.data.data_len = data->fh.len; args.where.dir.data.data_val = data->fh.val; args.where.name = str; args.how.mode = (cb_data->flags & O_EXCL) ? GUARDED : UNCHECKED; args.how.createhow3_u.obj_attributes.mode.set_it = 1; args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = cb_data->mode; if (rpc_nfs3_create_async(nfs->rpc, nfs3_create_1_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send CREATE " "call for %s/%s", data->path, str); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_create_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data) { struct create_cb_data *cb_data; char *ptr; cb_data = malloc(sizeof(struct create_cb_data)); if (cb_data == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "mode buffer for cb data"); return -1; } ptr = strrchr(path, '/'); if (ptr) { cb_data->path = strdup(path); if (cb_data->path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for creat path"); return -1; } ptr = strrchr(cb_data->path, '/'); *ptr = 0; } else { cb_data->path = malloc(strlen(path) + 2); if (cb_data->path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for creat path"); return -1; } sprintf(cb_data->path, "%c%s", '\0', path); } cb_data->flags = flags; cb_data->mode = mode; /* new_path now points to the parent directory and beyond the * null terminator is the new object to create */ if (nfs3_lookuppath_async(nfs, cb_data->path, 0, cb, private_data, nfs3_create_continue_internal, cb_data, free_create_cb_data, 0) != 0) { return -1; } return 0; } static void nfs3_rmdir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { RMDIR3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); str = &str[strlen(str) + 1]; if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: RMDIR of %s/%s failed with " "%s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { char *str = data->continue_data; RMDIR3args args; str = &str[strlen(str) + 1]; args.object.dir.data.data_len = data->fh.len; args.object.dir.data.data_val = data->fh.val; args.object.name = str; if (rpc_nfs3_rmdir_async(nfs->rpc, nfs3_rmdir_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send RMDIR " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { char *new_path; char *ptr; ptr = strrchr(path, '/'); if (ptr) { new_path = strdup(path); if (new_path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for rmdir path"); return -1; } ptr = strrchr(new_path, '/'); *ptr = 0; } else { new_path = malloc(strlen(path) + 2); if (new_path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for rmdir path"); return -1; } sprintf(new_path, "%c%s", '\0', path); } /* new_path now points to the parent directory and beyond the * null terminator is the directory to remove */ if (nfs3_lookuppath_async(nfs, new_path, 0, cb, private_data, nfs3_rmdir_continue_internal, new_path, free, 0) != 0) { return -1; } return 0; } static void nfs3_mkdir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { MKDIR3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); str = &str[strlen(str) + 1]; if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: MKDIR of %s/%s failed " "with %s(%d)", data->saved_path, str, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } static int nfs3_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { char *str = data->continue_data; int mode = (int)data->continue_int; MKDIR3args args; str = &str[strlen(str) + 1]; memset(&args, 0, sizeof(MKDIR3args)); args.where.dir.data.data_len = data->fh.len; args.where.dir.data.data_val = data->fh.val; args.where.name = str; args.attributes.mode.set_it = 1; args.attributes.mode.set_mode3_u.mode = mode; if (rpc_nfs3_mkdir_async(nfs->rpc, nfs3_mkdir_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send MKDIR " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_mkdir2_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { char *new_path; char *ptr; ptr = strrchr(path, '/'); if (ptr) { new_path = strdup(path); if (new_path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for mkdir path"); return -1; } ptr = strrchr(new_path, '/'); *ptr = 0; } else { new_path = malloc(strlen(path) + 2); if (new_path == NULL) { nfs_set_error(nfs, "Out of memory, failed to allocate " "buffer for mkdir path"); return -1; } sprintf(new_path, "%c%s", '\0', path); } /* new_path now points to the parent directory and beyond the * null terminator is the new directory to create */ if (nfs3_lookuppath_async(nfs, new_path, 0, cb, private_data, nfs3_mkdir_continue_internal, new_path, free, mode) != 0) { return -1; } return 0; } static int nfs3_truncate_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { uint64_t offset = data->continue_int; struct nfsfh nfsfh; memset(&nfsfh, 0, sizeof(struct nfsfh)); nfsfh.fh = data->fh; if (nfs_ftruncate_async(nfs, &nfsfh, offset, data->cb, data->private_data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send SETATTR " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } free_nfs_cb_data(data); return 0; } int nfs3_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data) { uint64_t offset; offset = length; if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_truncate_continue_internal, NULL, NULL, offset) != 0) { return -1; } return 0; } static void nfs3_ftruncate_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; SETATTR3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfs_dircache_drop(nfs, &data->fh); data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } int nfs3_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; SETATTR3args args; nfs_pagecache_invalidate(nfs, nfsfh); data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " "nfs_cb_data structure"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; memset(&args, 0, sizeof(SETATTR3args)); args.object.data.data_len = nfsfh->fh.len; args.object.data.data_val = nfsfh->fh.val; args.new_attributes.size.set_it = 1; args.new_attributes.size.set_size3_u.size = length; if (rpc_nfs3_setattr_async(nfs->rpc, nfs3_ftruncate_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send SETATTR " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } static void nfs3_fsync_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMMIT3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: Commit failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); } int nfs3_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; struct COMMIT3args args; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " "nfs_cb_data structure"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; args.file.data.data_len = nfsfh->fh.len; args.file.data.data_val = nfsfh->fh.val; args.offset = 0; args.count = 0; if (rpc_nfs3_commit_async(nfs->rpc, nfs3_fsync_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send COMMIT " "call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } static void nfs3_stat_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { GETATTR3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; #ifdef WIN32 struct __stat64 st; #else struct stat st; #endif assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: GETATTR of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } st.st_dev = (dev_t)res->GETATTR3res_u.resok.obj_attributes.fsid; st.st_ino = (ino_t)res->GETATTR3res_u.resok.obj_attributes.fileid; st.st_mode = res->GETATTR3res_u.resok.obj_attributes.mode; switch (res->GETATTR3res_u.resok.obj_attributes.type) { case NF3REG: st.st_mode |= S_IFREG; break; case NF3DIR: st.st_mode |= S_IFDIR; break; case NF3BLK: st.st_mode |= S_IFBLK; break; case NF3CHR: st.st_mode |= S_IFCHR; break; case NF3LNK: st.st_mode |= S_IFLNK; break; case NF3SOCK: st.st_mode |= S_IFSOCK; break; case NF3FIFO: st.st_mode |= S_IFIFO; break; } st.st_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink; st.st_uid = res->GETATTR3res_u.resok.obj_attributes.uid; st.st_gid = res->GETATTR3res_u.resok.obj_attributes.gid; st.st_rdev = specdata3_to_rdev(&res->GETATTR3res_u.resok.obj_attributes.rdev); st.st_size = res->GETATTR3res_u.resok.obj_attributes.size; #ifndef WIN32 st.st_blksize = NFS_BLKSIZE; st.st_blocks = (res->GETATTR3res_u.resok.obj_attributes.used + 512 - 1) / 512; #endif//WIN32 st.st_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds; st.st_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds; st.st_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds; #ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC st.st_atim.tv_nsec = res->GETATTR3res_u.resok.obj_attributes.atime.nseconds; st.st_mtim.tv_nsec = res->GETATTR3res_u.resok.obj_attributes.mtime.nseconds; st.st_ctim.tv_nsec = res->GETATTR3res_u.resok.obj_attributes.ctime.nseconds; #endif data->cb(0, nfs, &st, data->private_data); free_nfs_cb_data(data); } int nfs3_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; struct GETATTR3args args; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " "nfs_cb_data structure"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = nfsfh->fh.len; args.object.data.data_val = nfsfh->fh.val; if (rpc_nfs3_getattr_async(nfs->rpc, nfs3_stat_1_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } static void nfs3_stat64_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { GETATTR3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfs_stat_64 st; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: GETATTR of %s failed with " "%s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } st.nfs_dev = res->GETATTR3res_u.resok.obj_attributes.fsid; st.nfs_ino = res->GETATTR3res_u.resok.obj_attributes.fileid; st.nfs_mode = res->GETATTR3res_u.resok.obj_attributes.mode; switch (res->GETATTR3res_u.resok.obj_attributes.type) { case NF3REG: st.nfs_mode |= S_IFREG; break; case NF3DIR: st.nfs_mode |= S_IFDIR; break; case NF3BLK: st.nfs_mode |= S_IFBLK; break; case NF3CHR: st.nfs_mode |= S_IFCHR; break; case NF3LNK: st.nfs_mode |= S_IFLNK; break; case NF3SOCK: st.nfs_mode |= S_IFSOCK; break; case NF3FIFO: st.nfs_mode |= S_IFIFO; break; } st.nfs_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink; st.nfs_uid = res->GETATTR3res_u.resok.obj_attributes.uid; st.nfs_gid = res->GETATTR3res_u.resok.obj_attributes.gid; st.nfs_rdev = specdata3_to_rdev(&res->GETATTR3res_u.resok.obj_attributes.rdev); st.nfs_size = res->GETATTR3res_u.resok.obj_attributes.size; st.nfs_blksize = NFS_BLKSIZE; st.nfs_blocks = (res->GETATTR3res_u.resok.obj_attributes.used + 512 - 1) / 512; st.nfs_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds; st.nfs_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds; st.nfs_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds; st.nfs_atime_nsec = res->GETATTR3res_u.resok.obj_attributes.atime.nseconds; st.nfs_mtime_nsec = res->GETATTR3res_u.resok.obj_attributes.mtime.nseconds; st.nfs_ctime_nsec = res->GETATTR3res_u.resok.obj_attributes.ctime.nseconds; st.nfs_used = res->GETATTR3res_u.resok.obj_attributes.used; data->cb(0, nfs, &st, data->private_data); free_nfs_cb_data(data); } static int nfs3_stat64_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct GETATTR3args args; memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; if (rpc_nfs3_getattr_async(nfs->rpc, nfs3_stat64_1_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_stat64_async(struct nfs_context *nfs, const char *path, int no_follow, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, no_follow, cb, private_data, nfs3_stat64_continue_internal, NULL, NULL, 0) != 0) { return -1; } return 0; } int nfs3_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; struct GETATTR3args args; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " "nfs_cb_data structure"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = nfsfh->fh.len; args.object.data.data_val = nfsfh->fh.val; if (rpc_nfs3_getattr_async(nfs->rpc, nfs3_stat64_1_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } static int nfs3_stat_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { struct GETATTR3args args; memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; if (rpc_nfs3_getattr_async(nfs->rpc, nfs3_stat_1_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } int nfs3_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_stat_continue_internal, NULL, NULL, 0) != 0) { return -1; } return 0; } static void nfs3_close_cb(int err, struct nfs_context *nfs, void *ret_data, void *private_data) { struct nfs_cb_data *data = private_data; nfs_free_nfsfh(data->nfsfh); data->cb(err, nfs, ret_data, data->private_data); free_nfs_cb_data(data); } int nfs3_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; if (!nfsfh->is_dirty) { nfs_free_nfsfh(nfsfh); cb(0, nfs, NULL, private_data); return 0; } data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " "nfs_cb_data structure"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfsfh = nfsfh; data->cb = cb; data->private_data = private_data; return nfs_fsync_async(nfs, nfsfh, nfs3_close_cb, data); } static void nfs3_write_append_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; GETATTR3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: GETATTR failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } if (nfs3_pwrite_async_internal(nfs, data->nfsfh, res->GETATTR3res_u.resok.obj_attributes.size, data->count, data->usrbuf, data->cb, data->private_data, 1) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } free_nfs_cb_data(data); } static void nfs3_fill_WRITE3args (WRITE3args *args, struct nfsfh *fh, uint64_t offset, uint64_t count, const void *buf) { memset(args, 0, sizeof(WRITE3args)); args->file.data.data_len = fh->fh.len; args->file.data.data_val = fh->fh.val; args->offset = offset; args->count = (count3)count; args->stable = fh->is_sync ? FILE_SYNC : UNSTABLE; args->data.data_len = (count3)count; args->data.data_val = (char *)buf; } static void nfs3_pwrite_mcb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_mcb_data *mdata = private_data; struct nfs_cb_data *data = mdata->data; struct nfs_context *nfs = data->nfs; WRITE3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); data->num_calls--; /* Flag the failure but do not invoke callback until we have * received all responses. */ if (status == RPC_STATUS_ERROR) { data->error = 1; } if (status == RPC_STATUS_CANCEL) { data->cancel = 1; } if (status == RPC_STATUS_TIMEOUT) { data->cancel = 1; } if (status == RPC_STATUS_SUCCESS) { res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->error = 1; } else { size_t count = res->WRITE3res_u.resok.count; if (count < mdata->count) { if (count == 0) { nfs_set_error(nfs, "NFS: Write failed. No bytes written!"); data->error = 1; } else { /* reissue reminder of this write request */ WRITE3args args; mdata->offset += count; mdata->count -= count; nfs3_fill_WRITE3args(&args, data->nfsfh, mdata->offset, mdata->count, &data->usrbuf[mdata->offset - data->offset]); if (rpc_nfs3_write_async(nfs->rpc, nfs3_pwrite_mcb, &args, mdata) == 0) { data->num_calls++; return; } else { nfs_set_error(nfs, "RPC error: Failed to send WRITE call for %s", data->path); data->oom = 1; } } } if (count > 0) { if (data->max_offset < mdata->offset + count) { data->max_offset = mdata->offset + count; } } } } free(mdata); if (data->num_calls > 0) { /* still waiting for more replies */ return; } if (data->oom != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; } if (data->error != 0) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; } if (data->cancel != 0) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); free_nfs_cb_data(data); return; } if (data->update_pos) { data->nfsfh->offset = data->max_offset; } nfs_pagecache_put(&data->nfsfh->pagecache, data->offset, data->usrbuf, data->count); data->cb((int)(data->max_offset - data->offset), nfs, NULL, data->private_data); free_nfs_cb_data(data); } int nfs3_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, size_t count, const char *buf, nfs_cb cb, void *private_data, int update_pos) { struct nfs_cb_data *data; nfsfh->is_dirty = 1; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " "nfs_cb_data structure"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->nfsfh = nfsfh; data->usrbuf = buf; data->update_pos = update_pos; /* hello, clang-analyzer */ assert(data->num_calls == 0); /* chop requests into chunks of at most WRITEMAX bytes if necessary. * we send all writes in parallel so that performance is still good. */ data->max_offset = offset; data->offset = offset; data->count = count; do { size_t writecount = count; struct nfs_mcb_data *mdata; WRITE3args args; if (writecount > nfs_get_writemax(nfs)) { writecount = (size_t)nfs_get_writemax(nfs); } mdata = malloc(sizeof(struct nfs_mcb_data)); if (mdata == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " "nfs_mcb_data structure"); if (data->num_calls == 0) { free_nfs_cb_data(data); return -1; } data->oom = 1; break; } memset(mdata, 0, sizeof(struct nfs_mcb_data)); mdata->data = data; mdata->offset = offset; mdata->count = writecount; nfs3_fill_WRITE3args(&args, nfsfh, offset, writecount, &buf[offset - data->offset]); if (rpc_nfs3_write_async(nfs->rpc, nfs3_pwrite_mcb, &args, mdata) != 0) { nfs_set_error(nfs, "RPC error: Failed to send WRITE " "call for %s", data->path); free(mdata); if (data->num_calls == 0) { free_nfs_cb_data(data); return -1; } data->oom = 1; break; } count -= writecount; offset += writecount; data->num_calls++; } while (count > 0); return 0; } int nfs3_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, const void *buf, nfs_cb cb, void *private_data) { if (nfsfh->is_append) { struct GETATTR3args args; struct nfs_cb_data *data; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->nfsfh = nfsfh; data->usrbuf = buf; data->count = (size_t)count; memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = nfsfh->fh.len; args.object.data.data_val = nfsfh->fh.val; if (rpc_nfs3_getattr_async(nfs->rpc, nfs3_write_append_cb, &args, data) != 0) { free_nfs_cb_data(data); return -1; } return 0; } return nfs3_pwrite_async_internal(nfs, nfsfh, nfsfh->offset, (size_t)count, buf, cb, private_data, 1); } static void nfs3_fill_READ3args(READ3args *args, struct nfsfh *fh, uint64_t offset, uint64_t count) { memset(args, 0, sizeof(READ3args)); args->file.data.data_len = fh->fh.len; args->file.data.data_val = fh->fh.val; args->offset = offset; args->count = (count3)count; } static void nfs3_pread_mcb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_mcb_data *mdata = private_data; struct nfs_cb_data *data = mdata->data; struct nfs_context *nfs = data->nfs; READ3res *res; int cb_err; void *cb_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); data->num_calls--; /* Flag the failure but do not invoke callback until we have * received all responses. */ if (status == RPC_STATUS_ERROR) { data->error = 1; } if (status == RPC_STATUS_CANCEL) { data->cancel = 1; } if (status == RPC_STATUS_TIMEOUT) { data->cancel = 1; } if (status == RPC_STATUS_SUCCESS) { res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->error = 1; } else { size_t count = res->READ3res_u.resok.count; if (count < data->count && data->buffer == NULL) { /* we need a reassembly buffer after all */ data->buffer = malloc(mdata->count); if (data->buffer == NULL) { data->oom = 1; goto out; } } if (count > 0) { if (count == data->count && data->buffer == NULL) { data->buffer = res->READ3res_u.resok.data.data_val; data->not_my_buffer = 1; } else if (count <= mdata->count) { /* copy data into reassembly buffer */ memcpy(&data->buffer[mdata->offset - data->offset], res->READ3res_u.resok.data.data_val, count); } else { nfs_set_error(nfs, "NFS: Read overflow. Server has sent more data than requested!"); data->error = 1; goto out; } if (data->max_offset < mdata->offset + count) { data->max_offset = mdata->offset + count; } } /* check if we have received a short read */ if (count < mdata->count && !res->READ3res_u.resok.eof) { if (count == 0) { nfs_set_error(nfs, "NFS: Read failed. No bytes read and not at EOF!"); data->error = 1; } else { /* reissue reminder of this read request */ READ3args args; mdata->offset += count; mdata->count -= count; nfs3_fill_READ3args(&args, data->nfsfh, mdata->offset, mdata->count); if (rpc_nfs3_read_async(nfs->rpc, nfs3_pread_mcb, &args, mdata) == 0) { data->num_calls++; return; } else { nfs_set_error(nfs, "RPC error: Failed to send READ call for %s", data->path); data->oom = 1; } } } } } out: free(mdata); if (data->num_calls > 0) { /* still waiting for more replies */ return; } if (data->oom != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; } if (data->error != 0) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; } if (data->cancel != 0) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); free_nfs_cb_data(data); return; } data->nfsfh->ra.fh_offset = data->max_offset; nfs_pagecache_put(&data->nfsfh->pagecache, data->offset, data->buffer, (size_t)(data->max_offset - data->offset)); if (data->max_offset > data->org_offset + data->org_count) { data->max_offset = data->org_offset + data->org_count; } if (data->update_pos) { data->nfsfh->offset = data->max_offset; } cb_err = (int)(data->max_offset - data->org_offset); cb_data = data->buffer + (data->org_offset - data->offset); data->cb(cb_err, nfs, cb_data, data->private_data); free_nfs_cb_data(data); return; } int nfs3_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, size_t count, nfs_cb cb, void *private_data, int update_pos) { struct nfs_cb_data *data; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " "nfs_cb_data structure"); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->nfsfh = nfsfh; data->org_offset = offset; data->org_count = (count3)count; data->update_pos = update_pos; assert(data->num_calls == 0); if (nfsfh->pagecache.num_entries) { /* align start offset to blocksize */ count += offset & (NFS_BLKSIZE - 1); offset &= ~(NFS_BLKSIZE - 1); /* align end offset to blocksize */ count += NFS_BLKSIZE - 1 ; count &= ~(NFS_BLKSIZE - 1); } data->offset = offset; data->count = (count3)count; if (nfsfh->pagecache.num_entries) { while (count > 0) { char *cdata = nfs_pagecache_get(&nfsfh->pagecache, offset); if (!cdata) { break; } /* we copy data from the pagecache so we need a * reassembly buffer */ if (data->buffer == NULL) { data->buffer = malloc(data->count); if (data->buffer == NULL) { free_nfs_cb_data(data); return -ENOMEM; } } memcpy(data->buffer + offset - data->offset, cdata, NFS_BLKSIZE); offset += NFS_BLKSIZE; count -= NFS_BLKSIZE; } if (!count) { data->nfsfh->ra.fh_offset = data->offset + data->count; if (update_pos) { data->nfsfh->offset = data->org_offset + data->org_count; } data->cb(data->org_count, nfs, data->buffer + (data->org_offset - data->offset), data->private_data); free_nfs_cb_data(data); return 0; } } if (nfs->rpc->readahead) { nfsfh->ra.cur_ra = MAX(NFS_BLKSIZE, nfsfh->ra.cur_ra); if (offset >= nfsfh->ra.fh_offset && offset <= nfsfh->ra.fh_offset + nfsfh->ra.cur_ra + NFS_BLKSIZE) { if (nfs->rpc->readahead > nfsfh->ra.cur_ra) { nfsfh->ra.cur_ra <<= 1; } } else { nfsfh->ra.cur_ra = 0; } count += nfsfh->ra.cur_ra; data->count += nfsfh->ra.cur_ra; } if ((data->count > nfs_get_readmax(nfs) || data->count > data->org_count) && (data->buffer == NULL || nfsfh->ra.cur_ra > 0)) { /* we do readahead, a big read or aligned out the request so we * need a (bigger) reassembly buffer */ data->buffer = realloc(data->buffer, data->count + nfsfh->ra.cur_ra); if (data->buffer == NULL) { free_nfs_cb_data(data); return -ENOMEM; } } data->max_offset = data->offset; /* chop requests into chunks of at most READMAX bytes if necessary. * we send all reads in parallel so that performance is still good. */ do { size_t readcount = count; struct nfs_mcb_data *mdata; READ3args args; if (readcount > nfs_get_readmax(nfs)) { readcount = (size_t)nfs_get_readmax(nfs); } mdata = malloc(sizeof(struct nfs_mcb_data)); if (mdata == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate nfs_mcb_data structure"); if (data->num_calls == 0) { free_nfs_cb_data(data); return -1; } data->oom = 1; break; } memset(mdata, 0, sizeof(struct nfs_mcb_data)); mdata->data = data; mdata->offset = offset; mdata->count = readcount; nfs3_fill_READ3args(&args, nfsfh, offset, readcount); if (rpc_nfs3_read_async(nfs->rpc, nfs3_pread_mcb, &args, mdata) != 0) { nfs_set_error(nfs, "RPC error: Failed to send READ " "call for %s", data->path); free(mdata); if (data->num_calls == 0) { free_nfs_cb_data(data); return -1; } data->oom = 1; break; } count -= readcount; offset += readcount; data->num_calls++; } while (count > 0); return 0; } static int nfs3_chdir_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { /* steal saved_path */ free(nfs->cwd); nfs->cwd = data->saved_path; data->saved_path = NULL; data->cb(0, nfs, NULL, data->private_data); free_nfs_cb_data(data); return 0; } int nfs3_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_chdir_continue_internal, NULL, NULL, 0) != 0) { return -1; } return 0; } static void nfs3_open_trunc_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *nfsfh; SETATTR3res *res; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } nfsfh = malloc(sizeof(struct nfsfh)); if (nfsfh == NULL) { nfs_set_error(nfs, "NFS: Failed to allocate nfsfh " "structure"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } memset(nfsfh, 0, sizeof(struct nfsfh)); if (data->continue_int & O_SYNC) { nfsfh->is_sync = 1; } if (data->continue_int & O_APPEND) { nfsfh->is_append = 1; } /* steal the filehandle */ nfsfh->fh = data->fh; data->fh.val = NULL; data->cb(0, nfs, nfsfh, data->private_data); free_nfs_cb_data(data); } static void nfs3_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { ACCESS3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *nfsfh; unsigned int nfsmode = 0; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs3_error(nfs, status, data, command_data)) { free_nfs_cb_data(data); return; } res = command_data; if (res->status != NFS3_OK) { nfs_set_error(nfs, "NFS: ACCESS of %s failed with %s(%d)", data->saved_path, nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } if (data->continue_int & O_WRONLY) { nfsmode |= ACCESS3_MODIFY; } if (data->continue_int & O_RDWR) { nfsmode |= ACCESS3_READ|ACCESS3_MODIFY; } if (!(data->continue_int & (O_WRONLY|O_RDWR))) { nfsmode |= ACCESS3_READ; } if (res->ACCESS3res_u.resok.access != nfsmode) { nfs_set_error(nfs, "NFS: ACCESS denied. Required " "access %c%c%c. Allowed access %c%c%c", nfsmode&ACCESS3_READ?'r':'-', nfsmode&ACCESS3_MODIFY?'w':'-', nfsmode&ACCESS3_EXECUTE?'x':'-', res->ACCESS3res_u.resok.access&ACCESS3_READ ? 'r':'-', res->ACCESS3res_u.resok.access&ACCESS3_MODIFY ?'w':'-', res->ACCESS3res_u.resok.access&ACCESS3_EXECUTE ?'x':'-'); data->cb(-EACCES, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } /* Try to truncate it if we were requested to */ if ((data->continue_int & O_TRUNC) && (data->continue_int & (O_RDWR|O_WRONLY))) { SETATTR3args args; memset(&args, 0, sizeof(SETATTR3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; args.new_attributes.size.set_it = 1; args.new_attributes.size.set_size3_u.size = 0; if (rpc_nfs3_setattr_async(nfs->rpc, nfs3_open_trunc_cb, &args, data) != 0) { nfs_set_error(nfs, "RPC error: Failed to send " "SETATTR call for %s", data->path); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } return; } nfsfh = malloc(sizeof(struct nfsfh)); if (nfsfh == NULL) { nfs_set_error(nfs, "NFS: Failed to allocate nfsfh structure"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return; } memset(nfsfh, 0, sizeof(struct nfsfh)); if (data->continue_int & O_SYNC) { nfsfh->is_sync = 1; } if (data->continue_int & O_APPEND) { nfsfh->is_append = 1; } /* init the pagecache */ nfs_pagecache_init(nfs, nfsfh); /* steal the filehandle */ nfsfh->fh = data->fh; data->fh.val = NULL; data->cb(0, nfs, nfsfh, data->private_data); free_nfs_cb_data(data); } static int nfs3_open_continue_internal(struct nfs_context *nfs, struct nfs_attr *attr _U_, struct nfs_cb_data *data) { int nfsmode = 0; ACCESS3args args; if (data->continue_int & O_WRONLY) { nfsmode |= ACCESS3_MODIFY; } if (data->continue_int & O_RDWR) { nfsmode |= ACCESS3_READ|ACCESS3_MODIFY; } if (!(data->continue_int & (O_WRONLY|O_RDWR))) { nfsmode |= ACCESS3_READ; } memset(&args, 0, sizeof(ACCESS3args)); args.object.data.data_len = data->fh.len; args.object.data.data_val = data->fh.val; args.access = nfsmode; if (rpc_nfs3_access_async(nfs->rpc, nfs3_open_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs_cb_data(data); return -1; } return 0; } /* TODO add the plumbing for mode */ int nfs3_open_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data) { if (flags & O_CREAT) { return nfs3_create_async(nfs, path, flags, mode, cb, private_data); } if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, nfs3_open_continue_internal, NULL, NULL, flags) != 0) { return -1; } return 0; } libnfs-libnfs-4.0.0/lib/nfs_v4.c000066400000000000000000004574161343063627400164050ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2017 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ /* * High level api to nfsv4 filesystems */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #endif #ifdef HAVE_INTTYPES_H #include #else #define PRIu64 "llu" #endif #ifdef HAVE_UTIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #if defined(__ANDROID__) && !defined(HAVE_SYS_STATVFS_H) #define statvfs statfs #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef MAJOR_IN_MKDEV #include #endif #ifdef HAVE_SYS_SYSMACROS_H #include #endif #ifdef HAVE_GETPWNAM #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "libnfs-zdr.h" #include "slist.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #ifndef discard_const #define discard_const(ptr) ((void *)((intptr_t)(ptr))) #endif struct nfs4_cb_data; typedef int (*op_filler)(struct nfs4_cb_data *data, nfs_argop4 *op); struct lookup_link_data { unsigned int idx; }; typedef void (*blob_free)(void *); struct nfs4_blob { int len; void *val; blob_free free; }; /* Function and arguments to append the requested operations we want * for the resolved path. */ struct lookup_filler { op_filler func; int max_op; int flags; void *data; /* Freed by nfs4_cb_data destructor */ struct nfs4_blob blob0; struct nfs4_blob blob1; struct nfs4_blob blob2; struct nfs4_blob blob3; }; struct rw_data { uint64_t offset; int update_pos; }; struct nfs4_cb_data { struct nfs_context *nfs; /* Do not follow symlinks for the final component on a lookup. * I.e. stat vs lstat */ #define LOOKUP_FLAG_NO_FOLLOW 0x0001 #define LOOKUP_FLAG_IS_STATVFS64 0x0002 int flags; /* Internal callback for open-with-continuation use */ rpc_cb open_cb; /* Application callback and data */ nfs_cb cb; void *private_data; /* internal callback */ rpc_cb continue_cb; char *path; /* path to lookup */ struct lookup_filler filler; /* Data we need when resolving a symlink in the path */ struct lookup_link_data link; /* Data we need for updating offset in read/write */ struct rw_data rw_data; }; static uint32_t standard_attributes[2] = { (1 << FATTR4_TYPE | 1 << FATTR4_SIZE | 1 << FATTR4_FILEID), (1 << (FATTR4_MODE - 32) | 1 << (FATTR4_NUMLINKS - 32) | 1 << (FATTR4_OWNER - 32) | 1 << (FATTR4_OWNER_GROUP - 32) | 1 << (FATTR4_SPACE_USED - 32) | 1 << (FATTR4_TIME_ACCESS - 32) | 1 << (FATTR4_TIME_METADATA - 32) | 1 << (FATTR4_TIME_MODIFY - 32)) }; static uint32_t statvfs_attributes[2] = { (1 << FATTR4_FSID | 1 << FATTR4_FILES_AVAIL | 1 << FATTR4_FILES_FREE | 1 << FATTR4_FILES_TOTAL | 1 << FATTR4_MAXNAME), (1 << (FATTR4_SPACE_AVAIL - 32) | 1 << (FATTR4_SPACE_FREE - 32) | 1 << (FATTR4_SPACE_TOTAL - 32)) }; static int nfs4_open_async_internal(struct nfs_context *nfs, struct nfs4_cb_data *data, int flags, int mode); /* Caller will free the returned path. */ static char * nfs4_resolve_path(struct nfs_context *nfs, const char *path) { char *new_path = NULL; /* Absolute paths we just use as is. * Relateive paths have cwd prepended to them and then become * absolute paths too. */ if (path[0] == '/') { new_path = strdup(path); } else { new_path = malloc(strlen(path) + strlen(nfs->cwd) + 2); if (new_path != NULL) { sprintf(new_path, "%s/%s", nfs->cwd, path); } } if (new_path == NULL) { nfs_set_error(nfs, "Out of memory: failed to " "allocate path string"); return NULL; } if (nfs_normalize_path(nfs, new_path)) { nfs_set_error(nfs, "Failed to normalize real path. %s", nfs_get_error(nfs)); free(new_path); return NULL; } return new_path; } static void free_nfs4_cb_data(struct nfs4_cb_data *data) { free(data->path); free(data->filler.data); if (data->filler.blob0.val && data->filler.blob0.free) { data->filler.blob0.free(data->filler.blob0.val); } if (data->filler.blob1.val && data->filler.blob1.free) { data->filler.blob1.free(data->filler.blob1.val); } if (data->filler.blob2.val && data->filler.blob2.free) { data->filler.blob2.free(data->filler.blob2.val); } if (data->filler.blob3.val && data->filler.blob3.free) { data->filler.blob3.free(data->filler.blob3.val); } free(data); } static struct nfs4_cb_data * init_cb_data_full_path(struct nfs_context *nfs, const char *path) { struct nfs4_cb_data *data; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "cb data"); return NULL; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->path = nfs4_resolve_path(nfs, path); if (data->path == NULL) { free_nfs4_cb_data(data); return NULL; } return data; } static void data_split_path(struct nfs4_cb_data *data) { char *path; path = strrchr(data->path, '/'); if (path == data->path) { char *ptr; for (ptr = data->path; *ptr; ptr++) { *ptr = *(ptr + 1); } /* No path to lookup */ data->filler.data = data->path; data->path = strdup("/"); } else { *path++ = 0; data->filler.data = strdup(path); } } static struct nfs4_cb_data * init_cb_data_split_path(struct nfs_context *nfs, const char *orig_path) { struct nfs4_cb_data *data; data = init_cb_data_full_path(nfs, orig_path); if (data == NULL) { return NULL; } data_split_path(data); return data; } static int check_nfs4_error(struct nfs_context *nfs, int status, struct nfs4_cb_data *data, void *command_data, char *op_name) { COMPOUND4res *res = command_data; if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, res, data->private_data); free_nfs4_cb_data(data); return 1; } if (status == RPC_STATUS_CANCEL) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); free_nfs4_cb_data(data); return 1; } if (status == RPC_STATUS_TIMEOUT) { data->cb(-EINTR, nfs, "Command timed out", data->private_data); free_nfs4_cb_data(data); return 1; } if (res && res->status != NFS4_OK) { nfs_set_error(nfs, "NFS4: %s (path %s) failed with " "%s(%d)", op_name, data->path, nfsstat4_to_str(res->status), nfsstat4_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return 1; } return 0; } static int nfs4_find_op(struct nfs_context *nfs, struct nfs4_cb_data *data, COMPOUND4res *res, int op, const char *op_name) { int i; for (i = 0; i < (int)res->resarray.resarray_len; i++) { if (res->resarray.resarray_val[i].resop == op) { break; } } if (i == res->resarray.resarray_len) { nfs_set_error(nfs, "No %s result.", op_name); data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return -1; } return i; } static uint64_t nfs_hton64(uint64_t val) { int i; uint64_t res; unsigned char *ptr = (void *)&res; for (i = 0; i < 8; i++) { ptr[7 - i] = val & 0xff; val >>= 8; } return res; } static uint64_t nfs_ntoh64(uint64_t val) { int i; uint64_t res; unsigned char *ptr = (void *)&res; for (i = 0; i < 8; i++) { ptr[7 - i] = val & 0xff; val >>= 8; } return res; } static uint64_t nfs_pntoh64(const uint32_t *buf) { uint64_t val; val = ntohl(*(uint32_t *)(void *)buf++); val <<= 32; val |= ntohl(*(uint32_t *)(void *)buf); return val; } static int nfs_get_ugid(struct nfs_context *nfs, const char *buf, int slen, int is_user) { int ugid = 0; const char *name = buf; while (slen) { if (isdigit(*buf)) { ugid *= 10; ugid += *buf - '0'; } else { #ifdef HAVE_GETPWNAM struct passwd *pwd = getpwnam(name); if (pwd) { if (is_user) { return pwd->pw_uid; } else { return pwd->pw_gid; } } #else (void) name; // Let the compiler know that this variable is intentionally unused, build would fail with -Werror=unused-variable otherwise #endif return 65534; } buf++; slen--; } return ugid; } #define CHECK_GETATTR_BUF_SPACE(len, size) \ if (len < size) { \ nfs_set_error(nfs, "Not enough data in fattr4"); \ return -1; \ } static int nfs_parse_attributes(struct nfs_context *nfs, struct nfs4_cb_data *data, struct nfs_stat_64 *st, const char *buf, int len) { int type, slen, pad; /* Type */ CHECK_GETATTR_BUF_SPACE(len, 4); type = ntohl(*(uint32_t *)(void *)buf); buf += 4; len -= 4; /* Size */ CHECK_GETATTR_BUF_SPACE(len, 8); st->nfs_size = nfs_pntoh64((uint32_t *)(void *)buf); buf += 8; len -= 8; /* Inode */ CHECK_GETATTR_BUF_SPACE(len, 8); st->nfs_ino = nfs_pntoh64((uint32_t *)(void *)buf); buf += 8; len -= 8; /* Mode */ CHECK_GETATTR_BUF_SPACE(len, 4); st->nfs_mode = ntohl(*(uint32_t *)(void *)buf); buf += 4; len -= 4; switch (type) { case NF4REG: st->nfs_mode |= S_IFREG; break; case NF4DIR: st->nfs_mode |= S_IFDIR; break; case NF4BLK: st->nfs_mode |= S_IFBLK; break; case NF4CHR: st->nfs_mode |= S_IFCHR; break; case NF4LNK: st->nfs_mode |= S_IFLNK; break; case NF4SOCK: st->nfs_mode |= S_IFSOCK; break; case NF4FIFO: st->nfs_mode |= S_IFIFO; break; default: break; } /* Num Links */ CHECK_GETATTR_BUF_SPACE(len, 4); st->nfs_nlink = ntohl(*(uint32_t *)(void *)buf); buf += 4; len -= 4; /* Owner */ CHECK_GETATTR_BUF_SPACE(len, 4); slen = ntohl(*(uint32_t *)(void *)buf); buf += 4; len -= 4; pad = (4 - (slen & 0x03)) & 0x03; CHECK_GETATTR_BUF_SPACE(len, slen); st->nfs_uid = nfs_get_ugid(nfs, buf, slen, 1); buf += slen; CHECK_GETATTR_BUF_SPACE(len, pad); buf += pad; len -= pad; /* Group */ CHECK_GETATTR_BUF_SPACE(len, 4); slen = ntohl(*(uint32_t *)(void *)buf); buf += 4; len -= 4; pad = (4 - (slen & 0x03)) & 0x03; CHECK_GETATTR_BUF_SPACE(len, slen); st->nfs_gid = nfs_get_ugid(nfs, buf, slen, 0); buf += slen; CHECK_GETATTR_BUF_SPACE(len, pad); buf += pad; len -= pad; /* Space Used */ CHECK_GETATTR_BUF_SPACE(len, 8); st->nfs_used = nfs_pntoh64((uint32_t *)(void *)buf); buf += 8; len -= 8; /* ATime */ CHECK_GETATTR_BUF_SPACE(len, 12); st->nfs_atime = nfs_pntoh64((uint32_t *)(void *)buf); buf += 8; len -= 8; st->nfs_atime_nsec = ntohl(*(uint32_t *)(void *)buf); buf += 4; len -= 4; /* CTime */ CHECK_GETATTR_BUF_SPACE(len, 12); st->nfs_ctime = nfs_pntoh64((uint32_t *)(void *)buf); buf += 8; len -= 8; st->nfs_ctime_nsec = ntohl(*(uint32_t *)(void *)buf); buf += 4; len -= 4; /* MTime */ CHECK_GETATTR_BUF_SPACE(len, 12); st->nfs_mtime = nfs_pntoh64((uint32_t *)(void *)buf); buf += 8; len -= 8; st->nfs_mtime_nsec = ntohl(*(uint32_t *)(void *)buf); buf += 4; len -= 4; st->nfs_blksize = NFS_BLKSIZE; st->nfs_blocks = (st->nfs_used + NFS_BLKSIZE -1) / NFS_BLKSIZE; return 0; } static int nfs4_num_path_components(struct nfs_context *nfs, const char *path) { int i; for (i = 0; (path = strchr(path, '/')); path++, i++) ; return i; } static int nfs4_op_create(struct nfs_context *nfs, nfs_argop4 *op, const char *name, nfs_ftype4 type, struct nfs4_blob *attrmask, struct nfs4_blob *attr_vals, const char *linkdata, int dev) { CREATE4args *cargs; op[0].argop = OP_CREATE; cargs = &op[0].nfs_argop4_u.opcreate; memset(cargs, 0, sizeof(*cargs)); cargs->objtype.type = type; cargs->objname.utf8string_len = strlen(name); cargs->objname.utf8string_val = discard_const(name); if (attrmask) { cargs->createattrs.attrmask.bitmap4_len = attrmask->len; cargs->createattrs.attrmask.bitmap4_val = attrmask->val; } if (attr_vals) { cargs->createattrs.attr_vals.attrlist4_len = attr_vals->len; cargs->createattrs.attr_vals.attrlist4_val = attr_vals->val; } if (linkdata) { cargs->objtype.createtype4_u.linkdata.utf8string_len = strlen(linkdata); cargs->objtype.createtype4_u.linkdata.utf8string_val = discard_const(linkdata); } switch (type) { case NF4CHR: cargs->objtype.type = NF4CHR; cargs->objtype.createtype4_u.devdata.specdata1 = major(dev); cargs->objtype.createtype4_u.devdata.specdata2 = minor(dev); break; case NF4BLK: cargs->objtype.type = NF4BLK; cargs->objtype.createtype4_u.devdata.specdata1 = major(dev); cargs->objtype.createtype4_u.devdata.specdata2 = minor(dev); break; default: ; } return 1; } static int nfs4_op_commit(struct nfs_context *nfs, nfs_argop4 *op) { COMMIT4args *coargs; op[0].argop = OP_COMMIT; coargs = &op[0].nfs_argop4_u.opcommit; coargs->offset = 0; coargs->count = 0; return 1; } static int nfs4_op_close(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh) { CLOSE4args *clargs; int i = 0; if (fh->is_dirty) { i += nfs4_op_commit(nfs, &op[i]); } op[i].argop = OP_CLOSE; clargs = &op[i++].nfs_argop4_u.opclose; clargs->seqid = nfs->seqid; clargs->open_stateid.seqid = fh->stateid.seqid; memcpy(clargs->open_stateid.other, fh->stateid.other, 12); return i; } static int nfs4_op_access(struct nfs_context *nfs, nfs_argop4 *op, uint32_t access_mask) { ACCESS4args *aargs; op[0].argop = OP_ACCESS; aargs = &op[0].nfs_argop4_u.opaccess; memset(aargs, 0, sizeof(*aargs)); aargs->access = access_mask; return 1; } static int nfs4_op_setclientid(struct nfs_context *nfs, nfs_argop4 *op, verifier4 verifier, const char *client_name) { SETCLIENTID4args *scidargs; op[0].argop = OP_SETCLIENTID; scidargs = &op[0].nfs_argop4_u.opsetclientid; memcpy(scidargs->client.verifier, verifier, sizeof(verifier4)); scidargs->client.id.id_len = strlen(client_name); scidargs->client.id.id_val = discard_const(client_name); /* TODO: Decide what we should do here. As long as we only * expose a single FD to the application we will not be able to * do NFSv4 callbacks easily. * Just give it garbage for now until we figure out how we should * solve this. Until then we will just have to avoid doing things * that require a callback. * ( Clients (i.e. Linux) ignore this anyway and just call back to * the originating address and program anyway. ) */ scidargs->callback.cb_program = 0; /* NFS4_CALLBACK */ scidargs->callback.cb_location.r_netid = "tcp"; scidargs->callback.cb_location.r_addr = "0.0.0.0.0.0"; scidargs->callback_ident = 0x00000001; return 1; } static int nfs4_op_open_confirm(struct nfs_context *nfs, nfs_argop4 *op, uint32_t seqid, struct nfsfh *fh) { OPEN_CONFIRM4args *ocargs; op[0].argop = OP_OPEN_CONFIRM; ocargs = &op[0].nfs_argop4_u.opopen_confirm; ocargs->open_stateid.seqid = fh->stateid.seqid; memcpy(&ocargs->open_stateid.other, fh->stateid.other, 12); ocargs->seqid = seqid; return 1; } static int nfs4_op_truncate(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, void *sabuf) { SETATTR4args *saargs; static uint32_t mask[2] = {1 << (FATTR4_SIZE), 1 << (FATTR4_TIME_MODIFY_SET - 32)}; op[0].argop = OP_SETATTR; saargs = &op[0].nfs_argop4_u.opsetattr; saargs->stateid.seqid = fh->stateid.seqid; memcpy(saargs->stateid.other, fh->stateid.other, 12); saargs->obj_attributes.attrmask.bitmap4_len = 2; saargs->obj_attributes.attrmask.bitmap4_val = mask; saargs->obj_attributes.attr_vals.attrlist4_len = 12; saargs->obj_attributes.attr_vals.attrlist4_val = sabuf; return 1; } static int nfs4_op_chmod(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, void *sabuf) { SETATTR4args *saargs; static uint32_t mask[2] = {0, 1 << (FATTR4_MODE - 32)}; op[0].argop = OP_SETATTR; saargs = &op[0].nfs_argop4_u.opsetattr; saargs->stateid.seqid = fh->stateid.seqid; memcpy(saargs->stateid.other, fh->stateid.other, 12); saargs->obj_attributes.attrmask.bitmap4_len = 2; saargs->obj_attributes.attrmask.bitmap4_val = mask; saargs->obj_attributes.attr_vals.attrlist4_len = 4; saargs->obj_attributes.attr_vals.attrlist4_val = sabuf; return 1; } static int nfs4_op_chown(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, void *sabuf, int len) { SETATTR4args *saargs; static uint32_t mask[2] = {0, 1 << (FATTR4_OWNER - 32) | 1 << (FATTR4_OWNER_GROUP - 32)}; op[0].argop = OP_SETATTR; saargs = &op[0].nfs_argop4_u.opsetattr; saargs->stateid.seqid = fh->stateid.seqid; memcpy(saargs->stateid.other, fh->stateid.other, 12); saargs->obj_attributes.attrmask.bitmap4_len = 2; saargs->obj_attributes.attrmask.bitmap4_val = mask; saargs->obj_attributes.attr_vals.attrlist4_len = len; saargs->obj_attributes.attr_vals.attrlist4_val = sabuf; return 1; } static int nfs4_op_utimes(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, void *sabuf, int len) { SETATTR4args *saargs; static uint32_t mask[2] = {0, 1 << (FATTR4_TIME_ACCESS_SET - 32) | 1 << (FATTR4_TIME_MODIFY_SET - 32)}; op[0].argop = OP_SETATTR; saargs = &op[0].nfs_argop4_u.opsetattr; saargs->stateid.seqid = fh->stateid.seqid; memcpy(saargs->stateid.other, fh->stateid.other, 12); saargs->obj_attributes.attrmask.bitmap4_len = 2; saargs->obj_attributes.attrmask.bitmap4_val = mask; saargs->obj_attributes.attr_vals.attrlist4_len = len; saargs->obj_attributes.attr_vals.attrlist4_val = sabuf; return 1; } static int nfs4_op_readdir(struct nfs_context *nfs, nfs_argop4 *op, uint64_t cookie) { READDIR4args *rdargs; op[0].argop = OP_READDIR; rdargs = &op[0].nfs_argop4_u.opreaddir; memset(rdargs, 0, sizeof(*rdargs)); rdargs->cookie = cookie; rdargs->dircount = 8192; rdargs->maxcount = 8192; rdargs->attr_request.bitmap4_len = 2; rdargs->attr_request.bitmap4_val = standard_attributes; return 1; } static int nfs4_op_rename(struct nfs_context *nfs, nfs_argop4 *op, const char *oldname, const char *newname) { RENAME4args *rargs; op[0].argop = OP_RENAME; rargs = &op[0].nfs_argop4_u.oprename; memset(rargs, 0, sizeof(*rargs)); rargs->oldname.utf8string_len = strlen(oldname); rargs->oldname.utf8string_val = discard_const(oldname); rargs->newname.utf8string_len = strlen(newname); rargs->newname.utf8string_val = discard_const(newname); return 1; } static int nfs4_op_read(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, uint64_t offset, size_t count) { READ4args *rargs; op[0].argop = OP_READ; rargs = &op[0].nfs_argop4_u.opread; rargs->stateid.seqid = fh->stateid.seqid; memcpy(rargs->stateid.other, fh->stateid.other, 12); rargs->offset = offset; rargs->count = count; return 1; } static int nfs4_op_write(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, uint64_t offset, size_t count, const char *buf) { WRITE4args *wargs; op[0].argop = OP_WRITE; wargs = &op[0].nfs_argop4_u.opwrite; wargs->stateid.seqid = fh->stateid.seqid; memcpy(wargs->stateid.other, fh->stateid.other, 12); wargs->offset = offset; if (fh->is_sync) { wargs->stable = DATA_SYNC4; } else { wargs->stable = UNSTABLE4; fh->is_dirty = 1; } wargs->data.data_len = count; wargs->data.data_val = discard_const(buf); return 1; } static int nfs4_op_getfh(struct nfs_context *nfs, nfs_argop4 *op) { op[0].argop = OP_GETFH; return 1; } static int nfs4_op_savefh(struct nfs_context *nfs, nfs_argop4 *op) { op[0].argop = OP_SAVEFH; return 1; } static int nfs4_op_link(struct nfs_context *nfs, nfs_argop4 *op, const char *newname) { LINK4args *largs; op[0].argop = OP_LINK; largs = &op[0].nfs_argop4_u.oplink; memset(largs, 0, sizeof(*largs)); largs->newname.utf8string_len = strlen(newname); largs->newname.utf8string_val = discard_const(newname); return 1; } static int nfs4_op_putfh(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *nfsfh) { PUTFH4args *pfargs; op[0].argop = OP_PUTFH; pfargs = &op[0].nfs_argop4_u.opputfh; pfargs->object.nfs_fh4_len = nfsfh->fh.len; pfargs->object.nfs_fh4_val = nfsfh->fh.val; return 1; } static int nfs4_op_lock(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, nfs_opnum4 cmd, nfs_lock_type4 locktype, int reclaim, uint64_t offset, length4 length) { LOCK4args *largs; op[0].argop = cmd; largs = &op[0].nfs_argop4_u.oplock; largs->locktype = locktype; largs->reclaim = reclaim; largs->offset = offset; largs->length = length; if (nfs->has_lock_owner) { largs->locker.new_lock_owner = 0; largs->locker.locker4_u.lock_owner.lock_stateid.seqid = fh->lock_stateid.seqid; memcpy(largs->locker.locker4_u.lock_owner.lock_stateid.other, fh->lock_stateid.other, 12); largs->locker.locker4_u.lock_owner.lock_seqid = fh->lock_seqid; } else { largs->locker.new_lock_owner = 1; largs->locker.locker4_u.open_owner.open_seqid = nfs->seqid; largs->locker.locker4_u.open_owner.open_stateid.seqid = fh->stateid.seqid; memcpy(largs->locker.locker4_u.open_owner.open_stateid.other, fh->stateid.other, 12); largs->locker.locker4_u.open_owner.lock_owner.clientid = nfs->clientid; largs->locker.locker4_u.open_owner.lock_owner.owner.owner_len = strlen(nfs->client_name); largs->locker.locker4_u.open_owner.lock_owner.owner.owner_val = nfs->client_name; largs->locker.locker4_u.open_owner.lock_seqid = fh->lock_seqid; } fh->lock_seqid++; return 1; } static int nfs4_op_locku(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, nfs_lock_type4 locktype, uint64_t offset, length4 length) { LOCKU4args *luargs; op[0].argop = OP_LOCKU; luargs = &op[0].nfs_argop4_u.oplocku; luargs->locktype = locktype; luargs->offset = offset; luargs->length = length; luargs->seqid = fh->lock_seqid; luargs->lock_stateid.seqid = fh->lock_stateid.seqid; memcpy(luargs->lock_stateid.other, fh->lock_stateid.other, 12); fh->lock_seqid++; return 1; } static int nfs4_op_lockt(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh, nfs_lock_type4 locktype, uint64_t offset, length4 length) { LOCKT4args *ltargs; op[0].argop = OP_LOCKT; ltargs = &op[0].nfs_argop4_u.oplockt; ltargs->locktype = locktype; ltargs->offset = offset; ltargs->length = length; ltargs->owner.clientid = nfs->clientid; ltargs->owner.owner.owner_len = strlen(nfs->client_name); ltargs->owner.owner.owner_val = nfs->client_name; return 1; } static int nfs4_op_lookup(struct nfs_context *nfs, nfs_argop4 *op, const char *path) { LOOKUP4args *largs; op[0].argop = OP_LOOKUP; largs = &op[0].nfs_argop4_u.oplookup; largs->objname.utf8string_len = strlen(path); largs->objname.utf8string_val = discard_const(path); return 1; } static int nfs4_op_setclientid_confirm(struct nfs_context *nfs, struct nfs_argop4 *op, uint64_t clientid, verifier4 verifier) { SETCLIENTID_CONFIRM4args *scidcargs; op[0].argop = OP_SETCLIENTID_CONFIRM; scidcargs = &op[0].nfs_argop4_u.opsetclientid_confirm; scidcargs->clientid = clientid; memcpy(scidcargs->setclientid_confirm, verifier, NFS4_VERIFIER_SIZE); return 1; } static int nfs4_op_putrootfh(struct nfs_context *nfs, nfs_argop4 *op) { op[0].argop = OP_PUTROOTFH; return 1; } static int nfs4_op_readlink(struct nfs_context *nfs, nfs_argop4 *op) { op[0].argop = OP_READLINK; return 1; } static int nfs4_op_remove(struct nfs_context *nfs, nfs_argop4 *op, const char *name) { REMOVE4args *rmargs; op[0].argop = OP_REMOVE; rmargs = &op[0].nfs_argop4_u.opremove; memset(rmargs, 0, sizeof(*rmargs)); rmargs->target.utf8string_len = strlen(name); rmargs->target.utf8string_val = discard_const(name); return 1; } static int nfs4_op_getattr(struct nfs_context *nfs, nfs_argop4 *op, uint32_t *attributes, int count) { GETATTR4args *gaargs; op[0].argop = OP_GETATTR; gaargs = &op[0].nfs_argop4_u.opgetattr; memset(gaargs, 0, sizeof(*gaargs)); gaargs->attr_request.bitmap4_val = attributes; gaargs->attr_request.bitmap4_len = count; return 1; } /* * Allocate op and populate the path components. * Will mutate path. * * Returns: * -1 : On error. * : On success. Idx represents the next free index in op. * Caller must free op. */ static int nfs4_allocate_op(struct nfs_context *nfs, nfs_argop4 **op, char *path, int num_extra) { char *ptr; int i, count; *op = NULL; count = nfs4_num_path_components(nfs, path); *op = malloc(sizeof(**op) * (2 + 2 * count + num_extra)); if (*op == NULL) { nfs_set_error(nfs, "Failed to allocate op array"); return -1; } i = 0; if (nfs->rootfh.len) { struct nfsfh fh; fh.fh.len = nfs->rootfh.len; fh.fh.val = nfs->rootfh.val; i += nfs4_op_putfh(nfs, &(*op)[i], &fh); } else { i += nfs4_op_putrootfh(nfs, &(*op)[i]); } ptr = &path[1]; while (ptr && *ptr != 0) { char *tmp; tmp = strchr(ptr, '/'); if (tmp) { *tmp = 0; tmp = tmp + 1; } i += nfs4_op_lookup(nfs, &(*op)[i], ptr); ptr = tmp; } i += nfs4_op_getattr(nfs, &(*op)[i], standard_attributes, 2); return i; } static int nfs4_lookup_path_async(struct nfs_context *nfs, struct nfs4_cb_data *data, rpc_cb cb); static void nfs4_lookup_path_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; READLINK4res *rlres = NULL; char *path, *tmp, *end; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "READLINK")) { return; } path = strdup(data->path); if (path == NULL) { nfs_set_error(nfs, "Out of memory duplicating path."); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } tmp = &path[0]; while (data->link.idx-- > 1) { tmp = strchr(tmp + 1, '/'); } *tmp++ = 0; end = strchr(tmp, '/'); if (end == NULL) { /* Symlink was the last component. */ end = ""; } else { *end++ = 0; } if ((i = nfs4_find_op(nfs, data, res, OP_READLINK, "READLINK")) < 0) { free(path); return; } rlres = &res->resarray.resarray_val[i].nfs_resop4_u.opreadlink; tmp = malloc(strlen(data->path) + 3 + strlen(rlres->READLINK4res_u.resok4.link.utf8string_val)); if (tmp == NULL) { nfs_set_error(nfs, "Out of memory duplicating path."); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); free(path); return; } sprintf(tmp, "%s/%s/%s", path, rlres->READLINK4res_u.resok4.link.utf8string_val, end); free(path); free(data->path); data->path = tmp; if (nfs4_lookup_path_async(nfs, data, data->continue_cb) < 0) { data->cb(-ENOMEM, nfs, res, data->private_data); free_nfs4_cb_data(data); return; } } static int nfs4_open_readlink(struct rpc_context *rpc, COMPOUND4res *res, struct nfs4_cb_data *data); static void nfs4_lookup_path_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4args args; nfs_argop4 *op; COMPOUND4res *res = command_data; int i; int resolve_link = 0; char *path, *tmp; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, res, data->private_data); free_nfs4_cb_data(data); return; } if (status == RPC_STATUS_CANCEL) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); free_nfs4_cb_data(data); return; } if (status == RPC_STATUS_TIMEOUT) { data->cb(-EINTR, nfs, "Command timed out", data->private_data); free_nfs4_cb_data(data); return; } if (res->status != NFS4_OK && res->status != NFS4ERR_SYMLINK) { nfs_set_error(nfs, "NFS4: (path %s) failed with " "%s(%d)", data->path, nfsstat4_to_str(res->status), nfsstat4_to_errno(res->status)); data->cb(nfsstat3_to_errno(res->status), nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } for (i = 0; i < (int)res->resarray.resarray_len; i++) { if (res->resarray.resarray_val[i].resop == OP_GETATTR) { GETATTR4resok *garesok; struct nfs_stat_64 st; garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4; memset(&st, 0, sizeof(st)); if (nfs_parse_attributes(nfs, data, &st, garesok->obj_attributes.attr_vals.attrlist4_val, garesok->obj_attributes.attr_vals.attrlist4_len) < 0) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } if ((st.nfs_mode & S_IFMT) == S_IFLNK) { /* The final component of the path was a * symlink so we may need to resolve it. */ resolve_link = 1; } } } /* Open/create is special since the final component for the file * object is sent as part of the OP_OPEN command. So even if the * directory path is all good and resolved, we still need to check * the attributes for the final component and resolve it if it too * is a symlink. */ if (!resolve_link) { if (nfs4_open_readlink(rpc, res, data) < 0) { /* It was a symlink and we have started trying to * resolve it. Nothing more to do here. */ return; } } if (data->flags & LOOKUP_FLAG_NO_FOLLOW) { /* Do not resolve the final component of the path * if it is a symlink. */ resolve_link = 0; } /* Everything is good so we can just pass it on to the next * phase. */ if (res->status == NFS4_OK && !resolve_link) { data->continue_cb(rpc, NFS4_OK, res, data); return; } /* Find the lookup that failed and the associated fh */ data->link.idx = 0; for (i = 0; i < (int)res->resarray.resarray_len; i++) { if (res->resarray.resarray_val[i].resop == OP_LOOKUP) { if (res->resarray.resarray_val[i].nfs_resop4_u.oplookup.status == NFS4ERR_SYMLINK) { break; } data->link.idx++; } } if (!resolve_link && i == res->resarray.resarray_len) { nfs_set_error(nfs, "Symlink not found during lookup."); data->cb(-EFAULT, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } /* Build a new path that strips of everything after the symlink. */ path = strdup(data->path); if (path == NULL) { nfs_set_error(nfs, "Out of memory. Failed to duplicate " "path."); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } /* The symlink is not the last component, so find the '/' before * the symlink and zero it out. */ if (!resolve_link) { tmp = path; for (i = 0; i < (int)data->link.idx; i++) { tmp = strchr(tmp + 1, '/'); } *tmp = 0; } /* We need to resolve the symlink */ if ((i = nfs4_allocate_op(nfs, &op, path, 1)) < 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); free(path); return; } /* Append a READLINK command */ i += nfs4_op_readlink(nfs, &op[i]); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_lookup_path_2_cb, &args, data) != 0) { nfs_set_error(nfs, "Failed to queue READLINK command. %s", nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); free(path); return; } free(path); } static int nfs4_lookup_path_async(struct nfs_context *nfs, struct nfs4_cb_data *data, rpc_cb cb) { COMPOUND4args args; nfs_argop4 *op; char *path; int i, num_op; path = nfs4_resolve_path(nfs, data->path); if (path == NULL) { return -1; } free(data->path); data->path = path; path = strdup(path); if (path == NULL) { return -1; } if ((i = nfs4_allocate_op(nfs, &op, path, data->filler.max_op)) < 0) { free(path); return -1; } num_op = data->filler.func(data, &op[i]); data->continue_cb = cb; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i + num_op; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_lookup_path_1_cb, &args, data) != 0) { nfs_set_error(nfs, "Failed to queue LOOKUP command. %s", nfs_get_error(nfs)); free(path); free(op); return -1; } free(path); free(op); return 0; } static int nfs4_populate_getfh(struct nfs4_cb_data *data, nfs_argop4 *op) { return nfs4_op_getfh(data->nfs, op); } static int nfs4_populate_getattr(struct nfs4_cb_data *data, nfs_argop4 *op) { return nfs4_op_getfh(data->nfs, op); } static int nfs4_populate_access(struct nfs4_cb_data *data, nfs_argop4 *op) { uint32_t mode; memcpy(&mode, data->filler.blob3.val, sizeof(uint32_t)); return nfs4_op_access(data->nfs, op, mode); } static void nfs4_mount_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; GETFH4resok *gfhresok; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "GETFH")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_GETFH, "GETFH")) < 0) { return; } gfhresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; nfs->rootfh.len = gfhresok->object.nfs_fh4_len; nfs->rootfh.val = malloc(nfs->rootfh.len); if (nfs->rootfh.val == NULL) { nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memcpy(nfs->rootfh.val, gfhresok->object.nfs_fh4_val, nfs->rootfh.len); data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } static void nfs4_mount_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "SETCLIENTID_CONFIRM")) { return; } data->filler.func = nfs4_populate_getfh; data->filler.max_op = 1; data->filler.data = malloc(2 * sizeof(uint32_t)); if (data->filler.data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "data structure."); data->cb(-ENOMEM, nfs, res, data->private_data); free_nfs4_cb_data(data); return; } memset(data->filler.data, 0, 2 * sizeof(uint32_t)); if (nfs4_lookup_path_async(nfs, data, nfs4_mount_4_cb) < 0) { data->cb(-ENOMEM, nfs, res, data->private_data); free_nfs4_cb_data(data); return; } } static void nfs4_mount_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; COMPOUND4args args; nfs_argop4 op[1]; SETCLIENTID4resok *scidresok; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "SETCLIENTID")) { return; } scidresok = &res->resarray.resarray_val[0].nfs_resop4_u.opsetclientid.SETCLIENTID4res_u.resok4; nfs->clientid = scidresok->clientid; memcpy(nfs->setclientid_confirm, scidresok->setclientid_confirm, NFS4_VERIFIER_SIZE); memset(op, 0, sizeof(op)); i = nfs4_op_setclientid_confirm(nfs, &op[0], nfs->clientid, nfs->setclientid_confirm); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, nfs4_mount_3_cb, &args, private_data) != 0) { nfs_set_error(nfs, "Failed to queue SETCLIENTID_CONFIRM. %s", nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } static void nfs4_mount_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4args args; nfs_argop4 op[1]; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, NULL, "CONNECT")) { return; } memset(op, 0, sizeof(op)); i = nfs4_op_setclientid(nfs, &op[0], nfs->verifier, nfs->client_name); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, nfs4_mount_2_cb, &args, data) != 0) { nfs_set_error(nfs, "Failed to queue SETCLIENTID. %s", nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } int nfs4_mount_async(struct nfs_context *nfs, const char *server, const char *export, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; char *new_server, *new_export; int port; new_server = strdup(server); free(nfs->server); nfs->server = new_server; new_export = strdup(export); if (nfs_normalize_path(nfs, new_export)) { nfs_set_error(nfs, "Bad export path. %s", nfs_get_error(nfs)); free(new_export); return -1; } free(nfs->export); nfs->export = new_export; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "memory for nfs mount data"); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->path = strdup(new_export); port = nfs->nfsport ? nfs->nfsport : 2049; if (rpc_connect_port_async(nfs->rpc, server, port, NFS4_PROGRAM, NFS_V4, nfs4_mount_1_cb, data) != 0) { nfs_set_error(nfs, "Failed to start connection. %s", nfs_get_error(nfs)); free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_chdir_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "CHDIR")) { return; } /* Ok, all good. Lets steal the path string. */ free(nfs->cwd); nfs->cwd = data->path; data->path = NULL; data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } int nfs4_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_full_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_getattr; data->filler.max_op = 1; data->filler.data = malloc(2 * sizeof(uint32_t)); if (data->filler.data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "data structure."); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return -1; } memset(data->filler.data, 0, 2 * sizeof(uint32_t)); if (nfs4_lookup_path_async(nfs, data, nfs4_chdir_1_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_xstat64_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; GETATTR4resok *garesok; struct nfs_stat_64 st; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "STAT64")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_GETATTR, "GETATTR")) < 0) { return; } garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4; memset(&st, 0, sizeof(st)); if (nfs_parse_attributes(nfs, data, &st, garesok->obj_attributes.attr_vals.attrlist4_val, garesok->obj_attributes.attr_vals.attrlist4_len) < 0) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); } data->cb(0, nfs, &st, data->private_data); free_nfs4_cb_data(data); } int nfs4_stat64_async(struct nfs_context *nfs, const char *path, int no_follow, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_full_path(nfs, path); if (data == NULL) { return -1; } if (no_follow) { data->flags |= LOOKUP_FLAG_NO_FOLLOW; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_getattr; data->filler.max_op = 1; data->filler.data = malloc(2 * sizeof(uint32_t)); if (data->filler.data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "data structure."); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return -1; } memset(data->filler.data, 0, 2 * sizeof(uint32_t)); if (nfs4_lookup_path_async(nfs, data, nfs4_xstat64_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } /* Takes object name as filler.data * blob0 as the fattr4 attribute mask * blob1 as the fattr4 attribute list */ static int nfs4_populate_mkdir(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; return nfs4_op_create(nfs, op, data->filler.data, NF4DIR, &data->filler.blob0, &data->filler.blob1, NULL, 0); } static void nfs4_mkdir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "MKDIR")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } int nfs4_mkdir2_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; uint32_t *u32ptr; data = init_cb_data_split_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_mkdir; data->filler.max_op = 1; /* attribute mask */ u32ptr = malloc(2 * sizeof(uint32_t)); if (u32ptr == NULL) { nfs_set_error(nfs, "Out of memory allocating bitmap"); free_nfs4_cb_data(data); return -1; } u32ptr[0] = 0; u32ptr[1] = 1 << (FATTR4_MODE - 32); data->filler.blob0.len = 2; data->filler.blob0.val = u32ptr; data->filler.blob0.free = free; /* attribute values */ u32ptr = malloc(1 * sizeof(uint32_t)); if (u32ptr == NULL) { nfs_set_error(nfs, "Out of memory allocating attributes"); free_nfs4_cb_data(data); return -1; } u32ptr[0] = htonl(mode); data->filler.blob1.len = 4; data->filler.blob1.val = u32ptr; data->filler.blob1.free = free; if (nfs4_lookup_path_async(nfs, data, nfs4_mkdir_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } /* Takes object name as filler.data */ static int nfs4_populate_remove(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; return nfs4_op_remove(nfs, op, data->filler.data); } static void nfs4_remove_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "REMOVE")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } static int nfs4_remove_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_split_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_remove; data->filler.max_op = 1; if (nfs4_lookup_path_async(nfs, data, nfs4_remove_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } int nfs4_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { return nfs4_remove_async(nfs, path, cb, private_data); } static void nfs_increment_seqid(struct nfs_context *nfs, uint32_t status) { /* RFC3530 8.1.5 */ switch (status) { case NFS4ERR_STALE_CLIENTID: case NFS4ERR_STALE_STATEID: case NFS4ERR_BAD_STATEID: case NFS4ERR_BAD_SEQID: case NFS4ERR_BADZDR: case NFS4ERR_RESOURCE: case NFS4ERR_NOFILEHANDLE: break; default: nfs->seqid++; } } static void nfs4_open_setattr_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; struct nfsfh *fh; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "SETATTR")) { return; } fh = data->filler.blob0.val; data->filler.blob0.val = NULL; data->cb(0, nfs, fh, data->private_data); free_nfs4_cb_data(data); } static void nfs4_open_truncate_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *fh = data->filler.blob0.val; COMPOUND4res *res = command_data; COMPOUND4args args; nfs_argop4 op[2]; int i; if (check_nfs4_error(nfs, status, data, res, "OPEN")) { return; } i = nfs4_op_putfh(nfs, op, fh); i += nfs4_op_truncate(nfs, &op[i], fh, data->filler.blob3.val); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_open_setattr_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } static void nfs4_open_chmod_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *fh = data->filler.blob0.val; COMPOUND4res *res = command_data; COMPOUND4args args; nfs_argop4 op[2]; int i; if (check_nfs4_error(nfs, status, data, res, "OPEN")) { return; } i = nfs4_op_putfh(nfs, op, fh); i += nfs4_op_chmod(nfs, &op[i], fh, data->filler.blob3.val); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_open_setattr_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } static void nfs4_open_confirm_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; OPEN_CONFIRM4resok *ocresok; int i; struct nfsfh *fh; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (res) { nfs_increment_seqid(nfs, res->status); } if (check_nfs4_error(nfs, status, data, res, "OPEN_CONFIRM")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_OPEN_CONFIRM, "OPEN_CONFIRM")) < 0) { return; } ocresok = &res->resarray.resarray_val[i].nfs_resop4_u.opopen_confirm.OPEN_CONFIRM4res_u.resok4; fh = data->filler.blob0.val; fh->stateid.seqid = ocresok->open_stateid.seqid; memcpy(fh->stateid.other, ocresok->open_stateid.other, 12); if (data->open_cb) { data->open_cb(rpc, status, command_data, private_data); return; } data->filler.blob0.val = NULL; data->cb(0, nfs, fh, data->private_data); free_nfs4_cb_data(data); } static void nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; ACCESS4resok *aresok; OPEN4resok *oresok; GETFH4resok *gresok; int i; struct nfsfh *fh; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (res) { nfs_increment_seqid(nfs, res->status); } if (check_nfs4_error(nfs, status, data, res, "OPEN")) { return; } /* Parse Access and check that we have the access that we need */ if ((i = nfs4_find_op(nfs, data, res, OP_ACCESS, "ACCESS")) < 0) { return; } aresok = &res->resarray.resarray_val[i].nfs_resop4_u.opaccess.ACCESS4res_u.resok4; if (aresok->supported != aresok->access) { nfs_set_error(nfs, "Insufficient ACCESS. Wanted %08x but " "got %08x.", aresok->access, aresok->supported); data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } /* Parse GetFH */ if ((i = nfs4_find_op(nfs, data, res, OP_GETFH, "GETFH")) < 0) { return; } gresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; fh = malloc(sizeof(*fh)); if (fh == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "nfsfh"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memset(fh, 0 , sizeof(*fh)); data->filler.blob0.val = fh; data->filler.blob0.free = (blob_free)nfs_free_nfsfh; fh->fh.len = gresok->object.nfs_fh4_len; fh->fh.val = malloc(fh->fh.len); if (fh->fh.val == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "nfsfh"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memcpy(fh->fh.val, gresok->object.nfs_fh4_val, fh->fh.len); if (data->filler.flags & O_SYNC) { fh->is_sync = 1; } if (data->filler.flags & O_APPEND) { fh->is_append = 1; } /* Parse Open */ if ((i = nfs4_find_op(nfs, data, res, OP_OPEN, "OPEN")) < 0) { return; } oresok = &res->resarray.resarray_val[i].nfs_resop4_u.opopen.OPEN4res_u.resok4; fh->stateid.seqid = oresok->stateid.seqid; memcpy(fh->stateid.other, oresok->stateid.other, 12); if (oresok->rflags & OPEN4_RESULT_CONFIRM) { COMPOUND4args args; nfs_argop4 op[2]; memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_open_confirm(nfs, &op[i], nfs->seqid, fh); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(rpc, nfs4_open_confirm_cb, &args, private_data) != 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } return; } if (data->open_cb) { data->open_cb(rpc, status, command_data, private_data); return; } data->filler.blob0.val = NULL; data->cb(0, nfs, fh, data->private_data); free_nfs4_cb_data(data); } static void nfs4_init_random_verifier(char *verifier) { static uint64_t seed = 0, v; int i; if (seed == 0) { seed = ~rpc_current_time() << 32 | getpid(); } else { seed *= 1337; } v = seed; for (i = 0; i < NFS4_VERIFIER_SIZE; i++) { verifier[i] = v & 0xff; v >>= 8; } } /* filler.flags are the open flags * filler.data is the object name */ static int nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; OPEN4args *oargs; uint32_t access_mask = 0; verifier4 verifier; int i; if (data->filler.flags & O_WRONLY) { access_mask |= ACCESS4_MODIFY; } if (data->filler.flags & O_RDWR) { access_mask |= ACCESS4_READ|ACCESS4_MODIFY; } if (!(data->filler.flags & O_WRONLY)) { access_mask |= ACCESS4_READ; } /* Access */ i = nfs4_op_access(nfs, &op[0], access_mask); /* Open */ op[i].argop = OP_OPEN; oargs = &op[i++].nfs_argop4_u.opopen; memset(oargs, 0, sizeof(*oargs)); oargs->seqid = nfs->seqid; if (access_mask & ACCESS4_READ) { oargs->share_access |= OPEN4_SHARE_ACCESS_READ; } if (access_mask & ACCESS4_MODIFY) { oargs->share_access |= OPEN4_SHARE_ACCESS_WRITE; } oargs->share_deny = OPEN4_SHARE_DENY_NONE; oargs->owner.clientid = nfs->clientid; oargs->owner.owner.owner_len = strlen(nfs->client_name); oargs->owner.owner.owner_val = nfs->client_name; if (data->filler.flags & O_CREAT) { createhow4 *ch; fattr4 *fa; ch = &oargs->openhow.openflag4_u.how; fa = &ch->createhow4_u.createattrs; oargs->openhow.opentype = OPEN4_CREATE; if (data->filler.flags|O_EXCL) { ch->mode = EXCLUSIVE4; nfs4_init_random_verifier(&verifier[0]); memcpy(ch->createhow4_u.createverf, verifier, sizeof(verifier4)); } else { ch->mode = UNCHECKED4; fa->attrmask.bitmap4_len = data->filler.blob1.len; fa->attrmask.bitmap4_val = data->filler.blob1.val; fa->attr_vals.attrlist4_len = data->filler.blob2.len; fa->attr_vals.attrlist4_val = data->filler.blob2.val; } } else { oargs->openhow.opentype = OPEN4_NOCREATE; } oargs->claim.claim = CLAIM_NULL; oargs->claim.open_claim4_u.file.utf8string_len = strlen(data->filler.data); oargs->claim.open_claim4_u.file.utf8string_val = data->filler.data; /* GetFH */ i += nfs4_op_getfh(nfs, &op[i]); return i; } static void nfs4_open_readlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; READLINK4resok *rlresok; int i; char *path; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "READLINK")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_READLINK, "READLINK")) < 0) { return; } rlresok = &res->resarray.resarray_val[i].nfs_resop4_u.opreadlink.READLINK4res_u.resok4; path = malloc(2 + strlen(data->path) + strlen(rlresok->link.utf8string_val)); if (path == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "path"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } sprintf(path, "%s/%s", data->path, rlresok->link.utf8string_val); free(data->path); data->path = NULL; free(data->filler.data); data->filler.data = NULL; data->path = nfs4_resolve_path(nfs, path); free(path); if (data->path == NULL) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } data_split_path(data); data->filler.func = nfs4_populate_open; data->filler.max_op = 3; if (nfs4_lookup_path_async(nfs, data, nfs4_open_cb) < 0) { data->cb(-ENOMEM, nfs, res, data->private_data); free_nfs4_cb_data(data); return; } } static int nfs4_populate_lookup_readlink(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; int i; i = nfs4_op_lookup(nfs, &op[0], data->filler.data); i += nfs4_op_readlink(nfs, &op[i]); return i; } /* If the final component in the open was a symlink we need to resolve it and * re-try the nfs4_open_async() */ static int nfs4_open_readlink(struct rpc_context *rpc, COMPOUND4res *res, struct nfs4_cb_data *data) { struct nfs_context *nfs = data->nfs; int i; for (i = 0; i < (int)res->resarray.resarray_len; i++) { OPEN4res *ores; if (res->resarray.resarray_val[i].resop != OP_OPEN) { continue; } ores = &res->resarray.resarray_val[i].nfs_resop4_u.opopen; if (ores->status != NFS4ERR_SYMLINK) { continue; } if (data->filler.flags & O_NOFOLLOW) { nfs_set_error(nfs, "Symlink encountered during " "open(O_NOFOLLOW)"); data->cb(-ELOOP, nfs, nfs_get_error(nfs), data->private_data); return -1; } /* The object we need to do readlink on is already stored in * data->filler.data so *populate* can just grab it from there. */ data->filler.func = nfs4_populate_lookup_readlink; data->filler.max_op = 2; if (nfs4_lookup_path_async(nfs, data, nfs4_open_readlink_cb) < 0) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return -1; } return -1; } return 0; } /* * data.blob0 is used for nfsfh * data.blob1 is used for the attribute mask in case on O_CREAT * data.blob2 is the attribute value in case of O_CREAT */ static int nfs4_open_async_internal(struct nfs_context *nfs, struct nfs4_cb_data *data, int flags, int mode) { if (flags & O_APPEND && !(flags & (O_RDWR|O_WRONLY))) { flags &= ~O_APPEND; } if (flags & O_CREAT) { uint32_t *d; /* Attribute mask */ d = malloc(2 * sizeof(uint32_t)); if (d == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } d[0] = 0; d[1] = 1 << (FATTR4_MODE - 32); data->filler.blob1.val = d; data->filler.blob1.len = 2; data->filler.blob1.free = free; /* Attribute value */ d = malloc(sizeof(uint32_t)); if (d == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } *d = htonl(mode); data->filler.blob2.val = d; data->filler.blob2.len = 4; data->filler.blob2.free = free; } data->filler.func = nfs4_populate_open; data->filler.max_op = 3; data->filler.flags = flags; if (nfs4_lookup_path_async(nfs, data, nfs4_open_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } int nfs4_open_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; uint32_t m; data = init_cb_data_split_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; /* O_TRUNC is only valid for O_RDWR or O_WRONLY */ if (flags & O_TRUNC && !(flags & (O_RDWR|O_WRONLY))) { flags &= ~O_TRUNC; } /* Successful O_EXCL means the file is 0 size already. */ if (flags & O_EXCL) { flags &= ~O_TRUNC; } if (flags & O_TRUNC) { data->open_cb = nfs4_open_truncate_cb; data->filler.blob3.val = malloc(12); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } data->filler.blob3.free = free; memset(data->filler.blob3.val, 0, 12); } if (flags & O_EXCL) { data->open_cb = nfs4_open_chmod_cb; data->filler.blob3.val = malloc(4); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } data->filler.blob3.free = free; m = htonl(mode); memcpy(data->filler.blob3.val, &m, sizeof(uint32_t)); } return nfs4_open_async_internal(nfs, data, flags, mode); } int nfs4_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "cb data"); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; i = nfs4_op_putfh(nfs, &op[0], nfsfh); i += nfs4_op_getattr(nfs, &op[i], standard_attributes, 2); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_xstat64_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_close_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (res) { nfs_increment_seqid(nfs, res->status); } if (check_nfs4_error(nfs, status, data, res, "CLOSE")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } int nfs4_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[3]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "cb data"); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], nfsfh); i += nfs4_op_close(nfs, &op[i], nfsfh); data->filler.blob0.val = nfsfh; data->filler.blob0.free = (blob_free)nfs_free_nfsfh; memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_close_cb, &args, data) != 0) { data->filler.blob0.val = NULL; free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_pread_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; READ4resok *rres = NULL; struct nfsfh *nfsfh; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); nfsfh = data->filler.blob0.val; if (check_nfs4_error(nfs, status, data, res, "READ")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_READ, "READ")) < 0) { return; } rres = &res->resarray.resarray_val[i].nfs_resop4_u.opread.READ4res_u.resok4; if (data->rw_data.update_pos) { nfsfh->offset = data->rw_data.offset + rres->data.data_len; } data->cb(rres->data.data_len, nfs, rres->data.data_val, data->private_data); free_nfs4_cb_data(data); } int nfs4_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, size_t count, nfs_cb cb, void *private_data, int update_pos) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "cb data"); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->filler.blob0.val = nfsfh; data->filler.blob0.free = NULL; data->rw_data.offset = offset; data->rw_data.update_pos = update_pos; memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], nfsfh); i += nfs4_op_read(nfs, &op[i], nfsfh, offset, count); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_pread_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_symlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "SYMLINK")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } /* Takes object name as filler.data * blob0 as the target */ static int nfs4_populate_symlink(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; return nfs4_op_create(nfs, op, data->filler.data, NF4LNK, NULL, NULL, data->filler.blob0.val, 0); return 1; } int nfs4_symlink_async(struct nfs_context *nfs, const char *target, const char *linkname, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_split_path(nfs, linkname); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_symlink; data->filler.max_op = 1; data->filler.blob0.val = strdup(target); data->filler.blob0.free = free; if (nfs4_lookup_path_async(nfs, data, nfs4_symlink_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_readlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; READLINK4resok *rlresok; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "READLINK")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_READLINK, "READLINK")) < 0) { return; } rlresok = &res->resarray.resarray_val[i].nfs_resop4_u.opreadlink.READLINK4res_u.resok4; data->cb(0, nfs, rlresok->link.utf8string_val, data->private_data); free_nfs4_cb_data(data); } static int nfs4_populate_readlink(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; int i; i = nfs4_op_readlink(nfs, &op[0]); return i; } int nfs4_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_full_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_readlink; data->filler.max_op = 1; data->flags |= LOOKUP_FLAG_NO_FOLLOW; if (nfs4_lookup_path_async(nfs, data, nfs4_readlink_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_pwrite_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; WRITE4resok *wres = NULL; struct nfsfh *nfsfh; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); nfsfh = data->filler.blob0.val; if (check_nfs4_error(nfs, status, data, res, "WRITE")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_WRITE, "WRITE")) < 0) { return; } wres = &res->resarray.resarray_val[i].nfs_resop4_u.opwrite.WRITE4res_u.resok4; if (data->rw_data.update_pos) { nfsfh->offset = data->rw_data.offset + wres->count; } data->cb(wres->count, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } int nfs4_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, size_t count, const char *buf, nfs_cb cb, void *private_data, int update_pos) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "cb data"); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->filler.blob0.val = nfsfh; data->filler.blob0.free = NULL; data->rw_data.offset = offset; data->rw_data.update_pos = update_pos; memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], nfsfh); i += nfs4_op_write(nfs, &op[i], nfsfh, offset, count, buf); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_pwrite_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_write_append_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; GETATTR4resok *garesok = NULL; struct nfsfh *nfsfh; int i; uint64_t offset; char *buf; uint32_t count; struct nfs_stat_64 st; assert(rpc->magic == RPC_CONTEXT_MAGIC); nfsfh = data->filler.blob0.val; buf = data->filler.blob1.val; count = data->filler.blob1.len; if (check_nfs4_error(nfs, status, data, res, "GETATTR")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_GETATTR, "GETATTR")) < 0) { return; } garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4; if (garesok->obj_attributes.attr_vals.attrlist4_len < 8) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memset(&st, 0, sizeof(st)); nfs_parse_attributes(nfs, data, &st, garesok->obj_attributes.attr_vals.attrlist4_val, garesok->obj_attributes.attr_vals.attrlist4_len); offset = st.nfs_size; if (nfs4_pwrite_async_internal(nfs, nfsfh, offset, (size_t)count, buf, data->cb, data->private_data, 1) < 0) { free_nfs4_cb_data(data); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); return; } free_nfs4_cb_data(data); } int nfs4_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, const void *buf, nfs_cb cb, void *private_data) { if (nfsfh->is_append) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "cb data"); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->filler.blob0.val = nfsfh; data->filler.blob0.free = NULL; memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], nfsfh); i += nfs4_op_getattr(nfs, &op[i], standard_attributes, 2); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; data->filler.blob0.val = nfsfh; data->filler.blob0.free = NULL; data->filler.blob1.val = discard_const(buf); data->filler.blob1.len = (int)count; data->filler.blob1.free = NULL; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_write_append_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } return nfs4_pwrite_async_internal(nfs, nfsfh, nfsfh->offset, (size_t)count, buf, cb, private_data, 1); } int nfs4_create_async(struct nfs_context *nfs, const char *path, int flags, int mode, nfs_cb cb, void *private_data) { return nfs4_open_async(nfs, path, O_CREAT | flags, mode, cb, private_data); } int nfs4_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { return nfs4_remove_async(nfs, path, cb, private_data); } static void nfs4_link_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "LINK")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } static int nfs4_populate_link(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; struct nfsfh *nfsfh = data->filler.blob0.val; int i; i = nfs4_op_savefh(nfs, &op[0]); i += nfs4_op_putfh(nfs, &op[i], nfsfh); i += nfs4_op_link(nfs, &op[i], data->filler.data); return i; } static void nfs4_link_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; GETFH4resok *gfhresok; int i; struct nfsfh *fh; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "LINK")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_GETFH, "GETFH")) < 0) { return; } gfhresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; /* oldpath fh */ fh = malloc(sizeof(*fh)); if (fh == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "nfsfh"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memset(fh, 0 , sizeof(*fh)); data->filler.blob0.val = fh; data->filler.blob0.free = (blob_free)nfs_free_nfsfh; fh->fh.len = gfhresok->object.nfs_fh4_len; fh->fh.val = malloc(fh->fh.len); if (fh->fh.val == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "nfsfh"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memcpy(fh->fh.val, gfhresok->object.nfs_fh4_val, fh->fh.len); data->filler.func = nfs4_populate_link; data->filler.max_op = 3; free(data->path); data->path = data->filler.blob1.val; data->filler.blob1.val = NULL; data->filler.blob1.free = NULL; if (nfs4_lookup_path_async(nfs, data, nfs4_link_2_cb) < 0) { data->cb(-EFAULT, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } /* * filler.data is the name of the new object * blob0 is the filehandle for newpath parent directory. * blob1 is oldpath. */ int nfs4_link_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_split_path(nfs, newpath); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_getfh; data->filler.max_op = 1; /* oldpath */ data->filler.blob1.val = strdup(oldpath); if (data->filler.blob1.val == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } data->filler.blob1.free = free; if (nfs4_lookup_path_async(nfs, data, nfs4_link_1_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_rename_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "RENAME")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } static int nfs4_populate_rename(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; struct nfsfh *nfsfh = data->filler.blob0.val; int i; i = nfs4_op_savefh(nfs, &op[0]); i += nfs4_op_putfh(nfs, &op[i], nfsfh); i += nfs4_op_rename(nfs, &op[i], data->filler.data, data->filler.blob1.val); return i; } static void nfs4_rename_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; GETFH4resok *gfhresok; int i; struct nfsfh *fh; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "RENAME")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_GETFH, "GETFH")) < 0) { return; } gfhresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; /* newpath fh */ fh = malloc(sizeof(*fh)); if (fh == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "nfsfh"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memset(fh, 0 , sizeof(*fh)); data->filler.blob0.val = fh; data->filler.blob0.free = (blob_free)nfs_free_nfsfh; fh->fh.len = gfhresok->object.nfs_fh4_len; fh->fh.val = malloc(fh->fh.len); if (fh->fh.val == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "nfsfh"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memcpy(fh->fh.val, gfhresok->object.nfs_fh4_val, fh->fh.len); data->filler.blob1.val = data->filler.data; data->filler.blob1.free = free; data->filler.data = NULL; /* Update path and data to point to the old path/name */ free(data->path); data->path = nfs4_resolve_path(nfs, data->filler.blob2.val); if (data->path == NULL) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } data_split_path(data); data->filler.func = nfs4_populate_rename; data->filler.max_op = 3; if (nfs4_lookup_path_async(nfs, data, nfs4_rename_2_cb) < 0) { nfs_set_error(nfs, "Out of memory."); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } /* * blob0 is the filehandle for newpath parent directory. * blob1 is the new name * blob2 is oldpath. */ int nfs4_rename_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_split_path(nfs, newpath); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_getfh; data->filler.max_op = 1; /* oldpath */ data->filler.blob2.val = strdup(oldpath); if (data->filler.blob2.val == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } data->filler.blob2.free = free; if (nfs4_lookup_path_async(nfs, data, nfs4_rename_1_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_mknod_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "MKNOD")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } static int nfs4_populate_mknod(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; uint32_t mode, *ptr; int dev; /* Strip off the file type before we marshall it */ ptr = (void *)data->filler.blob1.val; mode = *ptr; *ptr = htonl(mode & ~S_IFMT); dev = data->filler.blob2.len; switch (mode & S_IFMT) { case S_IFBLK: return nfs4_op_create(nfs, op, data->filler.data, NF4BLK, &data->filler.blob0, &data->filler.blob1, NULL, dev); case S_IFCHR: return nfs4_op_create(nfs, op, data->filler.data, NF4CHR, &data->filler.blob0, &data->filler.blob1, NULL, dev); } return 1; } /* Takes object name as filler.data * blob0 as attribute mask * blob1 as attribute value * blob2.len as dev */ int nfs4_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; uint32_t *u32ptr; switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: break; default: nfs_set_error(nfs, "Invalid file type for " "MKNOD call"); return -1; } data = init_cb_data_split_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_mknod; data->filler.max_op = 1; /* attribute mask */ u32ptr = malloc(2 * sizeof(uint32_t)); if (u32ptr == NULL) { nfs_set_error(nfs, "Out of memory allocating bitmap"); return 0; } u32ptr[0] = 0; u32ptr[1] = 1 << (FATTR4_MODE - 32); data->filler.blob0.len = 2; data->filler.blob0.val = u32ptr; data->filler.blob0.free = free; /* attribute values */ u32ptr = malloc(1 * sizeof(uint32_t)); if (u32ptr == NULL) { nfs_set_error(nfs, "Out of memory allocating attributes"); free_nfs4_cb_data(data); return -1; } u32ptr[0] = mode; data->filler.blob1.len = 4; data->filler.blob1.val = u32ptr; data->filler.blob1.free = free; data->filler.blob2.len = dev; if (nfs4_lookup_path_async(nfs, data, nfs4_mknod_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_parse_readdir(struct nfs_context *nfs, struct nfs4_cb_data *data, READDIR4resok *res); static void nfs4_opendir_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; READDIR4resok *rdresok; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "READDIR")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_READDIR, "READDIR")) < 0) { return; } rdresok = &res->resarray.resarray_val[i].nfs_resop4_u.opreaddir.READDIR4res_u.resok4; nfs4_parse_readdir(nfs, data, rdresok); } static void nfs4_opendir_continue(struct nfs_context *nfs, struct nfs4_cb_data *data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfsfh *fh = data->filler.blob0.val; uint64_t cookie; int i; memcpy(&cookie, data->filler.blob2.val, sizeof(uint64_t)); memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_readdir(nfs, &op[i], cookie); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_opendir_2_cb, &args, data) != 0) { nfs_set_error(nfs, "Failed to queue READDIR command. %s", nfs_get_error(nfs)); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } static void nfs4_parse_readdir(struct nfs_context *nfs, struct nfs4_cb_data *data, READDIR4resok *res) { struct nfsdir *nfsdir = data->filler.blob1.val; struct entry4 *e; e = res->reply.entries; while (e) { struct nfsdirent *nfsdirent; struct nfs_stat_64 st; memcpy(data->filler.blob2.val, &e->cookie, sizeof(uint64_t)); nfsdirent = malloc(sizeof(struct nfsdirent)); if (nfsdirent == NULL) { nfs_set_error(nfs, "Out of memory."); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } nfsdirent->name = strdup(e->name.utf8string_val); if (nfsdirent->name == NULL) { nfs_set_error(nfs, "Out of memory."); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); free(nfsdirent); return; } memset(&st, 0, sizeof(st)); if (nfs_parse_attributes(nfs, data, &st, e->attrs.attr_vals.attrlist4_val, e->attrs.attr_vals.attrlist4_len) < 0) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); free(nfsdirent->name); free(nfsdirent); return; } nfsdirent->mode = (uint32_t)st.nfs_mode; switch (st.nfs_mode & S_IFMT) { case S_IFREG: nfsdirent->type = NF4REG; break; case S_IFDIR: nfsdirent->type = NF4DIR; break; case S_IFBLK: nfsdirent->type = NF4BLK; break; case S_IFCHR: nfsdirent->type = NF4CHR; break; case S_IFLNK: nfsdirent->type = NF4LNK; break; case S_IFSOCK: nfsdirent->type = NF4SOCK; break; case S_IFIFO: nfsdirent->type = NF4FIFO; break; } nfsdirent->size = st.nfs_size; nfsdirent->atime.tv_sec = (long)st.nfs_atime; nfsdirent->atime.tv_usec = (long)(st.nfs_atime_nsec/1000); nfsdirent->atime_nsec = (uint32_t)st.nfs_atime_nsec; nfsdirent->mtime.tv_sec = (long)st.nfs_mtime; nfsdirent->mtime.tv_usec = (long)(st.nfs_mtime_nsec/1000); nfsdirent->mtime_nsec = (uint32_t)st.nfs_mtime_nsec; nfsdirent->ctime.tv_sec = (long)st.nfs_ctime; nfsdirent->ctime.tv_usec = (long)(st.nfs_ctime_nsec/1000); nfsdirent->ctime_nsec = (uint32_t)st.nfs_ctime_nsec; nfsdirent->uid = (uint32_t)st.nfs_uid; nfsdirent->gid = (uint32_t)st.nfs_gid; nfsdirent->nlink = (uint32_t)st.nfs_nlink; nfsdirent->dev = st.nfs_dev; nfsdirent->rdev = st.nfs_rdev; nfsdirent->blksize = NFS_BLKSIZE; nfsdirent->blocks = st.nfs_blocks; nfsdirent->used = st.nfs_used; nfsdirent->next = nfsdir->entries; nfsdir->entries = nfsdirent; e = e->nextentry; } if (res->reply.eof == 0) { nfs4_opendir_continue(nfs, data); return; } nfsdir->current = nfsdir->entries; data->filler.blob1.val = NULL; data->cb(0, nfs, nfsdir, data->private_data); free_nfs4_cb_data(data); } static void nfs4_opendir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; struct nfsfh *fh; GETFH4resok *gresok; READDIR4resok *rdresok; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "READDIR")) { return; } /* Parse GetFH */ if ((i = nfs4_find_op(nfs, data, res, OP_GETFH, "GETFH")) < 0) { return; } gresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; fh = malloc(sizeof(*fh)); if (fh == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "nfsfh"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memset(fh, 0 , sizeof(*fh)); data->filler.blob0.val = fh; data->filler.blob0.free = (blob_free)nfs_free_nfsfh; fh->fh.len = gresok->object.nfs_fh4_len; fh->fh.val = malloc(fh->fh.len); if (fh->fh.val == NULL) { nfs_set_error(nfs, "Out of memory. Failed to allocate " "nfsfh"); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } memcpy(fh->fh.val, gresok->object.nfs_fh4_val, fh->fh.len); if ((i = nfs4_find_op(nfs, data, res, OP_READDIR, "READDIR")) < 0) { return; } rdresok = &res->resarray.resarray_val[i].nfs_resop4_u.opreaddir.READDIR4res_u.resok4; nfs4_parse_readdir(nfs, data, rdresok); } static int nfs4_populate_readdir(struct nfs4_cb_data *data, nfs_argop4 *op) { struct nfs_context *nfs = data->nfs; uint64_t cookie; int i; memcpy(&cookie, data->filler.blob2.val, sizeof(uint64_t)); i = nfs4_op_getfh(nfs, &op[0]); i += nfs4_op_readdir(nfs, &op[i], cookie); return i; } /* blob0 is the directory filehandle * blob1 is nfsdir * blob2 is the cookie */ int nfs4_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; struct nfsdir *nfsdir; data = init_cb_data_full_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_readdir; data->filler.max_op = 2; nfsdir = malloc(sizeof(struct nfsdir)); if (nfsdir == NULL) { free_nfs4_cb_data(data); nfs_set_error(nfs, "failed to allocate buffer for nfsdir"); return -1; } memset(nfsdir, 0, sizeof(struct nfsdir)); data->filler.blob1.val = nfsdir; data->filler.blob1.free = (blob_free)nfs_free_nfsdir; data->filler.blob2.val = malloc(sizeof(uint64_t)); if (data->filler.blob2.val == NULL) { free_nfs4_cb_data(data); nfs_set_error(nfs, "failed to allocate buffer for cookie"); return -1; } memset(data->filler.blob2.val, 0, sizeof(uint64_t)); data->filler.blob2.free = (blob_free)free; if (nfs4_lookup_path_async(nfs, data, nfs4_opendir_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_truncate_close_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (res) { nfs_increment_seqid(nfs, res->status); } if (check_nfs4_error(nfs, status, data, res, "CLOSE")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } static void nfs4_truncate_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *fh = data->filler.blob0.val; COMPOUND4res *res = command_data; COMPOUND4args args; nfs_argop4 op[4]; int i; if (check_nfs4_error(nfs, status, data, res, "OPEN")) { return; } i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_truncate(nfs, &op[i], fh, data->filler.blob3.val); i += nfs4_op_close(nfs, &op[i], fh); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_truncate_close_cb, &args, data) != 0) { /* Not much we can do but leak one fd on the server :( */ data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } /* * data.blob3.val is a 12 byte SETATTR buffer for length+update_mtime */ int nfs4_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_split_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->open_cb = nfs4_truncate_open_cb; data->filler.blob3.val = malloc(12); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } data->filler.blob3.free = free; memset(data->filler.blob3.val, 0, 12); length = nfs_hton64(length); memcpy(data->filler.blob3.val, &length, sizeof(uint64_t)); if (nfs4_open_async_internal(nfs, data, O_WRONLY, 0) < 0) { return -1; } return 0; } static void nfs4_fsync_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "FSYNC")) { return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } int nfs4_fsync_async(struct nfs_context *nfs, struct nfsfh *fh, nfs_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_commit(nfs, &op[i]); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_fsync_cb, &args, data) != 0) { data->filler.blob0.val = NULL; free_nfs4_cb_data(data); return -1; } return 0; } int nfs4_ftruncate_async(struct nfs_context *nfs, struct nfsfh *fh, uint64_t length, nfs_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->filler.blob3.val = malloc(12); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } data->filler.blob3.free = free; memset(data->filler.blob3.val, 0, 12); length = nfs_hton64(length); memcpy(data->filler.blob3.val, &length, sizeof(uint64_t)); memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_truncate(nfs, &op[i], fh, data->filler.blob3.val); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_fsync_cb, &args, data) != 0) { data->filler.blob0.val = NULL; free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_lseek_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; GETATTR4resok *garesok = NULL; struct nfsfh *fh = data->filler.blob0.val; struct nfs_stat_64 st; int64_t offset; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); memcpy(&offset, data->filler.blob1.val, sizeof(int64_t)); if (check_nfs4_error(nfs, status, data, res, "LSEEK")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_GETATTR, "GETATTR")) < 0) { return; } garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4; memset(&st, 0, sizeof(st)); nfs_parse_attributes(nfs, data, &st, garesok->obj_attributes.attr_vals.attrlist4_val, garesok->obj_attributes.attr_vals.attrlist4_len); if (offset < 0 && -offset > (int64_t)st.nfs_size) { nfs_set_error(nfs, "Negative offset for lseek(" "SEET_END)"); data->cb(-EINVAL, nfs, &fh->offset, data->private_data); } else { fh->offset = offset + st.nfs_size; data->cb(0, nfs, &fh->offset, data->private_data); } free_nfs4_cb_data(data); } /* blob0.val is nfsfh * blob1.val is offset */ int nfs4_lseek_async(struct nfs_context *nfs, struct nfsfh *fh, int64_t offset, int whence, nfs_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; if (whence == SEEK_SET) { if (offset < 0) { nfs_set_error(nfs, "Negative offset for lseek(" "SEET_SET)"); cb(-EINVAL, nfs, &fh->offset, private_data); } else { fh->offset = offset; cb(0, nfs, &fh->offset, private_data); } return 0; } if (whence == SEEK_CUR) { if (offset < 0 && fh->offset < (uint64_t)(-offset)) { nfs_set_error(nfs, "Negative offset for lseek(" "SEET_CUR)"); cb(-EINVAL, nfs, &fh->offset, private_data); } else { fh->offset += offset; cb(0, nfs, &fh->offset, private_data); } return 0; } data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->filler.blob0.val = fh; data->filler.blob0.free = NULL; data->filler.blob1.val = malloc(sizeof(uint64_t)); if (data->filler.blob1.val == NULL) { nfs_set_error(nfs, "Out of memory."); free_nfs4_cb_data(data); return -1; } memcpy(data->filler.blob1.val, &offset, sizeof(uint64_t)); i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_getattr(nfs, &op[i], standard_attributes, 2); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_lseek_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_lockf_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; LOCK4resok *lresok = NULL; LOCKU4res *lures = NULL; struct nfsfh *fh = data->filler.blob0.val; enum nfs4_lock_op cmd; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); cmd = data->filler.blob1.len; if (check_nfs4_error(nfs, status, data, res, "LOCKF")) { return; } switch (cmd) { case NFS4_F_LOCK: case NFS4_F_TLOCK: if ((i = nfs4_find_op(nfs, data, res, OP_LOCK, "LOCK")) < 0) { return; } lresok = &res->resarray.resarray_val[i].nfs_resop4_u.oplock.LOCK4res_u.resok4; nfs->has_lock_owner = 1; fh->lock_stateid.seqid = lresok->lock_stateid.seqid; memcpy(fh->lock_stateid.other, lresok->lock_stateid.other, 12); break; case NFS4_F_ULOCK: if ((i = nfs4_find_op(nfs, data, res, OP_LOCKU, "LOCKU")) < 0) { return; } lures = &res->resarray.resarray_val[i].nfs_resop4_u.oplocku; fh->lock_stateid.seqid = lures->LOCKU4res_u.lock_stateid.seqid; memcpy(fh->lock_stateid.other, lures->LOCKU4res_u.lock_stateid.other, 12); break; case NFS4_F_TEST: break; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } /* blob0.val is nfsfh * blob1.len is cmd */ int nfs4_lockf_async(struct nfs_context *nfs, struct nfsfh *fh, enum nfs4_lock_op cmd, uint64_t count, nfs_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->filler.blob0.val = fh; data->filler.blob0.free = NULL; data->filler.blob1.len = cmd; i = nfs4_op_putfh(nfs, &op[0], fh); switch (cmd) { case NFS4_F_LOCK: i += nfs4_op_lock(nfs, &op[i], fh, OP_LOCK, WRITEW_LT, 0, fh->offset, count); break; case NFS4_F_TLOCK: i += nfs4_op_lock(nfs, &op[i], fh, OP_LOCK, WRITE_LT, 0, fh->offset, count); break; case NFS4_F_ULOCK: i += nfs4_op_locku(nfs, &op[i], fh, WRITE_LT, fh->offset, count); break; case NFS4_F_TEST: i += nfs4_op_lockt(nfs, &op[i], fh, WRITEW_LT, fh->offset, count); break; } memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_lockf_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_fcntl_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; LOCK4resok *lresok = NULL; struct nfsfh *fh = data->filler.blob0.val; enum nfs4_fcntl_op cmd; struct nfs4_flock *fl; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); cmd = data->filler.blob1.len; if (check_nfs4_error(nfs, status, data, res, "FCNTL")) { return; } switch (cmd) { case NFS4_F_SETLK: case NFS4_F_SETLKW: fl = (struct nfs4_flock *)data->filler.blob1.val; switch (fl->l_type) { case F_RDLCK: case F_WRLCK: if ((i = nfs4_find_op(nfs, data, res, OP_LOCK, "LOCK")) < 0) { return; } lresok = &res->resarray.resarray_val[i].nfs_resop4_u.oplock.LOCK4res_u.resok4; nfs->has_lock_owner = 1; fh->lock_stateid.seqid = lresok->lock_stateid.seqid; memcpy(fh->lock_stateid.other, lresok->lock_stateid.other, 12); break; case F_UNLCK: if ((i = nfs4_find_op(nfs, data, res, OP_LOCKU, "UNLOCK")) < 0) { return; } break; } break; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } static int nfs4_fcntl_async_internal(struct nfs_context *nfs, struct nfsfh *fh, struct nfs4_cb_data *data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_flock *fl; enum nfs4_fcntl_op cmd; int i, lock_type; cmd = data->filler.blob1.len; i = nfs4_op_putfh(nfs, &op[0], fh); switch (cmd) { case NFS4_F_SETLK: case NFS4_F_SETLKW: fl = data->filler.blob1.val; switch (fl->l_type) { case F_RDLCK: lock_type = cmd == NFS4_F_SETLK ? READ_LT : READW_LT; i += nfs4_op_lock(nfs, &op[i], fh, OP_LOCK, lock_type, 0, fl->l_start, fl->l_len); break; case F_WRLCK: lock_type = cmd == NFS4_F_SETLK ? WRITE_LT : WRITEW_LT; i += nfs4_op_lock(nfs, &op[i], fh, OP_LOCK, lock_type, 0, fl->l_start, fl->l_len); break; case F_UNLCK: i += nfs4_op_locku(nfs, &op[i], fh, WRITE_LT, fl->l_start, fl->l_len); break; } break; } memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_fcntl_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_fcntl_stat_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *fh = data->filler.blob0.val; enum nfs4_fcntl_op cmd = data->filler.blob1.len; COMPOUND4res *res = command_data; GETATTR4resok *garesok; struct nfs4_flock *fl; struct nfs_stat_64 st; int i; if (check_nfs4_error(nfs, status, data, res, "STAT64")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_GETATTR, "GETATTR")) < 0) { return; } garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4; memset(&st, 0, sizeof(st)); if (nfs_parse_attributes(nfs, data, &st, garesok->obj_attributes.attr_vals.attrlist4_val, garesok->obj_attributes.attr_vals.attrlist4_len) < 0) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); } switch (cmd) { case NFS4_F_SETLK: case NFS4_F_SETLKW: fl = data->filler.blob1.val; fl->l_whence = SEEK_SET; fl->l_start = st.nfs_size + fl->l_start; if (nfs4_fcntl_async_internal(nfs, fh, data)) { data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); } } } /* blob0.val is nfsfh * blob1.len is cmd * blob1.val is arg */ int nfs4_fcntl_async(struct nfs_context *nfs, struct nfsfh *fh, enum nfs4_fcntl_op cmd, void *arg, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; struct nfs4_flock *fl; COMPOUND4args args; nfs_argop4 op[2]; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->filler.blob0.val = fh; data->filler.blob0.free = NULL; data->filler.blob1.len = cmd; data->filler.blob1.val = arg; data->filler.blob1.free = NULL; switch (cmd) { case NFS4_F_SETLK: case NFS4_F_SETLKW: fl = arg; switch (fl->l_whence) { case SEEK_SET: return nfs4_fcntl_async_internal(nfs, fh, data); case SEEK_CUR: fl->l_whence = SEEK_SET; fl->l_start = fh->offset + fl->l_start; return nfs4_fcntl_async_internal(nfs, fh, data); case SEEK_END: i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_getattr(nfs, &op[i], standard_attributes, 2); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_fcntl_stat_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } nfs_set_error(nfs, "fcntl: unknown fl->whence:%d\n", fl->l_whence); free_nfs4_cb_data(data); return -1; } nfs_set_error(nfs, "fcntl: unknown cmd:%d\n", cmd); free_nfs4_cb_data(data); return -1; } static int nfs_parse_statvfs(struct nfs_context *nfs, struct nfs4_cb_data *data, struct statvfs *svfs, const char *buf, int len) { uint64_t u64; uint32_t u32; svfs->f_bsize = NFS_BLKSIZE; svfs->f_frsize = NFS_BLKSIZE; #if !defined(__ANDROID__) svfs->f_flag = 0; #endif /* FSID * NFSv4 FSID is 2*64 bit but statvfs fsid is just an * unsigmed long. Mix the 2*64 bits and hope for the best. */ CHECK_GETATTR_BUF_SPACE(len, 16); memcpy(&u64, buf, 8); svfs->f_fsid = (unsigned long)nfs_ntoh64(u64); buf += 8; len -= 8; memcpy(&u64, buf, 8); svfs->f_fsid |= (unsigned long)nfs_ntoh64(u64); buf += 8; len -= 8; /* Files Avail */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); #if !defined(__ANDROID__) svfs->f_favail = (fsfilcnt_t)nfs_ntoh64(u64); #endif buf += 8; len -= 8; /* Files Free */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs->f_ffree = (fsfilcnt_t)nfs_ntoh64(u64); buf += 8; len -= 8; /* Files Total */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs->f_files = (fsfilcnt_t)nfs_ntoh64(u64); buf += 8; len -= 8; /* Max Name */ CHECK_GETATTR_BUF_SPACE(len, 4); memcpy(&u32, buf, 4); #if !defined(__ANDROID__) svfs->f_namemax = ntohl(u32); #endif buf += 4; len -= 4; /* Space Avail */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs->f_bavail = (fsblkcnt_t)(nfs_ntoh64(u64) / svfs->f_frsize); buf += 8; len -= 8; /* Space Free */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs->f_bfree = (fsblkcnt_t)(nfs_ntoh64(u64) / svfs->f_frsize); buf += 8; len -= 8; /* Space Total */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs->f_blocks = (fsblkcnt_t)(nfs_ntoh64(u64) / svfs->f_frsize); buf += 8; len -= 8; return 0; } static int nfs_parse_statvfs64(struct nfs_context *nfs, struct nfs4_cb_data *data, struct nfs_statvfs_64 *svfs64, const char *buf, int len) { uint64_t u64; uint32_t u32; svfs64->f_bsize = NFS_BLKSIZE; svfs64->f_frsize = NFS_BLKSIZE; svfs64->f_flag = 0; /* FSID * NFSv4 FSID is 2*64 bit but statvfs fsid is just an * unsigmed long. Mix the 2*64 bits and hope for the best. */ CHECK_GETATTR_BUF_SPACE(len, 16); memcpy(&u64, buf, 8); svfs64->f_fsid = nfs_ntoh64(u64); buf += 8; len -= 8; memcpy(&u64, buf, 8); svfs64->f_fsid |= nfs_ntoh64(u64); buf += 8; len -= 8; /* Files Avail */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs64->f_favail = nfs_ntoh64(u64); buf += 8; len -= 8; /* Files Free */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs64->f_ffree = nfs_ntoh64(u64); buf += 8; len -= 8; /* Files Total */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs64->f_files = nfs_ntoh64(u64); buf += 8; len -= 8; /* Max Name */ CHECK_GETATTR_BUF_SPACE(len, 4); memcpy(&u32, buf, 4); svfs64->f_namemax = ntohl(u32); buf += 4; len -= 4; /* Space Avail */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs64->f_bavail = nfs_ntoh64(u64) / svfs64->f_frsize; buf += 8; len -= 8; /* Space Free */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs64->f_bfree = nfs_ntoh64(u64) / svfs64->f_frsize; buf += 8; len -= 8; /* Space Total */ CHECK_GETATTR_BUF_SPACE(len, 8); memcpy(&u64, buf, 8); svfs64->f_blocks = nfs_ntoh64(u64) / svfs64->f_frsize; buf += 8; len -= 8; return 0; } static void nfs4_statvfs_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; GETATTR4resok *garesok; struct statvfs svfs; struct nfs_statvfs_64 svfs64; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "STATVFS")) { return; } memset(&svfs, 0, sizeof(svfs)); memset(&svfs64, 0, sizeof(svfs64)); if ((i = nfs4_find_op(nfs, data, res, OP_GETATTR, "GETATTR")) < 0) { return; } garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4; if (data->flags & LOOKUP_FLAG_IS_STATVFS64) { /* statvfs64 */ if (nfs_parse_statvfs64(nfs, data, &svfs64, garesok->obj_attributes.attr_vals.attrlist4_val, garesok->obj_attributes.attr_vals.attrlist4_len) < 0) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } data->cb(0, nfs, &svfs64, data->private_data); } else { /* statvfs */ if (nfs_parse_statvfs(nfs, data, &svfs, garesok->obj_attributes.attr_vals.attrlist4_val, garesok->obj_attributes.attr_vals.attrlist4_len) < 0) { data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } data->cb(0, nfs, &svfs, data->private_data); } free_nfs4_cb_data(data); } static int nfs4_statvfs_async_internal(struct nfs_context *nfs, const char *path, int is_statvfs64, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; COMPOUND4args args; struct nfsfh fh; nfs_argop4 op[2]; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; if (is_statvfs64) { data->flags |= LOOKUP_FLAG_IS_STATVFS64; } fh.fh.len = nfs->rootfh.len; fh.fh.val = nfs->rootfh.val; i = nfs4_op_putfh(nfs, &op[0], &fh); i += nfs4_op_getattr(nfs, &op[i], statvfs_attributes, 2); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_statvfs_cb, &args, data) != 0) { free_nfs4_cb_data(data); return -1; } return 0; } int nfs4_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { return nfs4_statvfs_async_internal(nfs, path, 0, cb, private_data); } int nfs4_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { return nfs4_statvfs_async_internal(nfs, path, 1, cb, private_data); } static void nfs4_chmod_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *fh = data->filler.blob0.val; COMPOUND4res *res = command_data; COMPOUND4args args; nfs_argop4 op[4]; int i; if (check_nfs4_error(nfs, status, data, res, "OPEN")) { return; } i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_chmod(nfs, &op[i], fh, data->filler.blob3.val); i += nfs4_op_close(nfs, &op[i], fh); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_close_cb, &args, data) != 0) { /* Not much we can do but leak one fd on the server :( */ data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } int nfs4_chmod_async_internal(struct nfs_context *nfs, const char *path, int no_follow, int mode, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; uint32_t m; data = init_cb_data_split_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->open_cb = nfs4_chmod_open_cb; if (no_follow) { data->flags |= LOOKUP_FLAG_NO_FOLLOW; } data->filler.blob3.val = malloc(sizeof(uint32_t)); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } data->filler.blob3.free = free; m = htonl(mode); memcpy(data->filler.blob3.val, &m, sizeof(uint32_t)); if (nfs4_open_async_internal(nfs, data, O_WRONLY, 0) < 0) { return -1; } return 0; } int nfs4_fchmod_async(struct nfs_context *nfs, struct nfsfh *fh, int mode, nfs_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; uint32_t m; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; data->filler.blob3.val = malloc(sizeof(uint32_t)); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); free_nfs4_cb_data(data); return -1; } data->filler.blob3.free = free; m = htonl(mode); memcpy(data->filler.blob3.val, &m, sizeof(uint32_t)); memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_chmod(nfs, &op[i], fh, data->filler.blob3.val); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_fsync_cb, &args, data) != 0) { data->filler.blob0.val = NULL; free_nfs4_cb_data(data); return -1; } return 0; } #define CHOWN_BLOB_SIZE 64 static int nfs4_create_chown_buffer(struct nfs_context *nfs, struct nfs4_cb_data *data, int uid, int gid) { char *str; int i, l; uint32_t len; data->filler.blob3.val = malloc(CHOWN_BLOB_SIZE); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); return -1; } data->filler.blob3.free = free; memset(data->filler.blob3.val, 0, CHOWN_BLOB_SIZE); i = 0; str = data->filler.blob3.val; /* UID */ l = snprintf(&str[i + 4], CHOWN_BLOB_SIZE - 4 - i, "%d", uid); if (l < 0) { nfs_set_error(nfs, "snprintf failed"); return -1; } len = htonl(l); /* UID length prefix */ memcpy(&str[i], &len, sizeof(uint32_t)); i += 4 + l; i = (i + 3) & ~0x03; /* GID */ l = snprintf(&str[i + 4], CHOWN_BLOB_SIZE - 4 - i, "%d", gid); if (l < 0) { nfs_set_error(nfs, "snprintf failed"); return -1; } len = htonl(l); /* GID length prefix */ memcpy(&str[i], &len, sizeof(uint32_t)); i += 4 + l; i = (i + 3) & ~0x03; data->filler.blob3.len = i; return 0; } static void nfs4_chown_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *fh = data->filler.blob0.val; COMPOUND4res *res = command_data; COMPOUND4args args; nfs_argop4 op[4]; int i; if (check_nfs4_error(nfs, status, data, res, "OPEN")) { return; } i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_chown(nfs, &op[i], fh, data->filler.blob3.val, data->filler.blob3.len); i += nfs4_op_close(nfs, &op[i], fh); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_close_cb, &args, data) != 0) { /* Not much we can do but leak one fd on the server :( */ data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } int nfs4_chown_async_internal(struct nfs_context *nfs, const char *path, int no_follow, int uid, int gid, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; data = init_cb_data_split_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->open_cb = nfs4_chown_open_cb; if (no_follow) { data->flags |= LOOKUP_FLAG_NO_FOLLOW; } if (nfs4_create_chown_buffer(nfs, data, uid, gid) < 0) { free_nfs4_cb_data(data); return -1; } if (nfs4_open_async_internal(nfs, data, O_WRONLY, 0) < 0) { return -1; } return 0; } int nfs4_fchown_async(struct nfs_context *nfs, struct nfsfh *fh, int uid, int gid, nfs_cb cb, void *private_data) { COMPOUND4args args; nfs_argop4 op[2]; struct nfs4_cb_data *data; int i; data = malloc(sizeof(*data)); if (data == NULL) { nfs_set_error(nfs, "Out of memory."); return -1; } memset(data, 0, sizeof(*data)); data->nfs = nfs; data->cb = cb; data->private_data = private_data; if (nfs4_create_chown_buffer(nfs, data, uid, gid) < 0) { free_nfs4_cb_data(data); return -1; } memset(op, 0, sizeof(op)); i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_chown(nfs, &op[i], fh, data->filler.blob3.val, data->filler.blob3.len); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_fsync_cb, &args, data) != 0) { data->filler.blob0.val = NULL; free_nfs4_cb_data(data); return -1; } return 0; } static void nfs4_access_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; COMPOUND4res *res = command_data; ACCESS4resok *aresok; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (check_nfs4_error(nfs, status, data, res, "ACCESS")) { return; } if ((i = nfs4_find_op(nfs, data, res, OP_ACCESS, "ACCESS")) < 0) { return; } aresok = &res->resarray.resarray_val[i].nfs_resop4_u.opaccess.ACCESS4res_u.resok4; /* access2 */ if (data->filler.flags) { int mode = 0; if (aresok->access & ACCESS4_READ) { mode |= R_OK; } if (aresok->access & ACCESS4_MODIFY) { mode |= W_OK; } if (aresok->access & ACCESS4_EXECUTE) { mode |= X_OK; } data->cb(mode, nfs, NULL, data->private_data); free_nfs4_cb_data(data); return; } if (aresok->supported != aresok->access) { data->cb(-EACCES, nfs, NULL, data->private_data); free_nfs4_cb_data(data); return; } data->cb(0, nfs, NULL, data->private_data); free_nfs4_cb_data(data); } static int nfs4_access_internal(struct nfs_context *nfs, const char *path, int mode, int is_access2, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; uint32_t m; data = init_cb_data_full_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->filler.func = nfs4_populate_access; data->filler.max_op = 1; data->filler.flags = is_access2; data->filler.blob3.val = malloc(sizeof(uint32_t)); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); return -1; } data->filler.blob3.free = free; m = 0; if (mode & R_OK) { m |= ACCESS4_READ; } if (mode & W_OK) { m |= ACCESS4_MODIFY; } if (mode & X_OK) { m |= ACCESS4_EXECUTE; } memcpy(data->filler.blob3.val, &m, sizeof(uint32_t)); if (nfs4_lookup_path_async(nfs, data, nfs4_access_cb) < 0) { free_nfs4_cb_data(data); return -1; } return 0; } int nfs4_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { return nfs4_access_internal(nfs, path, mode, 0, cb, private_data); } int nfs4_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { return nfs4_access_internal(nfs, path, R_OK|W_OK|X_OK, 1, cb, private_data); } static void nfs4_utimes_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs4_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsfh *fh = data->filler.blob0.val; COMPOUND4res *res = command_data; COMPOUND4args args; nfs_argop4 op[4]; int i; if (check_nfs4_error(nfs, status, data, res, "OPEN")) { return; } i = nfs4_op_putfh(nfs, &op[0], fh); i += nfs4_op_utimes(nfs, &op[i], fh, data->filler.blob3.val, data->filler.blob3.len); i += nfs4_op_close(nfs, &op[i], fh); memset(&args, 0, sizeof(args)); args.argarray.argarray_len = i; args.argarray.argarray_val = op; if (rpc_nfs4_compound_async(nfs->rpc, nfs4_close_cb, &args, data) != 0) { /* Not much we can do but leak one fd on the server :( */ data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); free_nfs4_cb_data(data); return; } } int nfs4_utimes_async_internal(struct nfs_context *nfs, const char *path, int no_follow, struct timeval *times, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; char *buf; uint32_t u32; uint64_t u64; data = init_cb_data_split_path(nfs, path); if (data == NULL) { return -1; } data->cb = cb; data->private_data = private_data; data->open_cb = nfs4_utimes_open_cb; if (no_follow) { data->flags |= LOOKUP_FLAG_NO_FOLLOW; } data->filler.blob3.len = 2 * (4 + 8 + 4); buf = data->filler.blob3.val = malloc(data->filler.blob3.len); if (data->filler.blob3.val == NULL) { nfs_set_error(nfs, "Out of memory"); return -1; } data->filler.blob3.free = free; /* atime */ u32 = htonl(SET_TO_CLIENT_TIME4); memcpy(buf, &u32, sizeof(uint32_t)); u64 = nfs_hton64(times[0].tv_sec); memcpy(buf + 4, &u64, sizeof(uint64_t)); u32 = htonl(times[0].tv_usec * 1000); memcpy(buf + 12, &u32, sizeof(uint32_t)); buf += 16; /* mtime */ u32 = htonl(SET_TO_CLIENT_TIME4); memcpy(buf, &u32, sizeof(uint32_t)); u64 = nfs_hton64(times[1].tv_sec); memcpy(buf + 4, &u64, sizeof(uint64_t)); u32 = htonl(times[1].tv_usec * 1000); memcpy(buf + 12, &u32, sizeof(uint32_t)); if (nfs4_open_async_internal(nfs, data, O_WRONLY, 0) < 0) { return -1; } return 0; } int nfs4_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *times, nfs_cb cb, void *private_data) { struct timeval new_times[2]; new_times[0].tv_sec = times->actime; new_times[0].tv_usec = 0; new_times[1].tv_sec = times->modtime; new_times[1].tv_usec = 0; return nfs4_utimes_async_internal(nfs, path, 0, new_times, cb, private_data); } libnfs-libnfs-4.0.0/lib/pdu.c000066400000000000000000000420431343063627400157600ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #include #include #include #include #include #include "slist.h" #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" void rpc_reset_queue(struct rpc_queue *q) { q->head = NULL; q->tail = NULL; } /* * Push to the tail end of the queue */ void rpc_enqueue(struct rpc_queue *q, struct rpc_pdu *pdu) { if (q->head == NULL) q->head = pdu; else q->tail->next = pdu; q->tail = pdu; pdu->next = NULL; } /* * Push to the front/head of the queue */ void rpc_return_to_queue(struct rpc_queue *q, struct rpc_pdu *pdu) { pdu->next = q->head; q->head = pdu; if (q->tail == NULL) q->tail = pdu; } unsigned int rpc_hash_xid(uint32_t xid) { return (xid * 7919) % HASHES; } #define PAD_TO_8_BYTES(x) ((x + 0x07) & ~0x07) static struct rpc_pdu *rpc_allocate_reply_pdu(struct rpc_context *rpc, struct rpc_msg *res, size_t alloc_hint) { struct rpc_pdu *pdu; assert(rpc->magic == RPC_CONTEXT_MAGIC); pdu = malloc(sizeof(struct rpc_pdu)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory: Failed to allocate pdu structure"); return NULL; } memset(pdu, 0, sizeof(struct rpc_pdu)); pdu->flags = PDU_DISCARD_AFTER_SENDING; pdu->xid = 0; pdu->cb = NULL; pdu->private_data = NULL; pdu->zdr_decode_fn = NULL; pdu->zdr_decode_bufsize = 0; pdu->outdata.data = malloc(ZDR_ENCODEBUF_MINSIZE + alloc_hint); if (pdu->outdata.data == NULL) { rpc_set_error(rpc, "Out of memory: Failed to allocate encode buffer"); free(pdu); return NULL; } zdrmem_create(&pdu->zdr, pdu->outdata.data, ZDR_ENCODEBUF_MINSIZE + alloc_hint, ZDR_ENCODE); if (rpc->is_udp == 0) { zdr_setpos(&pdu->zdr, 4); /* skip past the record marker */ } if (zdr_replymsg(rpc, &pdu->zdr, res) == 0) { rpc_set_error(rpc, "zdr_replymsg failed with %s", rpc_get_error(rpc)); zdr_destroy(&pdu->zdr); free(pdu->outdata.data); free(pdu); return NULL; } return pdu; } struct rpc_pdu *rpc_allocate_pdu2(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_decode_bufsize, size_t alloc_hint) { struct rpc_pdu *pdu; struct rpc_msg msg; int pdu_size; assert(rpc->magic == RPC_CONTEXT_MAGIC); /* Since we already know how much buffer we need for the decoding * we can just piggyback in the same alloc as for the pdu. */ pdu_size = PAD_TO_8_BYTES(sizeof(struct rpc_pdu)); pdu_size += PAD_TO_8_BYTES(zdr_decode_bufsize); pdu = malloc(pdu_size); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory: Failed to allocate pdu structure"); return NULL; } memset(pdu, 0, pdu_size); pdu->xid = rpc->xid++; pdu->cb = cb; pdu->private_data = private_data; pdu->zdr_decode_fn = zdr_decode_fn; pdu->zdr_decode_bufsize = zdr_decode_bufsize; pdu->outdata.data = malloc(ZDR_ENCODEBUF_MINSIZE + alloc_hint); if (pdu->outdata.data == NULL) { rpc_set_error(rpc, "Out of memory: Failed to allocate encode buffer"); free(pdu); return NULL; } zdrmem_create(&pdu->zdr, pdu->outdata.data, ZDR_ENCODEBUF_MINSIZE + alloc_hint, ZDR_ENCODE); if (rpc->is_udp == 0) { zdr_setpos(&pdu->zdr, 4); /* skip past the record marker */ } memset(&msg, 0, sizeof(struct rpc_msg)); msg.xid = pdu->xid; msg.direction = CALL; msg.body.cbody.rpcvers = RPC_MSG_VERSION; msg.body.cbody.prog = program; msg.body.cbody.vers = version; msg.body.cbody.proc = procedure; msg.body.cbody.cred = rpc->auth->ah_cred; msg.body.cbody.verf = rpc->auth->ah_verf; if (zdr_callmsg(rpc, &pdu->zdr, &msg) == 0) { rpc_set_error(rpc, "zdr_callmsg failed with %s", rpc_get_error(rpc)); zdr_destroy(&pdu->zdr); free(pdu->outdata.data); free(pdu); return NULL; } return pdu; } struct rpc_pdu *rpc_allocate_pdu(struct rpc_context *rpc, int program, int version, int procedure, rpc_cb cb, void *private_data, zdrproc_t zdr_decode_fn, int zdr_decode_bufsize) { return rpc_allocate_pdu2(rpc, program, version, procedure, cb, private_data, zdr_decode_fn, zdr_decode_bufsize, 0); } void rpc_free_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu) { assert(rpc->magic == RPC_CONTEXT_MAGIC); free(pdu->outdata.data); if (pdu->zdr_decode_buf != NULL) { zdr_free(pdu->zdr_decode_fn, pdu->zdr_decode_buf); } zdr_destroy(&pdu->zdr); free(pdu); } void rpc_set_next_xid(struct rpc_context *rpc, uint32_t xid) { rpc->xid = xid; } int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu) { int size, recordmarker; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->timeout > 0) { pdu->timeout = rpc_current_time() + rpc->timeout; #ifndef HAVE_CLOCK_GETTIME /* If we do not have GETTIME we fallback to time() which * has 1s granularity for its timestamps. * We thus need to bump the timeout by 1000ms * so that the PDU will timeout within 1.0 - 2.0 seconds. * Otherwise setting a 1s timeout would trigger within * 0.001 - 1.0s. */ pdu->timeout += 1000; #endif } else { pdu->timeout = 0; } size = zdr_getpos(&pdu->zdr); /* for udp we dont queue, we just send it straight away */ if (rpc->is_udp != 0) { unsigned int hash; // XXX add a rpc->udp_dest_sock_size and get rid of sys/socket.h and netinet/in.h if (sendto(rpc->fd, pdu->zdr.buf, size, MSG_DONTWAIT, (struct sockaddr *)&rpc->udp_dest, sizeof(rpc->udp_dest)) < 0) { rpc_set_error(rpc, "Sendto failed with errno %s", strerror(errno)); rpc_free_pdu(rpc, pdu); return -1; } hash = rpc_hash_xid(pdu->xid); rpc_enqueue(&rpc->waitpdu[hash], pdu); rpc->waitpdu_len++; return 0; } /* write recordmarker */ zdr_setpos(&pdu->zdr, 0); recordmarker = (size - 4) | 0x80000000; zdr_int(&pdu->zdr, &recordmarker); pdu->outdata.size = size; rpc_enqueue(&rpc->outqueue, pdu); return 0; } uint32_t rpc_get_pdu_size(char *buf) { uint32_t size; size = ntohl(*(uint32_t *)(void *)buf); return (size & 0x7fffffff) + 4; } static int rpc_process_reply(struct rpc_context *rpc, struct rpc_pdu *pdu, ZDR *zdr) { struct rpc_msg msg; assert(rpc->magic == RPC_CONTEXT_MAGIC); memset(&msg, 0, sizeof(struct rpc_msg)); msg.body.rbody.reply.areply.verf = _null_auth; if (pdu->zdr_decode_bufsize > 0) { pdu->zdr_decode_buf = (char *)pdu + PAD_TO_8_BYTES(sizeof(struct rpc_pdu)); } msg.body.rbody.reply.areply.reply_data.results.where = pdu->zdr_decode_buf; msg.body.rbody.reply.areply.reply_data.results.proc = pdu->zdr_decode_fn; if (zdr_replymsg(rpc, zdr, &msg) == 0) { rpc_set_error(rpc, "zdr_replymsg failed in rpc_process_reply: " "%s", rpc_get_error(rpc)); pdu->cb(rpc, RPC_STATUS_ERROR, "Message rejected by server", pdu->private_data); if (pdu->zdr_decode_buf != NULL) { pdu->zdr_decode_buf = NULL; } return 0; } if (msg.body.rbody.stat != MSG_ACCEPTED) { pdu->cb(rpc, RPC_STATUS_ERROR, "RPC Packet not accepted by the server", pdu->private_data); return 0; } switch (msg.body.rbody.reply.areply.stat) { case SUCCESS: pdu->cb(rpc, RPC_STATUS_SUCCESS, pdu->zdr_decode_buf, pdu->private_data); break; case PROG_UNAVAIL: pdu->cb(rpc, RPC_STATUS_ERROR, "Server responded: Program not available", pdu->private_data); break; case PROG_MISMATCH: pdu->cb(rpc, RPC_STATUS_ERROR, "Server responded: Program version mismatch", pdu->private_data); break; case PROC_UNAVAIL: pdu->cb(rpc, RPC_STATUS_ERROR, "Server responded: Procedure not available", pdu->private_data); break; case GARBAGE_ARGS: pdu->cb(rpc, RPC_STATUS_ERROR, "Server responded: Garbage arguments", pdu->private_data); break; case SYSTEM_ERR: pdu->cb(rpc, RPC_STATUS_ERROR, "Server responded: System Error", pdu->private_data); break; default: pdu->cb(rpc, RPC_STATUS_ERROR, "Unknown rpc response from server", pdu->private_data); break; } return 0; } static int rpc_send_error_reply(struct rpc_context *rpc, struct rpc_msg *call, enum accept_stat err, int min_vers, int max_vers) { struct rpc_pdu *pdu; struct rpc_msg res; assert(rpc->magic == RPC_CONTEXT_MAGIC); memset(&res, 0, sizeof(struct rpc_msg)); res.xid = call->xid; res.direction = REPLY; res.body.rbody.stat = MSG_ACCEPTED; res.body.rbody.reply.areply.reply_data.mismatch_info.low = min_vers; res.body.rbody.reply.areply.reply_data.mismatch_info.high = max_vers; res.body.rbody.reply.areply.verf = _null_auth; res.body.rbody.reply.areply.stat = err; if (rpc->is_udp) { /* send the reply back to the client */ memcpy(&rpc->udp_dest, &rpc->udp_src, sizeof(rpc->udp_dest)); } pdu = rpc_allocate_reply_pdu(rpc, &res, 0); if (pdu == NULL) { rpc_set_error(rpc, "Failed to send error_reply: %s", rpc_get_error(rpc)); return -1; } rpc_queue_pdu(rpc, pdu); return 0; } int rpc_send_reply(struct rpc_context *rpc, struct rpc_msg *call, void *reply, zdrproc_t encode_fn, int alloc_hint) { struct rpc_pdu *pdu; struct rpc_msg res; assert(rpc->magic == RPC_CONTEXT_MAGIC); memset(&res, 0, sizeof(struct rpc_msg)); res.xid = call->xid; res.direction = REPLY; res.body.rbody.stat = MSG_ACCEPTED; res.body.rbody.reply.areply.verf = _null_auth; res.body.rbody.reply.areply.stat = SUCCESS; res.body.rbody.reply.areply.reply_data.results.where = reply; res.body.rbody.reply.areply.reply_data.results.proc = encode_fn; if (rpc->is_udp) { /* send the reply back to the client */ memcpy(&rpc->udp_dest, &rpc->udp_src, sizeof(rpc->udp_dest)); } pdu = rpc_allocate_reply_pdu(rpc, &res, alloc_hint); if (pdu == NULL) { rpc_set_error(rpc, "Failed to send error_reply: %s", rpc_get_error(rpc)); return -1; } rpc_queue_pdu(rpc, pdu); return 0; } static int rpc_process_call(struct rpc_context *rpc, ZDR *zdr) { struct rpc_msg call; struct rpc_endpoint *endpoint; int i, min_version = 0, max_version = 0, found_program = 0; assert(rpc->magic == RPC_CONTEXT_MAGIC); memset(&call, 0, sizeof(struct rpc_msg)); if (zdr_callmsg(rpc, zdr, &call) == 0) { rpc_set_error(rpc, "Failed to decode CALL message. %s", rpc_get_error(rpc)); return rpc_send_error_reply(rpc, &call, GARBAGE_ARGS, 0, 0); } for (endpoint = rpc->endpoints; endpoint; endpoint = endpoint->next) { if (call.body.cbody.prog == endpoint->program) { if (!found_program) { min_version = max_version = endpoint->version; } if (endpoint->version < min_version) { min_version = endpoint->version; } if (endpoint->version > max_version) { max_version = endpoint->version; } found_program = 1; if (call.body.cbody.vers == endpoint->version) { break; } } } if (endpoint == NULL) { rpc_set_error(rpc, "No endpoint found for CALL " "program:0x%08x version:%d\n", call.body.cbody.prog, call.body.cbody.vers); if (!found_program) { return rpc_send_error_reply(rpc, &call, PROG_UNAVAIL, 0, 0); } return rpc_send_error_reply(rpc, &call, PROG_MISMATCH, min_version, max_version); } for (i = 0; i < endpoint->num_procs; i++) { if (endpoint->procs[i].proc == call.body.cbody.proc) { if (endpoint->procs[i].decode_buf_size) { call.body.cbody.args = zdr_malloc(zdr, endpoint->procs[i].decode_buf_size); } if (!endpoint->procs[i].decode_fn(zdr, call.body.cbody.args)) { rpc_set_error(rpc, "Failed to unmarshall " "call payload"); return rpc_send_error_reply(rpc, &call, GARBAGE_ARGS, 0 ,0); } return endpoint->procs[i].func(rpc, &call); } } return rpc_send_error_reply(rpc, &call, PROC_UNAVAIL, 0 ,0); } int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size) { struct rpc_pdu *pdu, *prev_pdu; struct rpc_queue *q; ZDR zdr; int pos, recordmarker = 0; unsigned int hash; uint32_t xid; char *reasbuf = NULL; assert(rpc->magic == RPC_CONTEXT_MAGIC); memset(&zdr, 0, sizeof(ZDR)); zdrmem_create(&zdr, buf, size, ZDR_DECODE); if (rpc->is_udp == 0) { if (zdr_int(&zdr, &recordmarker) == 0) { rpc_set_error(rpc, "zdr_int reading recordmarker failed"); zdr_destroy(&zdr); return -1; } if (!(recordmarker&0x80000000)) { zdr_destroy(&zdr); if (rpc_add_fragment(rpc, buf+4, size-4) != 0) { rpc_set_error(rpc, "Failed to queue fragment for reassembly."); return -1; } return 0; } } /* reassembly */ if (recordmarker != 0 && rpc->fragments != NULL) { struct rpc_fragment *fragment; uint32_t total = size - 4; char *ptr; zdr_destroy(&zdr); for (fragment = rpc->fragments; fragment; fragment = fragment->next) { total += fragment->size; } reasbuf = malloc(total); if (reasbuf == NULL) { rpc_set_error(rpc, "Failed to reassemble PDU"); rpc_free_all_fragments(rpc); return -1; } ptr = reasbuf; for (fragment = rpc->fragments; fragment; fragment = fragment->next) { memcpy(ptr, fragment->data, fragment->size); ptr += fragment->size; } memcpy(ptr, buf + 4, size - 4); zdrmem_create(&zdr, reasbuf, total, ZDR_DECODE); rpc_free_all_fragments(rpc); } if (rpc->is_server_context) { int ret; ret = rpc_process_call(rpc, &zdr); zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return ret; } pos = zdr_getpos(&zdr); if (zdr_int(&zdr, (int *)&xid) == 0) { rpc_set_error(rpc, "zdr_int reading xid failed"); zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return -1; } zdr_setpos(&zdr, pos); /* Look up the transaction in a hash table of our requests */ hash = rpc_hash_xid(xid); q = &rpc->waitpdu[hash]; /* Follow the hash chain. Linear traverse singly-linked list, * but track previous entry for optimised removal */ prev_pdu = NULL; for (pdu=q->head; pdu; pdu=pdu->next) { if (pdu->xid != xid) { prev_pdu = pdu; continue; } if (rpc->is_udp == 0 || rpc->is_broadcast == 0) { /* Singly-linked but we track head and tail */ if (pdu == q->head) q->head = pdu->next; if (pdu == q->tail) q->tail = prev_pdu; if (prev_pdu != NULL) prev_pdu->next = pdu->next; rpc->waitpdu_len--; } if (rpc_process_reply(rpc, pdu, &zdr) != 0) { rpc_set_error(rpc, "rpc_procdess_reply failed"); } zdr_destroy(&zdr); if (rpc->is_udp == 0 || rpc->is_broadcast == 0) { rpc_free_pdu(rpc, pdu); } if (reasbuf != NULL) { free(reasbuf); } return 0; } zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return 0; } libnfs-libnfs-4.0.0/lib/socket.c000066400000000000000000000557531343063627400164740ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_NETINET_TCP_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_SYS_FILIO_H #include #endif #ifdef HAVE_SYS_SOCKIO_H #include #endif #include #include #include #include #include #include #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "slist.h" #ifdef WIN32 //has to be included after stdlib!! #include "win32_errnowrapper.h" #endif #ifndef MSG_NOSIGNAL #if (defined(__APPLE__) && defined(__MACH__)) #define MSG_NOSIGNAL 0 #endif #endif static int rpc_reconnect_requeue(struct rpc_context *rpc); static int create_socket(int domain, int type, int protocol) { #ifdef SOCK_CLOEXEC #ifdef __linux__ /* Linux-specific extension (since 2.6.27): set the close-on-exec flag on all sockets to avoid leaking file descriptors to child processes */ int fd = socket(domain, type|SOCK_CLOEXEC, protocol); if (fd >= 0 || errno != EINVAL) return fd; #endif #endif return socket(domain, type, protocol); } static int set_nonblocking(int fd) { int v = 0; #if defined(WIN32) u_long nonblocking=1; v = ioctl(fd, FIONBIO, &nonblocking); #else v = fcntl(fd, F_GETFL, 0); v = fcntl(fd, F_SETFL, v | O_NONBLOCK); #endif //FIXME return v; } static void set_nolinger(int fd) { struct linger lng; lng.l_onoff = 1; lng.l_linger = 0; setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&lng, sizeof(lng)); } static int set_bind_device(int fd, char *ifname) { int rc = 0; #ifdef HAVE_SO_BINDTODEVICE if (*ifname) { rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)); } #endif return rc; } #ifdef HAVE_NETINET_TCP_H static int set_tcp_sockopt(int sockfd, int optname, int value) { int level; #if defined(__FreeBSD__) || defined(__sun) || (defined(__APPLE__) && defined(__MACH__)) struct protoent *buf; if ((buf = getprotobyname("tcp")) != NULL) level = buf->p_proto; else return -1; #else level = SOL_TCP; #endif return setsockopt(sockfd, level, optname, (char *)&value, sizeof(value)); } #endif int rpc_get_fd(struct rpc_context *rpc) { assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->old_fd) { return rpc->old_fd; } return rpc->fd; } static int rpc_has_queue(struct rpc_queue *q) { return q->head != NULL; } int rpc_which_events(struct rpc_context *rpc) { int events; assert(rpc->magic == RPC_CONTEXT_MAGIC); events = rpc->is_connected ? POLLIN : POLLOUT; if (rpc->is_udp != 0) { /* for udp sockets we only wait for pollin */ return POLLIN; } if (rpc_has_queue(&rpc->outqueue)) { events |= POLLOUT; } return events; } static int rpc_write_to_socket(struct rpc_context *rpc) { int32_t count; struct rpc_pdu *pdu; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->fd == -1) { rpc_set_error(rpc, "trying to write but not connected"); return -1; } while ((pdu = rpc->outqueue.head) != NULL) { int64_t total; total = pdu->outdata.size; count = send(rpc->fd, pdu->outdata.data + pdu->written, (int)(total - pdu->written), MSG_NOSIGNAL); if (count == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return 0; } rpc_set_error(rpc, "Error when writing to socket :%s" "(%d)", strerror(errno), errno); return -1; } pdu->written += count; if (pdu->written == total) { unsigned int hash; rpc->outqueue.head = pdu->next; if (pdu->next == NULL) rpc->outqueue.tail = NULL; if (pdu->flags & PDU_DISCARD_AFTER_SENDING) { rpc_free_pdu(rpc, pdu); return 0; } hash = rpc_hash_xid(pdu->xid); rpc_enqueue(&rpc->waitpdu[hash], pdu); rpc->waitpdu_len++; } } return 0; } #define MAX_UDP_SIZE 65536 static int rpc_read_from_socket(struct rpc_context *rpc) { uint32_t pdu_size; ssize_t count; char *buf; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->is_udp) { socklen_t socklen = sizeof(rpc->udp_src); buf = malloc(MAX_UDP_SIZE); if (buf == NULL) { rpc_set_error(rpc, "Failed to malloc buffer for " "recvfrom"); return -1; } count = recvfrom(rpc->fd, buf, MAX_UDP_SIZE, MSG_DONTWAIT, (struct sockaddr *)&rpc->udp_src, &socklen); if (count == -1) { free(buf); if (errno == EINTR || errno == EAGAIN) { return 0; } rpc_set_error(rpc, "Failed recvfrom: %s", strerror(errno)); return -1; } if (rpc_process_pdu(rpc, buf, count) != 0) { rpc_set_error(rpc, "Invalid/garbage pdu received from " "server. Ignoring PDU"); free(buf); return -1; } free(buf); return 0; } do { /* Read record marker, * 4 bytes at the beginning of every pdu. */ if (rpc->inpos < 4) { buf = (void *)rpc->rm_buf; pdu_size = 4; } else { pdu_size = rpc_get_pdu_size((void *)&rpc->rm_buf); if (rpc->inbuf == NULL) { if (pdu_size > NFS_MAX_XFER_SIZE + 4096) { rpc_set_error(rpc, "Incoming PDU " "exceeds limit of %d " "bytes.", NFS_MAX_XFER_SIZE + 4096); return -1; } rpc->inbuf = malloc(pdu_size); if (rpc->inbuf == NULL) { rpc_set_error(rpc, "Failed to allocate " "buffer of %d bytes for " "pdu, errno:%d. Closing " "socket.", pdu_size, errno); return -1; } memcpy(rpc->inbuf, &rpc->rm_buf, 4); } buf = rpc->inbuf; } count = recv(rpc->fd, buf + rpc->inpos, pdu_size - rpc->inpos, MSG_DONTWAIT); if (count < 0) { if (errno == EINTR || errno == EAGAIN) { break; } rpc_set_error(rpc, "Read from socket failed, errno:%d. " "Closing socket.", errno); return -1; } if (count == 0) { /* remote side has closed the socket. Reconnect. */ return -1; } rpc->inpos += count; if (rpc->inpos == 4) { /* We have just read the header and there is likely * more data available */ continue; } if (rpc->inpos == pdu_size) { rpc->inbuf = NULL; rpc->inpos = 0; if (rpc_process_pdu(rpc, buf, pdu_size) != 0) { rpc_set_error(rpc, "Invalid/garbage pdu " "received from server. Closing " "socket"); free(buf); return -1; } free(buf); } } while (rpc->is_nonblocking && rpc->waitpdu_len > 0); return 0; } static void maybe_call_connect_cb(struct rpc_context *rpc, int status) { rpc_cb tmp_cb = rpc->connect_cb; if (rpc->connect_cb == NULL) { return; } rpc->connect_cb = NULL; tmp_cb(rpc, status, rpc->error_string, rpc->connect_data); } static void rpc_timeout_scan(struct rpc_context *rpc) { struct rpc_pdu *pdu; struct rpc_pdu *next_pdu; uint64_t t = rpc_current_time(); unsigned int i; for (pdu = rpc->outqueue.head; pdu; pdu = next_pdu) { next_pdu = pdu->next; if (pdu->timeout == 0) { /* no timeout for this pdu */ continue; } if (t < pdu->timeout) { /* not expired yet */ continue; } LIBNFS_LIST_REMOVE(&rpc->outqueue.head, pdu); if (!rpc->outqueue.head) { rpc->outqueue.tail = NULL; } rpc_set_error(rpc, "command timed out"); pdu->cb(rpc, RPC_STATUS_TIMEOUT, NULL, pdu->private_data); rpc_free_pdu(rpc, pdu); } for (i = 0; i < HASHES; i++) { struct rpc_queue *q = &rpc->waitpdu[i]; for (pdu = q->head; pdu; pdu = next_pdu) { next_pdu = pdu->next; if (pdu->timeout == 0) { /* no timeout for this pdu */ continue; } if (t < pdu->timeout) { /* not expired yet */ continue; } LIBNFS_LIST_REMOVE(&q->head, pdu); if (!q->head) { q->tail = NULL; } rpc_set_error(rpc, "command timed out"); pdu->cb(rpc, RPC_STATUS_TIMEOUT, NULL, pdu->private_data); rpc_free_pdu(rpc, pdu); } } } int rpc_service(struct rpc_context *rpc, int revents) { assert(rpc->magic == RPC_CONTEXT_MAGIC); rpc_timeout_scan(rpc); if (revents == -1 || revents & (POLLERR|POLLHUP)) { if (revents != -1 && revents & POLLERR) { #ifdef WIN32 char err = 0; #else int err = 0; #endif socklen_t err_size = sizeof(err); if (getsockopt(rpc->fd, SOL_SOCKET, SO_ERROR, (char *)&err, &err_size) != 0 || err != 0) { if (err == 0) { err = errno; } rpc_set_error(rpc, "rpc_service: socket error " "%s(%d).", strerror(err), err); } else { rpc_set_error(rpc, "rpc_service: POLLERR, " "Unknown socket error."); } } if (revents != -1 && revents & POLLHUP) { rpc_set_error(rpc, "Socket failed with POLLHUP"); } if (rpc->auto_reconnect) { return rpc_reconnect_requeue(rpc); } maybe_call_connect_cb(rpc, RPC_STATUS_ERROR); return -1; } if (rpc->is_connected == 0 && rpc->fd != -1 && (revents & POLLOUT)) { int err = 0; socklen_t err_size = sizeof(err); if (getsockopt(rpc->fd, SOL_SOCKET, SO_ERROR, (char *)&err, &err_size) != 0 || err != 0) { if (err == 0) { err = errno; } rpc_set_error(rpc, "rpc_service: socket error " "%s(%d) while connecting.", strerror(err), err); maybe_call_connect_cb(rpc, RPC_STATUS_ERROR); return -1; } rpc->is_connected = 1; RPC_LOG(rpc, 2, "connection established on fd %d", rpc->fd); maybe_call_connect_cb(rpc, RPC_STATUS_SUCCESS); return 0; } if (revents & POLLIN) { if (rpc_read_from_socket(rpc) != 0) { if (rpc->is_server_context) { return -1; } else { return rpc_reconnect_requeue(rpc); } } } if (revents & POLLOUT && rpc_has_queue(&rpc->outqueue)) { if (rpc_write_to_socket(rpc) != 0) { if (rpc->is_server_context) { return -1; } else { return rpc_reconnect_requeue(rpc); } } } return 0; } void rpc_set_autoreconnect(struct rpc_context *rpc, int num_retries) { assert(rpc->magic == RPC_CONTEXT_MAGIC); /* we can not connect and not reconnect on a server context. */ if (rpc->is_server_context) { return; } rpc->auto_reconnect = num_retries; } void rpc_set_tcp_syncnt(struct rpc_context *rpc, int v) { assert(rpc->magic == RPC_CONTEXT_MAGIC); rpc->tcp_syncnt = v; } #ifndef TCP_SYNCNT #define TCP_SYNCNT 7 #endif static int rpc_connect_sockaddr_async(struct rpc_context *rpc) { struct sockaddr_storage *s = &rpc->s; socklen_t socksize; assert(rpc->magic == RPC_CONTEXT_MAGIC); switch (s->ss_family) { case AF_INET: socksize = sizeof(struct sockaddr_in); rpc->fd = create_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (set_bind_device(rpc->fd, rpc->ifname) != 0) { rpc_set_error (rpc, "Failed to bind to interface"); return -1; } #ifdef HAVE_NETINET_TCP_H if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); } #endif break; case AF_INET6: socksize = sizeof(struct sockaddr_in6); rpc->fd = create_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (set_bind_device(rpc->fd, rpc->ifname) != 0) { rpc_set_error (rpc, "Failed to bind to interface"); return -1; } #ifdef HAVE_NETINET_TCP_H if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); } #endif break; default: rpc_set_error(rpc, "Can not handle AF_FAMILY:%d", s->ss_family); return -1; } if (rpc->fd == -1) { rpc_set_error(rpc, "Failed to open socket"); return -1; } if (rpc->old_fd) { #if !defined(WIN32) if (dup2(rpc->fd, rpc->old_fd) == -1) { return -1; } close(rpc->fd); rpc->fd = rpc->old_fd; #else /* On Windows dup2 does not work on sockets * instead just close the old socket */ close(rpc->old_fd); rpc->old_fd = 0; #endif } /* Some systems allow you to set capabilities on an executable * to allow the file to be executed with privilege to bind to * privileged system ports, even if the user is not root. * * Opportunistically try to bind the socket to a low numbered * system port in the hope that the user is either root or the * executable has the CAP_NET_BIND_SERVICE. * * As soon as we fail the bind() with EACCES we know we will never * be able to bind to a system port so we terminate the loop. * * On linux, use * sudo setcap 'cap_net_bind_service=+ep' /path/executable * to make the executable able to bind to a system port. * * On Windows, there is no concept of privileged ports. Thus * binding will usually succeed. */ { struct sockaddr_storage ss; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; static int portOfs = 0; const int firstPort = 512; /* >= 512 according to Sun docs */ const int portCount = IPPORT_RESERVED - firstPort; int startOfs, port, rc; sin = (struct sockaddr_in *)&ss; sin6 = (struct sockaddr_in6 *)&ss; if (portOfs == 0) { portOfs = rpc_current_time() % 400; } startOfs = portOfs; do { rc = -1; port = htons(firstPort + portOfs); portOfs = (portOfs + 1) % portCount; /* skip well-known ports */ if (!getservbyport(port, "tcp")) { memset(&ss, 0, sizeof(ss)); switch (s->ss_family) { case AF_INET: sin->sin_port = port; sin->sin_family = AF_INET; #ifdef HAVE_SOCKADDR_LEN sin->sin_len = sizeof(struct sockaddr_in); #endif break; case AF_INET6: sin6->sin6_port = port; sin6->sin6_family = AF_INET6; #ifdef HAVE_SOCKADDR_LEN sin6->sin6_len = sizeof(struct sockaddr_in6); #endif break; } rc = bind(rpc->fd, (struct sockaddr *)&ss, socksize); #if !defined(WIN32) /* we got EACCES, so don't try again */ if (rc != 0 && errno == EACCES) break; #endif } } while (rc != 0 && portOfs != startOfs); } rpc->is_nonblocking = !set_nonblocking(rpc->fd); set_nolinger(rpc->fd); if (connect(rpc->fd, (struct sockaddr *)s, socksize) != 0 && errno != EINPROGRESS) { rpc_set_error(rpc, "connect() to server failed. %s(%d)", strerror(errno), errno); return -1; } return 0; } static int rpc_set_sockaddr(struct rpc_context *rpc, const char *server, int port) { struct addrinfo *ai = NULL; if (getaddrinfo(server, NULL, NULL, &ai) != 0) { rpc_set_error(rpc, "Invalid address:%s. " "Can not resolv into IPv4/v6 structure.", server); return -1; } switch (ai->ai_family) { case AF_INET: ((struct sockaddr_in *)&rpc->s)->sin_family = ai->ai_family; ((struct sockaddr_in *)&rpc->s)->sin_port = htons(port); ((struct sockaddr_in *)&rpc->s)->sin_addr = ((struct sockaddr_in *)(void *)(ai->ai_addr))->sin_addr; #ifdef HAVE_SOCKADDR_LEN ((struct sockaddr_in *)&rpc->s)->sin_len = sizeof(struct sockaddr_in); #endif break; case AF_INET6: ((struct sockaddr_in6 *)&rpc->s)->sin6_family = ai->ai_family; ((struct sockaddr_in6 *)&rpc->s)->sin6_port = htons(port); ((struct sockaddr_in6 *)&rpc->s)->sin6_addr = ((struct sockaddr_in6 *)(void *)(ai->ai_addr))->sin6_addr; #ifdef HAVE_SOCKADDR_LEN ((struct sockaddr_in6 *)&rpc->s)->sin6_len = sizeof(struct sockaddr_in6); #endif break; } freeaddrinfo(ai); return 0; } int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc_cb cb, void *private_data) { assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->is_server_context) { rpc_set_error(rpc, "Can not connect on a server context"); return -1; } if (rpc->fd != -1) { rpc_set_error(rpc, "Trying to connect while already connected"); return -1; } if (rpc->is_udp != 0) { rpc_set_error(rpc, "Trying to connect on UDP socket"); return -1; } rpc->auto_reconnect = 0; if (rpc_set_sockaddr(rpc, server, port) != 0) { return -1; } rpc->connect_cb = cb; rpc->connect_data = private_data; if (rpc_connect_sockaddr_async(rpc) != 0) { return -1; } return 0; } int rpc_disconnect(struct rpc_context *rpc, const char *error) { assert(rpc->magic == RPC_CONTEXT_MAGIC); /* Do not re-disconnect if we are already disconnected */ if (!rpc->is_connected) { return 0; } /* Disable autoreconnect */ rpc_set_autoreconnect(rpc, 0); if (rpc->fd != -1) { close(rpc->fd); } rpc->fd = -1; rpc->is_connected = 0; if (!rpc->is_server_context) { rpc_error_all_pdus(rpc, error); } return 0; } static void reconnect_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data) { assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status != RPC_STATUS_SUCCESS) { rpc_set_error(rpc, "Failed to reconnect async"); rpc_reconnect_requeue(rpc); return; } rpc->is_connected = 1; rpc->connect_cb = NULL; rpc->old_fd = 0; } /* Disconnect but do not error all PDUs, just move pdus in-flight back to the * outqueue and reconnect. */ static int rpc_reconnect_requeue(struct rpc_context *rpc) { struct rpc_pdu *pdu, *next; unsigned int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->auto_reconnect == 0) { RPC_LOG(rpc, 1, "reconnect is disabled"); rpc_error_all_pdus(rpc, "RPC ERROR: Failed to reconnect async"); return -1; } if (rpc->is_connected) { rpc->num_retries = rpc->auto_reconnect; } if (rpc->fd != -1) { rpc->old_fd = rpc->fd; } rpc->fd = -1; rpc->is_connected = 0; if (rpc->outqueue.head) { rpc->outqueue.head->written = 0; } /* Socket is closed so we will not get any replies to any commands * in flight. Move them all over from the waitpdu queue back to the * out queue. */ for (i = 0; i < HASHES; i++) { struct rpc_queue *q = &rpc->waitpdu[i]; for (pdu = q->head; pdu; pdu = next) { next = pdu->next; rpc_return_to_queue(&rpc->outqueue, pdu); /* we have to re-send the whole pdu again */ pdu->written = 0; } rpc_reset_queue(q); } rpc->waitpdu_len = 0; if (rpc->auto_reconnect < 0 || rpc->num_retries > 0) { rpc->num_retries--; rpc->connect_cb = reconnect_cb; RPC_LOG(rpc, 1, "reconnect initiated"); if (rpc_connect_sockaddr_async(rpc) != 0) { rpc_error_all_pdus(rpc, "RPC ERROR: Failed to " "reconnect async"); return -1; } return 0; } RPC_LOG(rpc, 1, "reconnect: all attempts failed."); rpc_error_all_pdus(rpc, "RPC ERROR: All attempts to reconnect failed."); return -1; } int rpc_bind_udp(struct rpc_context *rpc, char *addr, int port) { struct addrinfo *ai = NULL; char service[6]; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->is_udp == 0) { rpc_set_error(rpc, "Cant not bind UDP. Not UDP context"); return -1; } sprintf(service, "%d", port); if (getaddrinfo(addr, service, NULL, &ai) != 0) { rpc_set_error(rpc, "Invalid address:%s. " "Can not resolv into IPv4/v6 structure.", addr); return -1; } switch(ai->ai_family) { case AF_INET: rpc->fd = create_socket(ai->ai_family, SOCK_DGRAM, 0); if (rpc->fd == -1) { rpc_set_error(rpc, "Failed to create UDP socket: %s", strerror(errno)); freeaddrinfo(ai); return -1; } if (bind(rpc->fd, (struct sockaddr *)ai->ai_addr, sizeof(struct sockaddr_in)) != 0) { rpc_set_error(rpc, "Failed to bind to UDP socket: %s", strerror(errno)); freeaddrinfo(ai); return -1; } break; default: rpc_set_error(rpc, "Can not handle UPD sockets of family %d " "yet", ai->ai_family); freeaddrinfo(ai); return -1; } freeaddrinfo(ai); return 0; } int rpc_set_udp_destination(struct rpc_context *rpc, char *addr, int port, int is_broadcast) { struct addrinfo *ai = NULL; char service[6]; assert(rpc->magic == RPC_CONTEXT_MAGIC); if (rpc->is_udp == 0) { rpc_set_error(rpc, "Can not set destination sockaddr. Not UDP " "context"); return -1; } sprintf(service, "%d", port); if (getaddrinfo(addr, service, NULL, &ai) != 0) { rpc_set_error(rpc, "Invalid address:%s. " "Can not resolv into IPv4/v6 structure.", addr); return -1; } memcpy(&rpc->udp_dest, ai->ai_addr, ai->ai_addrlen); freeaddrinfo(ai); rpc->is_broadcast = is_broadcast; setsockopt(rpc->fd, SOL_SOCKET, SO_BROADCAST, (char *)&is_broadcast, sizeof(is_broadcast)); return 0; } struct sockaddr * rpc_get_recv_sockaddr(struct rpc_context *rpc) { assert(rpc->magic == RPC_CONTEXT_MAGIC); return (struct sockaddr *)&rpc->udp_src; } int rpc_queue_length(struct rpc_context *rpc) { int i = 0; struct rpc_pdu *pdu; assert(rpc->magic == RPC_CONTEXT_MAGIC); for(pdu = rpc->outqueue.head; pdu; pdu = pdu->next) { i++; } i += rpc->waitpdu_len; return i; } void rpc_set_fd(struct rpc_context *rpc, int fd) { assert(rpc->magic == RPC_CONTEXT_MAGIC); rpc->fd = fd; } int rpc_is_udp_socket(struct rpc_context *rpc) { #ifdef WIN32 char type = 0; #else int type = 0; #endif socklen_t len = sizeof(type); getsockopt(rpc->fd, SOL_SOCKET, SO_TYPE, &type, &len); return type == SOCK_DGRAM; } libnfs-libnfs-4.0.0/libnfs.pc.in000066400000000000000000000004431343063627400164620ustar00rootroot00000000000000# libnfs pkg-config file prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libnfs Description: libnfs is a client library for accessing NFS shares over a network. Version: @VERSION@ Requires: Conflicts: Libs: -L${libdir} -lnfs Cflags: -I${includedir} libnfs-libnfs-4.0.0/m4/000077500000000000000000000000001343063627400145735ustar00rootroot00000000000000libnfs-libnfs-4.0.0/m4/.keep000066400000000000000000000000001343063627400155060ustar00rootroot00000000000000libnfs-libnfs-4.0.0/mount/000077500000000000000000000000001343063627400154155ustar00rootroot00000000000000libnfs-libnfs-4.0.0/mount/CMakeLists.txt000066400000000000000000000001551343063627400201560ustar00rootroot00000000000000set(SOURCES libnfs-raw-mount.c mount.c) set(HEADERS libnfs-raw-mount.h) core_add_library(mount) libnfs-libnfs-4.0.0/mount/Makefile.am000066400000000000000000000021461343063627400174540ustar00rootroot00000000000000noinst_LTLIBRARIES = libmount.la mount_SOURCES_GENERATED = mount_HEADERS_GENERATED = mount_GENERATED = $(mount_SOURCES_GENERATED) $(mount_HEADERS_GENERATED) CLEANFILES = $(mount_GENERATED) mount-stamp libmount_la_CPPFLAGS = -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/win32 libmount_la_SOURCES = \ $(mount_SOURCES_GENERATED) \ mount.c libnfs-raw-mount.c libnfs-raw-mount.h $(mount_GENERATED) : mount-stamp mount-stamp : mount.x rm -f $(mount_GENERATED) touch mount-stamp compile_rpc: cat mount.x | head -29 >libnfs-raw-mount.h rpcgen -h mount.x | sed -e "s/#include /#include /" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/ CLIENT / void /g" -e "s/SVCXPRT /void /g" -e "s/bool_t/uint32_t/g" >> libnfs-raw-mount.h cat mount.x | head -29 >libnfs-raw-mount.c rpcgen -c mount.x | sed -e "s/#include \".*mount.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-mount.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" -e "s/bool_t/uint32_t/g" >> libnfs-raw-mount.c libnfs-libnfs-4.0.0/mount/libnfs-raw-mount.c000066400000000000000000000112161343063627400207660ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #include "libnfs-zdr.h" #include "libnfs-raw-mount.h" uint32_t zdr_fhandle3 (ZDR *zdrs, fhandle3 *objp) { if (!zdr_bytes (zdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3)) return FALSE; return TRUE; } uint32_t zdr_dirpath (ZDR *zdrs, dirpath *objp) { if (!zdr_string (zdrs, objp, MNTPATHLEN)) return FALSE; return TRUE; } uint32_t zdr_name (ZDR *zdrs, name *objp) { if (!zdr_string (zdrs, objp, MNTNAMLEN)) return FALSE; return TRUE; } uint32_t zdr_mountstat3 (ZDR *zdrs, mountstat3 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_mountlist (ZDR *zdrs, mountlist *objp) { if (!zdr_pointer (zdrs, (char **)objp, sizeof (struct mountbody), (zdrproc_t) zdr_mountbody)) return FALSE; return TRUE; } uint32_t zdr_mountbody (ZDR *zdrs, mountbody *objp) { if (!zdr_name (zdrs, &objp->ml_hostname)) return FALSE; if (!zdr_dirpath (zdrs, &objp->ml_directory)) return FALSE; if (!zdr_mountlist (zdrs, &objp->ml_next)) return FALSE; return TRUE; } uint32_t zdr_groups (ZDR *zdrs, groups *objp) { if (!zdr_pointer (zdrs, (char **)objp, sizeof (struct groupnode), (zdrproc_t) zdr_groupnode)) return FALSE; return TRUE; } uint32_t zdr_groupnode (ZDR *zdrs, groupnode *objp) { if (!zdr_name (zdrs, &objp->gr_name)) return FALSE; if (!zdr_groups (zdrs, &objp->gr_next)) return FALSE; return TRUE; } uint32_t zdr_exports (ZDR *zdrs, exports *objp) { if (!zdr_pointer (zdrs, (char **)objp, sizeof (struct exportnode), (zdrproc_t) zdr_exportnode)) return FALSE; return TRUE; } uint32_t zdr_exportnode (ZDR *zdrs, exportnode *objp) { if (!zdr_dirpath (zdrs, &objp->ex_dir)) return FALSE; if (!zdr_groups (zdrs, &objp->ex_groups)) return FALSE; if (!zdr_exports (zdrs, &objp->ex_next)) return FALSE; return TRUE; } uint32_t zdr_mountres3_ok (ZDR *zdrs, mountres3_ok *objp) { if (!zdr_fhandle3 (zdrs, &objp->fhandle)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->auth_flavors.auth_flavors_val, (u_int *) &objp->auth_flavors.auth_flavors_len, ~0, sizeof (int), (zdrproc_t) zdr_int)) return FALSE; return TRUE; } uint32_t zdr_mountres3 (ZDR *zdrs, mountres3 *objp) { if (!zdr_mountstat3 (zdrs, &objp->fhs_status)) return FALSE; switch (objp->fhs_status) { case MNT3_OK: if (!zdr_mountres3_ok (zdrs, &objp->mountres3_u.mountinfo)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_mountstat1 (ZDR *zdrs, mountstat1 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_fhandle1 (ZDR *zdrs, fhandle1 objp) { if (!zdr_opaque (zdrs, objp, FHSIZE)) return FALSE; return TRUE; } uint32_t zdr_mountres1_ok (ZDR *zdrs, mountres1_ok *objp) { if (!zdr_fhandle1 (zdrs, objp->fhandle)) return FALSE; return TRUE; } uint32_t zdr_mountres1 (ZDR *zdrs, mountres1 *objp) { if (!zdr_mountstat1 (zdrs, &objp->fhs_status)) return FALSE; switch (objp->fhs_status) { case MNT1_OK: if (!zdr_mountres1_ok (zdrs, &objp->mountres1_u.mountinfo)) return FALSE; break; default: break; } return TRUE; } libnfs-libnfs-4.0.0/mount/libnfs-raw-mount.h000066400000000000000000000200601343063627400207700ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _MOUNT_H_RPCGEN #define _MOUNT_H_RPCGEN #include #ifdef __cplusplus extern "C" { #endif #define MNTPATHLEN 1024 #define MNTNAMLEN 255 #define FHSIZE3 64 typedef struct { u_int fhandle3_len; char *fhandle3_val; } fhandle3; typedef char *dirpath; typedef char *name; enum mountstat3 { MNT3_OK = 0, MNT3ERR_PERM = 1, MNT3ERR_NOENT = 2, MNT3ERR_IO = 5, MNT3ERR_ACCES = 13, MNT3ERR_NOTDIR = 20, MNT3ERR_INVAL = 22, MNT3ERR_NAMETOOLONG = 63, MNT3ERR_NOTSUPP = 10004, MNT3ERR_SERVERFAULT = 10006, }; typedef enum mountstat3 mountstat3; typedef struct mountbody *mountlist; struct mountbody { name ml_hostname; dirpath ml_directory; mountlist ml_next; }; typedef struct mountbody mountbody; typedef struct groupnode *groups; struct groupnode { name gr_name; groups gr_next; }; typedef struct groupnode groupnode; typedef struct exportnode *exports; struct exportnode { dirpath ex_dir; groups ex_groups; exports ex_next; }; typedef struct exportnode exportnode; struct mountres3_ok { fhandle3 fhandle; struct { u_int auth_flavors_len; int *auth_flavors_val; } auth_flavors; }; typedef struct mountres3_ok mountres3_ok; struct mountres3 { mountstat3 fhs_status; union { mountres3_ok mountinfo; } mountres3_u; }; typedef struct mountres3 mountres3; enum mountstat1 { MNT1_OK = 0, MNT1ERR_PERM = 1, MNT1ERR_NOENT = 2, MNT1ERR_IO = 5, MNT1ERR_ACCES = 13, MNT1ERR_NOTDIR = 20, MNT1ERR_INVAL = 22, MNT1ERR_NAMETOOLONG = 63, MNT1ERR_NOTSUPP = 10004, MNT1ERR_SERVERFAULT = 10006, }; typedef enum mountstat1 mountstat1; #define FHSIZE 32 typedef char fhandle1[FHSIZE]; struct mountres1_ok { fhandle1 fhandle; }; typedef struct mountres1_ok mountres1_ok; struct mountres1 { mountstat1 fhs_status; union { mountres1_ok mountinfo; } mountres1_u; }; typedef struct mountres1 mountres1; #define MOUNT_PROGRAM 100005 #define MOUNT_V1 1 #if defined(__STDC__) || defined(__cplusplus) #define MOUNT1_NULL 0 extern void * mount1_null_1(void *, void *); extern void * mount1_null_1_svc(void *, struct svc_req *); #define MOUNT1_MNT 1 extern mountres1 * mount1_mnt_1(dirpath *, void *); extern mountres1 * mount1_mnt_1_svc(dirpath *, struct svc_req *); #define MOUNT1_DUMP 2 extern mountlist * mount1_dump_1(void *, void *); extern mountlist * mount1_dump_1_svc(void *, struct svc_req *); #define MOUNT1_UMNT 3 extern void * mount1_umnt_1(dirpath *, void *); extern void * mount1_umnt_1_svc(dirpath *, struct svc_req *); #define MOUNT1_UMNTALL 4 extern void * mount1_umntall_1(void *, void *); extern void * mount1_umntall_1_svc(void *, struct svc_req *); #define MOUNT1_EXPORT 5 extern exports * mount1_export_1(void *, void *); extern exports * mount1_export_1_svc(void *, struct svc_req *); extern int mount_program_1_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define MOUNT1_NULL 0 extern void * mount1_null_1(); extern void * mount1_null_1_svc(); #define MOUNT1_MNT 1 extern mountres1 * mount1_mnt_1(); extern mountres1 * mount1_mnt_1_svc(); #define MOUNT1_DUMP 2 extern mountlist * mount1_dump_1(); extern mountlist * mount1_dump_1_svc(); #define MOUNT1_UMNT 3 extern void * mount1_umnt_1(); extern void * mount1_umnt_1_svc(); #define MOUNT1_UMNTALL 4 extern void * mount1_umntall_1(); extern void * mount1_umntall_1_svc(); #define MOUNT1_EXPORT 5 extern exports * mount1_export_1(); extern exports * mount1_export_1_svc(); extern int mount_program_1_freeresult (); #endif /* K&R C */ #define MOUNT_V3 3 #if defined(__STDC__) || defined(__cplusplus) #define MOUNT3_NULL 0 extern void * mount3_null_3(void *, void *); extern void * mount3_null_3_svc(void *, struct svc_req *); #define MOUNT3_MNT 1 extern mountres3 * mount3_mnt_3(dirpath *, void *); extern mountres3 * mount3_mnt_3_svc(dirpath *, struct svc_req *); #define MOUNT3_DUMP 2 extern mountlist * mount3_dump_3(void *, void *); extern mountlist * mount3_dump_3_svc(void *, struct svc_req *); #define MOUNT3_UMNT 3 extern void * mount3_umnt_3(dirpath *, void *); extern void * mount3_umnt_3_svc(dirpath *, struct svc_req *); #define MOUNT3_UMNTALL 4 extern void * mount3_umntall_3(void *, void *); extern void * mount3_umntall_3_svc(void *, struct svc_req *); #define MOUNT3_EXPORT 5 extern exports * mount3_export_3(void *, void *); extern exports * mount3_export_3_svc(void *, struct svc_req *); extern int mount_program_3_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define MOUNT3_NULL 0 extern void * mount3_null_3(); extern void * mount3_null_3_svc(); #define MOUNT3_MNT 1 extern mountres3 * mount3_mnt_3(); extern mountres3 * mount3_mnt_3_svc(); #define MOUNT3_DUMP 2 extern mountlist * mount3_dump_3(); extern mountlist * mount3_dump_3_svc(); #define MOUNT3_UMNT 3 extern void * mount3_umnt_3(); extern void * mount3_umnt_3_svc(); #define MOUNT3_UMNTALL 4 extern void * mount3_umntall_3(); extern void * mount3_umntall_3_svc(); #define MOUNT3_EXPORT 5 extern exports * mount3_export_3(); extern exports * mount3_export_3_svc(); extern int mount_program_3_freeresult (); #endif /* K&R C */ /* the zdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern uint32_t zdr_fhandle3 (ZDR *, fhandle3*); extern uint32_t zdr_dirpath (ZDR *, dirpath*); extern uint32_t zdr_name (ZDR *, name*); extern uint32_t zdr_mountstat3 (ZDR *, mountstat3*); extern uint32_t zdr_mountlist (ZDR *, mountlist*); extern uint32_t zdr_mountbody (ZDR *, mountbody*); extern uint32_t zdr_groups (ZDR *, groups*); extern uint32_t zdr_groupnode (ZDR *, groupnode*); extern uint32_t zdr_exports (ZDR *, exports*); extern uint32_t zdr_exportnode (ZDR *, exportnode*); extern uint32_t zdr_mountres3_ok (ZDR *, mountres3_ok*); extern uint32_t zdr_mountres3 (ZDR *, mountres3*); extern uint32_t zdr_mountstat1 (ZDR *, mountstat1*); extern uint32_t zdr_fhandle1 (ZDR *, fhandle1); extern uint32_t zdr_mountres1_ok (ZDR *, mountres1_ok*); extern uint32_t zdr_mountres1 (ZDR *, mountres1*); #else /* K&R C */ extern uint32_t zdr_fhandle3 (); extern uint32_t zdr_dirpath (); extern uint32_t zdr_name (); extern uint32_t zdr_mountstat3 (); extern uint32_t zdr_mountlist (); extern uint32_t zdr_mountbody (); extern uint32_t zdr_groups (); extern uint32_t zdr_groupnode (); extern uint32_t zdr_exports (); extern uint32_t zdr_exportnode (); extern uint32_t zdr_mountres3_ok (); extern uint32_t zdr_mountres3 (); extern uint32_t zdr_mountstat1 (); extern uint32_t zdr_fhandle1 (); extern uint32_t zdr_mountres1_ok (); extern uint32_t zdr_mountres1 (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_MOUNT_H_RPCGEN */ libnfs-libnfs-4.0.0/mount/mount.c000066400000000000000000000222301343063627400167220ustar00rootroot00000000000000/* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef WIN32 #include #endif/*WIN32*/ #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-mount.h" int rpc_mount3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V3, MOUNT3_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for mount/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for mount/null call"); return -1; } return 0; } int rpc_mount_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { return rpc_mount3_null_async(rpc, cb, private_data); } int rpc_mount3_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V3, MOUNT3_MNT, cb, private_data, (zdrproc_t)zdr_mountres3, sizeof(mountres3)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for mount/mnt call"); return -1; } if (zdr_dirpath(&pdu->zdr, &export) == 0) { rpc_set_error(rpc, "ZDR error. Failed to encode mount/mnt call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for mount/mnt call"); return -1; } return 0; } int rpc_mount_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data) { return rpc_mount3_mnt_async(rpc, cb, export, private_data); } int rpc_mount3_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V3, MOUNT3_DUMP, cb, private_data, (zdrproc_t)zdr_mountlist, sizeof(mountlist)); if (pdu == NULL) { rpc_set_error(rpc, "Failed to allocate pdu for mount/dump"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue mount/dump pdu"); return -1; } return 0; } int rpc_mount_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { return rpc_mount3_dump_async(rpc, cb, private_data); } int rpc_mount3_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V3, MOUNT3_UMNT, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Failed to allocate pdu for mount/umnt"); return -1; } if (zdr_dirpath(&pdu->zdr, &export) == 0) { rpc_set_error(rpc, "failed to encode dirpath for mount/umnt"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue mount/umnt pdu"); return -1; } return 0; } int rpc_mount_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data) { return rpc_mount3_umnt_async(rpc, cb, export, private_data); } int rpc_mount3_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V3, MOUNT3_UMNTALL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Failed to allocate pdu for mount/umntall"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue mount/umntall pdu"); return -1; } return 0; } int rpc_mount_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { return rpc_mount3_umntall_async(rpc, cb, private_data); } int rpc_mount3_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V3, MOUNT3_EXPORT, cb, private_data, (zdrproc_t)zdr_exports, sizeof(exports)); if (pdu == NULL) { rpc_set_error(rpc, "Failed to allocate pdu for mount/export"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue mount/export pdu"); return -1; } return 0; } int rpc_mount_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { return rpc_mount3_export_async(rpc, cb, private_data); } char *mountstat3_to_str(int st) { enum mountstat3 stat = st; char *str = "unknown mount stat"; switch (stat) { case MNT3_OK: str="MNT3_OK"; break; case MNT3ERR_PERM: str="MNT3ERR_PERM"; break; case MNT3ERR_NOENT: str="MNT3ERR_NOENT"; break; case MNT3ERR_IO: str="MNT3ERR_IO"; break; case MNT3ERR_ACCES: str="MNT3ERR_ACCES"; break; case MNT3ERR_NOTDIR: str="MNT3ERR_NOTDIR"; break; case MNT3ERR_INVAL: str="MNT3ERR_INVAL"; break; case MNT3ERR_NAMETOOLONG: str="MNT3ERR_NAMETOOLONG"; break; case MNT3ERR_NOTSUPP: str="MNT3ERR_NOTSUPP"; break; case MNT3ERR_SERVERFAULT: str="MNT3ERR_SERVERFAULT"; break; } return str; } int mountstat3_to_errno(int st) { enum mountstat3 stat = st; switch (stat) { case MNT3_OK: return 0; break; case MNT3ERR_PERM: return -EPERM; break; case MNT3ERR_NOENT: return -EPERM; break; case MNT3ERR_IO: return -EIO; break; case MNT3ERR_ACCES: return -EACCES; break; case MNT3ERR_NOTDIR: return -ENOTDIR; break; case MNT3ERR_INVAL: return -EINVAL; break; case MNT3ERR_NAMETOOLONG: return -E2BIG; break; case MNT3ERR_NOTSUPP: return -EINVAL; break; case MNT3ERR_SERVERFAULT: return -EIO; break; } return -ERANGE; } int rpc_mount1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for MOUNT1/NULL call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for MOUNT1/NULL call"); return -1; } return 0; } int rpc_mount1_mnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_MNT, cb, private_data, (zdrproc_t)zdr_mountres1, sizeof(mountres1)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for MOUNT1/MNT call"); return -1; } if (zdr_dirpath(&pdu->zdr, &export) == 0) { rpc_set_error(rpc, "ZDR error. Failed to encode MOUNT1/MNT call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for MOUNT1/MNT call"); return -1; } return 0; } int rpc_mount1_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_DUMP, cb, private_data, (zdrproc_t)zdr_mountlist, sizeof(mountlist)); if (pdu == NULL) { rpc_set_error(rpc, "Failed to allocate pdu for MOUNT1/DUMP"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue MOUNT1/DUMP pdu"); return -1; } return 0; } int rpc_mount1_umnt_async(struct rpc_context *rpc, rpc_cb cb, char *export, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_UMNT, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Failed to allocate pdu for MOUNT1/UMNT"); return -1; } if (zdr_dirpath(&pdu->zdr, &export) == 0) { rpc_set_error(rpc, "failed to encode dirpath for MOUNT1/UMNT"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue MOUNT1/UMNT pdu"); return -1; } return 0; } int rpc_mount1_umntall_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_UMNTALL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Failed to allocate pdu for MOUNT1/UMNTALL"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue MOUNT1/UMNTALL pdu"); return -1; } return 0; } int rpc_mount1_export_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, MOUNT_PROGRAM, MOUNT_V1, MOUNT1_EXPORT, cb, private_data, (zdrproc_t)zdr_exports, sizeof(exports)); if (pdu == NULL) { rpc_set_error(rpc, "Failed to allocate pdu for MOUNT1/EXPORT"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue MOUNT1/EXPORT pdu"); return -1; } return 0; } libnfs-libnfs-4.0.0/mount/mount.x000066400000000000000000000101601343063627400167460ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ const MNTPATHLEN = 1024; /* Maximum bytes in a path name */ const MNTNAMLEN = 255; /* Maximum bytes in a name */ const FHSIZE3 = 64; /* Maximum bytes in a V3 file handle */ typedef opaque fhandle3; typedef string dirpath; typedef string name; enum mountstat3 { MNT3_OK = 0, /* no error */ MNT3ERR_PERM = 1, /* Not owner */ MNT3ERR_NOENT = 2, /* No such file or directory */ MNT3ERR_IO = 5, /* I/O error */ MNT3ERR_ACCES = 13, /* Permission denied */ MNT3ERR_NOTDIR = 20, /* Not a directory */ MNT3ERR_INVAL = 22, /* Invalid argument */ MNT3ERR_NAMETOOLONG = 63, /* Filename too long */ MNT3ERR_NOTSUPP = 10004, /* Operation not supported */ MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */ }; typedef struct mountbody *mountlist; struct mountbody { name ml_hostname; dirpath ml_directory; mountlist ml_next; }; typedef struct groupnode *groups; struct groupnode { name gr_name; groups gr_next; }; typedef struct exportnode *exports; struct exportnode { dirpath ex_dir; groups ex_groups; exports ex_next; }; struct mountres3_ok { fhandle3 fhandle; int auth_flavors<>; }; union mountres3 switch (mountstat3 fhs_status) { case MNT3_OK: mountres3_ok mountinfo; default: void; }; enum mountstat1 { MNT1_OK = 0, /* no error */ MNT1ERR_PERM = 1, /* Not owner */ MNT1ERR_NOENT = 2, /* No such file or directory */ MNT1ERR_IO = 5, /* I/O error */ MNT1ERR_ACCES = 13, /* Permission denied */ MNT1ERR_NOTDIR = 20, /* Not a directory */ MNT1ERR_INVAL = 22, /* Invalid argument */ MNT1ERR_NAMETOOLONG = 63, /* Filename too long */ MNT1ERR_NOTSUPP = 10004, /* Operation not supported */ MNT1ERR_SERVERFAULT = 10006 /* A failure on the server */ }; const FHSIZE = 32; typedef opaque fhandle1[FHSIZE]; struct mountres1_ok { fhandle1 fhandle; }; union mountres1 switch (mountstat1 fhs_status) { case MNT1_OK: mountres1_ok mountinfo; default: void; }; program MOUNT_PROGRAM { version MOUNT_V1 { void MOUNT1_NULL(void) = 0; mountres1 MOUNT1_MNT(dirpath) = 1; mountlist MOUNT1_DUMP(void) = 2; void MOUNT1_UMNT(dirpath) = 3; void MOUNT1_UMNTALL(void) = 4; exports MOUNT1_EXPORT(void) = 5; } = 1; version MOUNT_V3 { void MOUNT3_NULL(void) = 0; mountres3 MOUNT3_MNT(dirpath) = 1; mountlist MOUNT3_DUMP(void) = 2; void MOUNT3_UMNT(dirpath) = 3; void MOUNT3_UMNTALL(void) = 4; exports MOUNT3_EXPORT(void) = 5; } = 3; } = 100005; libnfs-libnfs-4.0.0/nfs/000077500000000000000000000000001343063627400150415ustar00rootroot00000000000000libnfs-libnfs-4.0.0/nfs/CMakeLists.txt000066400000000000000000000001721343063627400176010ustar00rootroot00000000000000set(SOURCES libnfs-raw-nfs.c nfs.c nfsacl.c) set(HEADERS libnfs-raw-nfs.h) core_add_library(nfs) libnfs-libnfs-4.0.0/nfs/Makefile.am000066400000000000000000000023071343063627400170770ustar00rootroot00000000000000noinst_LTLIBRARIES = libnfs.la nfs_SOURCES_GENERATED = nfs_HEADERS_GENERATED = nfs_GENERATED = $(nfs_SOURCES_GENERATED) $(nfs_HEADERS_GENERATED) CLEANFILES = $(nfs_GENERATED) nfs-stamp libnfs_la_CPPFLAGS = -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/win32 libnfs_la_SOURCES = \ $(nfs_SOURCES_GENERATED) \ nfs.c nfsacl.c libnfs-raw-nfs.c libnfs-raw-nfs.h $(nfs_GENERATED) : nfs-stamp nfs-stamp : nfs.x rm -f $(nfs_GENERATED) touch nfs-stamp compile_rpc: cat nfs.x | head -29 >libnfs-raw-nfs.h rpcgen -h nfs.x | sed -e "s/#include /#include /" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/#define _NFS_H_RPCGEN/#define _NFS_H_RPCGEN\n#include /g" -e "s/#define NFS3_COOKIEVERFSIZE 8/#define NFS3_COOKIEVERFSIZE 8\n\n/g" -e "s/ CLIENT / void /g" -e "s/SVCXPRT /void /g" -e "s/bool_t/uint32_t/g" >> libnfs-raw-nfs.h cat nfs.x | head -29 >libnfs-raw-nfs.c rpcgen -c nfs.x | sed -e "s/#include \".*nfs.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nfs.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" -e "s/bool_t/uint32_t/g" >> libnfs-raw-nfs.c libnfs-libnfs-4.0.0/nfs/libnfs-raw-nfs.c000066400000000000000000001576261343063627400200560ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #include "libnfs-zdr.h" #include "libnfs-raw-nfs.h" uint32_t zdr_cookieverf3 (ZDR *zdrs, cookieverf3 objp) { if (!zdr_opaque (zdrs, objp, NFS3_COOKIEVERFSIZE)) return FALSE; return TRUE; } uint32_t zdr_cookie3 (ZDR *zdrs, cookie3 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_nfs_fh3 (ZDR *zdrs, nfs_fh3 *objp) { if (!zdr_bytes (zdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, NFS3_FHSIZE)) return FALSE; return TRUE; } uint32_t zdr_filename3 (ZDR *zdrs, filename3 *objp) { if (!zdr_string (zdrs, objp, ~0)) return FALSE; return TRUE; } uint32_t zdr_diropargs3 (ZDR *zdrs, diropargs3 *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->dir)) return FALSE; if (!zdr_filename3 (zdrs, &objp->name)) return FALSE; return TRUE; } uint32_t zdr_ftype3 (ZDR *zdrs, ftype3 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_mode3 (ZDR *zdrs, mode3 *objp) { if (!zdr_u_int (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_uid3 (ZDR *zdrs, uid3 *objp) { if (!zdr_u_int (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_gid3 (ZDR *zdrs, gid3 *objp) { if (!zdr_u_int (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_size3 (ZDR *zdrs, size3 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fileid3 (ZDR *zdrs, fileid3 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_specdata3 (ZDR *zdrs, specdata3 *objp) { if (!zdr_u_int (zdrs, &objp->specdata1)) return FALSE; if (!zdr_u_int (zdrs, &objp->specdata2)) return FALSE; return TRUE; } uint32_t zdr_nfstime3 (ZDR *zdrs, nfstime3 *objp) { if (!zdr_u_int (zdrs, &objp->seconds)) return FALSE; if (!zdr_u_int (zdrs, &objp->nseconds)) return FALSE; return TRUE; } uint32_t zdr_fattr3 (ZDR *zdrs, fattr3 *objp) { if (!zdr_ftype3 (zdrs, &objp->type)) return FALSE; if (!zdr_mode3 (zdrs, &objp->mode)) return FALSE; if (!zdr_u_int (zdrs, &objp->nlink)) return FALSE; if (!zdr_uid3 (zdrs, &objp->uid)) return FALSE; if (!zdr_gid3 (zdrs, &objp->gid)) return FALSE; if (!zdr_size3 (zdrs, &objp->size)) return FALSE; if (!zdr_size3 (zdrs, &objp->used)) return FALSE; if (!zdr_specdata3 (zdrs, &objp->rdev)) return FALSE; if (!zdr_uint64_t (zdrs, &objp->fsid)) return FALSE; if (!zdr_fileid3 (zdrs, &objp->fileid)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->atime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->mtime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->ctime)) return FALSE; return TRUE; } uint32_t zdr_post_op_attr (ZDR *zdrs, post_op_attr *objp) { if (!zdr_bool (zdrs, &objp->attributes_follow)) return FALSE; switch (objp->attributes_follow) { case TRUE: if (!zdr_fattr3 (zdrs, &objp->post_op_attr_u.attributes)) return FALSE; break; case FALSE: break; default: return FALSE; } return TRUE; } uint32_t zdr_nfsstat3 (ZDR *zdrs, nfsstat3 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_stable_how (ZDR *zdrs, stable_how *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_offset3 (ZDR *zdrs, offset3 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_count3 (ZDR *zdrs, count3 *objp) { if (!zdr_u_int (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_wcc_attr (ZDR *zdrs, wcc_attr *objp) { if (!zdr_size3 (zdrs, &objp->size)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->mtime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->ctime)) return FALSE; return TRUE; } uint32_t zdr_pre_op_attr (ZDR *zdrs, pre_op_attr *objp) { if (!zdr_bool (zdrs, &objp->attributes_follow)) return FALSE; switch (objp->attributes_follow) { case TRUE: if (!zdr_wcc_attr (zdrs, &objp->pre_op_attr_u.attributes)) return FALSE; break; case FALSE: break; default: return FALSE; } return TRUE; } uint32_t zdr_wcc_data (ZDR *zdrs, wcc_data *objp) { if (!zdr_pre_op_attr (zdrs, &objp->before)) return FALSE; if (!zdr_post_op_attr (zdrs, &objp->after)) return FALSE; return TRUE; } uint32_t zdr_WRITE3args (ZDR *zdrs, WRITE3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->file)) return FALSE; if (!zdr_offset3 (zdrs, &objp->offset)) return FALSE; if (!zdr_count3 (zdrs, &objp->count)) return FALSE; if (!zdr_stable_how (zdrs, &objp->stable)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_writeverf3 (ZDR *zdrs, writeverf3 objp) { if (!zdr_opaque (zdrs, objp, NFS3_WRITEVERFSIZE)) return FALSE; return TRUE; } uint32_t zdr_WRITE3resok (ZDR *zdrs, WRITE3resok *objp) { if (!zdr_wcc_data (zdrs, &objp->file_wcc)) return FALSE; if (!zdr_count3 (zdrs, &objp->count)) return FALSE; if (!zdr_stable_how (zdrs, &objp->committed)) return FALSE; if (!zdr_writeverf3 (zdrs, objp->verf)) return FALSE; return TRUE; } uint32_t zdr_WRITE3resfail (ZDR *zdrs, WRITE3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->file_wcc)) return FALSE; return TRUE; } uint32_t zdr_WRITE3res (ZDR *zdrs, WRITE3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_WRITE3resok (zdrs, &objp->WRITE3res_u.resok)) return FALSE; break; default: if (!zdr_WRITE3resfail (zdrs, &objp->WRITE3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_LOOKUP3args (ZDR *zdrs, LOOKUP3args *objp) { if (!zdr_diropargs3 (zdrs, &objp->what)) return FALSE; return TRUE; } uint32_t zdr_LOOKUP3resok (ZDR *zdrs, LOOKUP3resok *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->object)) return FALSE; if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_post_op_attr (zdrs, &objp->dir_attributes)) return FALSE; return TRUE; } uint32_t zdr_LOOKUP3resfail (ZDR *zdrs, LOOKUP3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->dir_attributes)) return FALSE; return TRUE; } uint32_t zdr_LOOKUP3res (ZDR *zdrs, LOOKUP3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_LOOKUP3resok (zdrs, &objp->LOOKUP3res_u.resok)) return FALSE; break; default: if (!zdr_LOOKUP3resfail (zdrs, &objp->LOOKUP3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_COMMIT3args (ZDR *zdrs, COMMIT3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->file)) return FALSE; if (!zdr_offset3 (zdrs, &objp->offset)) return FALSE; if (!zdr_count3 (zdrs, &objp->count)) return FALSE; return TRUE; } uint32_t zdr_COMMIT3resok (ZDR *zdrs, COMMIT3resok *objp) { if (!zdr_wcc_data (zdrs, &objp->file_wcc)) return FALSE; if (!zdr_writeverf3 (zdrs, objp->verf)) return FALSE; return TRUE; } uint32_t zdr_COMMIT3resfail (ZDR *zdrs, COMMIT3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->file_wcc)) return FALSE; return TRUE; } uint32_t zdr_COMMIT3res (ZDR *zdrs, COMMIT3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_COMMIT3resok (zdrs, &objp->COMMIT3res_u.resok)) return FALSE; break; default: if (!zdr_COMMIT3resfail (zdrs, &objp->COMMIT3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_ACCESS3args (ZDR *zdrs, ACCESS3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->object)) return FALSE; if (!zdr_u_int (zdrs, &objp->access)) return FALSE; return TRUE; } uint32_t zdr_ACCESS3resok (ZDR *zdrs, ACCESS3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_u_int (zdrs, &objp->access)) return FALSE; return TRUE; } uint32_t zdr_ACCESS3resfail (ZDR *zdrs, ACCESS3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_ACCESS3res (ZDR *zdrs, ACCESS3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_ACCESS3resok (zdrs, &objp->ACCESS3res_u.resok)) return FALSE; break; default: if (!zdr_ACCESS3resfail (zdrs, &objp->ACCESS3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_GETATTR3args (ZDR *zdrs, GETATTR3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->object)) return FALSE; return TRUE; } uint32_t zdr_GETATTR3resok (ZDR *zdrs, GETATTR3resok *objp) { if (!zdr_fattr3 (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_GETATTR3res (ZDR *zdrs, GETATTR3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_GETATTR3resok (zdrs, &objp->GETATTR3res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_time_how (ZDR *zdrs, time_how *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_set_mode3 (ZDR *zdrs, set_mode3 *objp) { if (!zdr_bool (zdrs, &objp->set_it)) return FALSE; switch (objp->set_it) { case TRUE: if (!zdr_mode3 (zdrs, &objp->set_mode3_u.mode)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_set_uid3 (ZDR *zdrs, set_uid3 *objp) { if (!zdr_bool (zdrs, &objp->set_it)) return FALSE; switch (objp->set_it) { case TRUE: if (!zdr_uid3 (zdrs, &objp->set_uid3_u.uid)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_set_gid3 (ZDR *zdrs, set_gid3 *objp) { if (!zdr_bool (zdrs, &objp->set_it)) return FALSE; switch (objp->set_it) { case TRUE: if (!zdr_gid3 (zdrs, &objp->set_gid3_u.gid)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_set_size3 (ZDR *zdrs, set_size3 *objp) { if (!zdr_bool (zdrs, &objp->set_it)) return FALSE; switch (objp->set_it) { case TRUE: if (!zdr_size3 (zdrs, &objp->set_size3_u.size)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_set_atime (ZDR *zdrs, set_atime *objp) { if (!zdr_time_how (zdrs, &objp->set_it)) return FALSE; switch (objp->set_it) { case SET_TO_CLIENT_TIME: if (!zdr_nfstime3 (zdrs, &objp->set_atime_u.atime)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_set_mtime (ZDR *zdrs, set_mtime *objp) { if (!zdr_time_how (zdrs, &objp->set_it)) return FALSE; switch (objp->set_it) { case SET_TO_CLIENT_TIME: if (!zdr_nfstime3 (zdrs, &objp->set_mtime_u.mtime)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_sattr3 (ZDR *zdrs, sattr3 *objp) { if (!zdr_set_mode3 (zdrs, &objp->mode)) return FALSE; if (!zdr_set_uid3 (zdrs, &objp->uid)) return FALSE; if (!zdr_set_gid3 (zdrs, &objp->gid)) return FALSE; if (!zdr_set_size3 (zdrs, &objp->size)) return FALSE; if (!zdr_set_atime (zdrs, &objp->atime)) return FALSE; if (!zdr_set_mtime (zdrs, &objp->mtime)) return FALSE; return TRUE; } uint32_t zdr_createmode3 (ZDR *zdrs, createmode3 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_createverf3 (ZDR *zdrs, createverf3 objp) { if (!zdr_opaque (zdrs, objp, NFS3_CREATEVERFSIZE)) return FALSE; return TRUE; } uint32_t zdr_createhow3 (ZDR *zdrs, createhow3 *objp) { if (!zdr_createmode3 (zdrs, &objp->mode)) return FALSE; switch (objp->mode) { case UNCHECKED: if (!zdr_sattr3 (zdrs, &objp->createhow3_u.obj_attributes)) return FALSE; break; case GUARDED: if (!zdr_sattr3 (zdrs, &objp->createhow3_u.g_obj_attributes)) return FALSE; break; case EXCLUSIVE: if (!zdr_createverf3 (zdrs, objp->createhow3_u.verf)) return FALSE; break; default: return FALSE; } return TRUE; } uint32_t zdr_CREATE3args (ZDR *zdrs, CREATE3args *objp) { if (!zdr_diropargs3 (zdrs, &objp->where)) return FALSE; if (!zdr_createhow3 (zdrs, &objp->how)) return FALSE; return TRUE; } uint32_t zdr_post_op_fh3 (ZDR *zdrs, post_op_fh3 *objp) { if (!zdr_bool (zdrs, &objp->handle_follows)) return FALSE; switch (objp->handle_follows) { case TRUE: if (!zdr_nfs_fh3 (zdrs, &objp->post_op_fh3_u.handle)) return FALSE; break; case FALSE: break; default: return FALSE; } return TRUE; } uint32_t zdr_CREATE3resok (ZDR *zdrs, CREATE3resok *objp) { if (!zdr_post_op_fh3 (zdrs, &objp->obj)) return FALSE; if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_CREATE3resfail (ZDR *zdrs, CREATE3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_CREATE3res (ZDR *zdrs, CREATE3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_CREATE3resok (zdrs, &objp->CREATE3res_u.resok)) return FALSE; break; default: if (!zdr_CREATE3resfail (zdrs, &objp->CREATE3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_REMOVE3args (ZDR *zdrs, REMOVE3args *objp) { if (!zdr_diropargs3 (zdrs, &objp->object)) return FALSE; return TRUE; } uint32_t zdr_REMOVE3resok (ZDR *zdrs, REMOVE3resok *objp) { if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_REMOVE3resfail (ZDR *zdrs, REMOVE3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_REMOVE3res (ZDR *zdrs, REMOVE3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_REMOVE3resok (zdrs, &objp->REMOVE3res_u.resok)) return FALSE; break; default: if (!zdr_REMOVE3resfail (zdrs, &objp->REMOVE3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_READ3args (ZDR *zdrs, READ3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->file)) return FALSE; if (!zdr_offset3 (zdrs, &objp->offset)) return FALSE; if (!zdr_count3 (zdrs, &objp->count)) return FALSE; return TRUE; } uint32_t zdr_READ3resok (ZDR *zdrs, READ3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->file_attributes)) return FALSE; if (!zdr_count3 (zdrs, &objp->count)) return FALSE; if (!zdr_bool (zdrs, &objp->eof)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_READ3resfail (ZDR *zdrs, READ3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->file_attributes)) return FALSE; return TRUE; } uint32_t zdr_READ3res (ZDR *zdrs, READ3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_READ3resok (zdrs, &objp->READ3res_u.resok)) return FALSE; break; default: if (!zdr_READ3resfail (zdrs, &objp->READ3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_FSINFO3args (ZDR *zdrs, FSINFO3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->fsroot)) return FALSE; return TRUE; } uint32_t zdr_FSINFO3resok (ZDR *zdrs, FSINFO3resok *objp) { register int32_t *buf; buf = NULL; if (zdrs->x_op == ZDR_ENCODE) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; buf = ZDR_INLINE (zdrs, 7 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->rtmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->rtpref)) return FALSE; if (!zdr_u_int (zdrs, &objp->rtmult)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtpref)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtmult)) return FALSE; if (!zdr_u_int (zdrs, &objp->dtpref)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->rtmax); IZDR_PUT_U_LONG(buf, objp->rtpref); IZDR_PUT_U_LONG(buf, objp->rtmult); IZDR_PUT_U_LONG(buf, objp->wtmax); IZDR_PUT_U_LONG(buf, objp->wtpref); IZDR_PUT_U_LONG(buf, objp->wtmult); IZDR_PUT_U_LONG(buf, objp->dtpref); } if (!zdr_size3 (zdrs, &objp->maxfilesize)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->time_delta)) return FALSE; if (!zdr_u_int (zdrs, &objp->properties)) return FALSE; return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; buf = ZDR_INLINE (zdrs, 7 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->rtmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->rtpref)) return FALSE; if (!zdr_u_int (zdrs, &objp->rtmult)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtpref)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtmult)) return FALSE; if (!zdr_u_int (zdrs, &objp->dtpref)) return FALSE; } else { objp->rtmax = IZDR_GET_U_LONG(buf); objp->rtpref = IZDR_GET_U_LONG(buf); objp->rtmult = IZDR_GET_U_LONG(buf); objp->wtmax = IZDR_GET_U_LONG(buf); objp->wtpref = IZDR_GET_U_LONG(buf); objp->wtmult = IZDR_GET_U_LONG(buf); objp->dtpref = IZDR_GET_U_LONG(buf); } if (!zdr_size3 (zdrs, &objp->maxfilesize)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->time_delta)) return FALSE; if (!zdr_u_int (zdrs, &objp->properties)) return FALSE; return TRUE; } if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_u_int (zdrs, &objp->rtmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->rtpref)) return FALSE; if (!zdr_u_int (zdrs, &objp->rtmult)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtpref)) return FALSE; if (!zdr_u_int (zdrs, &objp->wtmult)) return FALSE; if (!zdr_u_int (zdrs, &objp->dtpref)) return FALSE; if (!zdr_size3 (zdrs, &objp->maxfilesize)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->time_delta)) return FALSE; if (!zdr_u_int (zdrs, &objp->properties)) return FALSE; return TRUE; } uint32_t zdr_FSINFO3resfail (ZDR *zdrs, FSINFO3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_FSINFO3res (ZDR *zdrs, FSINFO3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_FSINFO3resok (zdrs, &objp->FSINFO3res_u.resok)) return FALSE; break; default: if (!zdr_FSINFO3resfail (zdrs, &objp->FSINFO3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_FSSTAT3args (ZDR *zdrs, FSSTAT3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->fsroot)) return FALSE; return TRUE; } uint32_t zdr_FSSTAT3resok (ZDR *zdrs, FSSTAT3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_size3 (zdrs, &objp->tbytes)) return FALSE; if (!zdr_size3 (zdrs, &objp->fbytes)) return FALSE; if (!zdr_size3 (zdrs, &objp->abytes)) return FALSE; if (!zdr_size3 (zdrs, &objp->tfiles)) return FALSE; if (!zdr_size3 (zdrs, &objp->ffiles)) return FALSE; if (!zdr_size3 (zdrs, &objp->afiles)) return FALSE; if (!zdr_u_int (zdrs, &objp->invarsec)) return FALSE; return TRUE; } uint32_t zdr_FSSTAT3resfail (ZDR *zdrs, FSSTAT3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_FSSTAT3res (ZDR *zdrs, FSSTAT3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_FSSTAT3resok (zdrs, &objp->FSSTAT3res_u.resok)) return FALSE; break; default: if (!zdr_FSSTAT3resfail (zdrs, &objp->FSSTAT3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_PATHCONF3args (ZDR *zdrs, PATHCONF3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->object)) return FALSE; return TRUE; } uint32_t zdr_PATHCONF3resok (ZDR *zdrs, PATHCONF3resok *objp) { register int32_t *buf; buf = NULL; if (zdrs->x_op == ZDR_ENCODE) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; buf = ZDR_INLINE (zdrs, 6 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->linkmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->name_max)) return FALSE; if (!zdr_bool (zdrs, &objp->no_trunc)) return FALSE; if (!zdr_bool (zdrs, &objp->chown_restricted)) return FALSE; if (!zdr_bool (zdrs, &objp->case_insensitive)) return FALSE; if (!zdr_bool (zdrs, &objp->case_preserving)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->linkmax); IZDR_PUT_U_LONG(buf, objp->name_max); IZDR_PUT_BOOL(buf, objp->no_trunc); IZDR_PUT_BOOL(buf, objp->chown_restricted); IZDR_PUT_BOOL(buf, objp->case_insensitive); IZDR_PUT_BOOL(buf, objp->case_preserving); } return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; buf = ZDR_INLINE (zdrs, 6 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->linkmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->name_max)) return FALSE; if (!zdr_bool (zdrs, &objp->no_trunc)) return FALSE; if (!zdr_bool (zdrs, &objp->chown_restricted)) return FALSE; if (!zdr_bool (zdrs, &objp->case_insensitive)) return FALSE; if (!zdr_bool (zdrs, &objp->case_preserving)) return FALSE; } else { objp->linkmax = IZDR_GET_U_LONG(buf); objp->name_max = IZDR_GET_U_LONG(buf); objp->no_trunc = IZDR_GET_BOOL(buf); objp->chown_restricted = IZDR_GET_BOOL(buf); objp->case_insensitive = IZDR_GET_BOOL(buf); objp->case_preserving = IZDR_GET_BOOL(buf); } return TRUE; } if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_u_int (zdrs, &objp->linkmax)) return FALSE; if (!zdr_u_int (zdrs, &objp->name_max)) return FALSE; if (!zdr_bool (zdrs, &objp->no_trunc)) return FALSE; if (!zdr_bool (zdrs, &objp->chown_restricted)) return FALSE; if (!zdr_bool (zdrs, &objp->case_insensitive)) return FALSE; if (!zdr_bool (zdrs, &objp->case_preserving)) return FALSE; return TRUE; } uint32_t zdr_PATHCONF3resfail (ZDR *zdrs, PATHCONF3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_PATHCONF3res (ZDR *zdrs, PATHCONF3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_PATHCONF3resok (zdrs, &objp->PATHCONF3res_u.resok)) return FALSE; break; default: if (!zdr_PATHCONF3resfail (zdrs, &objp->PATHCONF3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_nfspath3 (ZDR *zdrs, nfspath3 *objp) { if (!zdr_string (zdrs, objp, ~0)) return FALSE; return TRUE; } uint32_t zdr_symlinkdata3 (ZDR *zdrs, symlinkdata3 *objp) { if (!zdr_sattr3 (zdrs, &objp->symlink_attributes)) return FALSE; if (!zdr_nfspath3 (zdrs, &objp->symlink_data)) return FALSE; return TRUE; } uint32_t zdr_SYMLINK3args (ZDR *zdrs, SYMLINK3args *objp) { if (!zdr_diropargs3 (zdrs, &objp->where)) return FALSE; if (!zdr_symlinkdata3 (zdrs, &objp->symlink)) return FALSE; return TRUE; } uint32_t zdr_SYMLINK3resok (ZDR *zdrs, SYMLINK3resok *objp) { if (!zdr_post_op_fh3 (zdrs, &objp->obj)) return FALSE; if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_SYMLINK3resfail (ZDR *zdrs, SYMLINK3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_SYMLINK3res (ZDR *zdrs, SYMLINK3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_SYMLINK3resok (zdrs, &objp->SYMLINK3res_u.resok)) return FALSE; break; default: if (!zdr_SYMLINK3resfail (zdrs, &objp->SYMLINK3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_READLINK3args (ZDR *zdrs, READLINK3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->symlink)) return FALSE; return TRUE; } uint32_t zdr_READLINK3resok (ZDR *zdrs, READLINK3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->symlink_attributes)) return FALSE; if (!zdr_nfspath3 (zdrs, &objp->data)) return FALSE; return TRUE; } uint32_t zdr_READLINK3resfail (ZDR *zdrs, READLINK3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->symlink_attributes)) return FALSE; return TRUE; } uint32_t zdr_READLINK3res (ZDR *zdrs, READLINK3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_READLINK3resok (zdrs, &objp->READLINK3res_u.resok)) return FALSE; break; default: if (!zdr_READLINK3resfail (zdrs, &objp->READLINK3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_devicedata3 (ZDR *zdrs, devicedata3 *objp) { if (!zdr_sattr3 (zdrs, &objp->dev_attributes)) return FALSE; if (!zdr_specdata3 (zdrs, &objp->spec)) return FALSE; return TRUE; } uint32_t zdr_mknoddata3 (ZDR *zdrs, mknoddata3 *objp) { if (!zdr_ftype3 (zdrs, &objp->type)) return FALSE; switch (objp->type) { case NF3CHR: if (!zdr_devicedata3 (zdrs, &objp->mknoddata3_u.chr_device)) return FALSE; break; case NF3BLK: if (!zdr_devicedata3 (zdrs, &objp->mknoddata3_u.blk_device)) return FALSE; break; case NF3SOCK: if (!zdr_sattr3 (zdrs, &objp->mknoddata3_u.sock_attributes)) return FALSE; break; case NF3FIFO: if (!zdr_sattr3 (zdrs, &objp->mknoddata3_u.pipe_attributes)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_MKNOD3args (ZDR *zdrs, MKNOD3args *objp) { if (!zdr_diropargs3 (zdrs, &objp->where)) return FALSE; if (!zdr_mknoddata3 (zdrs, &objp->what)) return FALSE; return TRUE; } uint32_t zdr_MKNOD3resok (ZDR *zdrs, MKNOD3resok *objp) { if (!zdr_post_op_fh3 (zdrs, &objp->obj)) return FALSE; if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_MKNOD3resfail (ZDR *zdrs, MKNOD3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_MKNOD3res (ZDR *zdrs, MKNOD3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_MKNOD3resok (zdrs, &objp->MKNOD3res_u.resok)) return FALSE; break; default: if (!zdr_MKNOD3resfail (zdrs, &objp->MKNOD3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_MKDIR3args (ZDR *zdrs, MKDIR3args *objp) { if (!zdr_diropargs3 (zdrs, &objp->where)) return FALSE; if (!zdr_sattr3 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_MKDIR3resok (ZDR *zdrs, MKDIR3resok *objp) { if (!zdr_post_op_fh3 (zdrs, &objp->obj)) return FALSE; if (!zdr_post_op_attr (zdrs, &objp->obj_attributes)) return FALSE; if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_MKDIR3resfail (ZDR *zdrs, MKDIR3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_MKDIR3res (ZDR *zdrs, MKDIR3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_MKDIR3resok (zdrs, &objp->MKDIR3res_u.resok)) return FALSE; break; default: if (!zdr_MKDIR3resfail (zdrs, &objp->MKDIR3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_RMDIR3args (ZDR *zdrs, RMDIR3args *objp) { if (!zdr_diropargs3 (zdrs, &objp->object)) return FALSE; return TRUE; } uint32_t zdr_RMDIR3resok (ZDR *zdrs, RMDIR3resok *objp) { if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_RMDIR3resfail (ZDR *zdrs, RMDIR3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->dir_wcc)) return FALSE; return TRUE; } uint32_t zdr_RMDIR3res (ZDR *zdrs, RMDIR3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_RMDIR3resok (zdrs, &objp->RMDIR3res_u.resok)) return FALSE; break; default: if (!zdr_RMDIR3resfail (zdrs, &objp->RMDIR3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_RENAME3args (ZDR *zdrs, RENAME3args *objp) { if (!zdr_diropargs3 (zdrs, &objp->from)) return FALSE; if (!zdr_diropargs3 (zdrs, &objp->to)) return FALSE; return TRUE; } uint32_t zdr_RENAME3resok (ZDR *zdrs, RENAME3resok *objp) { if (!zdr_wcc_data (zdrs, &objp->fromdir_wcc)) return FALSE; if (!zdr_wcc_data (zdrs, &objp->todir_wcc)) return FALSE; return TRUE; } uint32_t zdr_RENAME3resfail (ZDR *zdrs, RENAME3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->fromdir_wcc)) return FALSE; if (!zdr_wcc_data (zdrs, &objp->todir_wcc)) return FALSE; return TRUE; } uint32_t zdr_RENAME3res (ZDR *zdrs, RENAME3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_RENAME3resok (zdrs, &objp->RENAME3res_u.resok)) return FALSE; break; default: if (!zdr_RENAME3resfail (zdrs, &objp->RENAME3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_READDIRPLUS3args (ZDR *zdrs, READDIRPLUS3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->dir)) return FALSE; if (!zdr_cookie3 (zdrs, &objp->cookie)) return FALSE; if (!zdr_cookieverf3 (zdrs, objp->cookieverf)) return FALSE; if (!zdr_count3 (zdrs, &objp->dircount)) return FALSE; if (!zdr_count3 (zdrs, &objp->maxcount)) return FALSE; return TRUE; } uint32_t zdr_entryplus3 (ZDR *zdrs, entryplus3 *objp) { if (!zdr_fileid3 (zdrs, &objp->fileid)) return FALSE; if (!zdr_filename3 (zdrs, &objp->name)) return FALSE; if (!zdr_cookie3 (zdrs, &objp->cookie)) return FALSE; if (!zdr_post_op_attr (zdrs, &objp->name_attributes)) return FALSE; if (!zdr_post_op_fh3 (zdrs, &objp->name_handle)) return FALSE; if (!zdr_pointer (zdrs, (char **)&objp->nextentry, sizeof (entryplus3), (zdrproc_t) zdr_entryplus3)) return FALSE; return TRUE; } uint32_t zdr_dirlistplus3 (ZDR *zdrs, dirlistplus3 *objp) { if (!zdr_pointer (zdrs, (char **)&objp->entries, sizeof (entryplus3), (zdrproc_t) zdr_entryplus3)) return FALSE; if (!zdr_bool (zdrs, &objp->eof)) return FALSE; return TRUE; } uint32_t zdr_READDIRPLUS3resok (ZDR *zdrs, READDIRPLUS3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->dir_attributes)) return FALSE; if (!zdr_cookieverf3 (zdrs, objp->cookieverf)) return FALSE; if (!zdr_dirlistplus3 (zdrs, &objp->reply)) return FALSE; return TRUE; } uint32_t zdr_READDIRPLUS3resfail (ZDR *zdrs, READDIRPLUS3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->dir_attributes)) return FALSE; return TRUE; } uint32_t zdr_READDIRPLUS3res (ZDR *zdrs, READDIRPLUS3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_READDIRPLUS3resok (zdrs, &objp->READDIRPLUS3res_u.resok)) return FALSE; break; default: if (!zdr_READDIRPLUS3resfail (zdrs, &objp->READDIRPLUS3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_READDIR3args (ZDR *zdrs, READDIR3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->dir)) return FALSE; if (!zdr_cookie3 (zdrs, &objp->cookie)) return FALSE; if (!zdr_cookieverf3 (zdrs, objp->cookieverf)) return FALSE; if (!zdr_count3 (zdrs, &objp->count)) return FALSE; return TRUE; } uint32_t zdr_entry3 (ZDR *zdrs, entry3 *objp) { if (!zdr_fileid3 (zdrs, &objp->fileid)) return FALSE; if (!zdr_filename3 (zdrs, &objp->name)) return FALSE; if (!zdr_cookie3 (zdrs, &objp->cookie)) return FALSE; if (!zdr_pointer (zdrs, (char **)&objp->nextentry, sizeof (entry3), (zdrproc_t) zdr_entry3)) return FALSE; return TRUE; } uint32_t zdr_dirlist3 (ZDR *zdrs, dirlist3 *objp) { if (!zdr_pointer (zdrs, (char **)&objp->entries, sizeof (entry3), (zdrproc_t) zdr_entry3)) return FALSE; if (!zdr_bool (zdrs, &objp->eof)) return FALSE; return TRUE; } uint32_t zdr_READDIR3resok (ZDR *zdrs, READDIR3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->dir_attributes)) return FALSE; if (!zdr_cookieverf3 (zdrs, objp->cookieverf)) return FALSE; if (!zdr_dirlist3 (zdrs, &objp->reply)) return FALSE; return TRUE; } uint32_t zdr_READDIR3resfail (ZDR *zdrs, READDIR3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->dir_attributes)) return FALSE; return TRUE; } uint32_t zdr_READDIR3res (ZDR *zdrs, READDIR3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_READDIR3resok (zdrs, &objp->READDIR3res_u.resok)) return FALSE; break; default: if (!zdr_READDIR3resfail (zdrs, &objp->READDIR3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_LINK3args (ZDR *zdrs, LINK3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->file)) return FALSE; if (!zdr_diropargs3 (zdrs, &objp->link)) return FALSE; return TRUE; } uint32_t zdr_LINK3resok (ZDR *zdrs, LINK3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->file_attributes)) return FALSE; if (!zdr_wcc_data (zdrs, &objp->linkdir_wcc)) return FALSE; return TRUE; } uint32_t zdr_LINK3resfail (ZDR *zdrs, LINK3resfail *objp) { if (!zdr_post_op_attr (zdrs, &objp->file_attributes)) return FALSE; if (!zdr_wcc_data (zdrs, &objp->linkdir_wcc)) return FALSE; return TRUE; } uint32_t zdr_LINK3res (ZDR *zdrs, LINK3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_LINK3resok (zdrs, &objp->LINK3res_u.resok)) return FALSE; break; default: if (!zdr_LINK3resfail (zdrs, &objp->LINK3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_sattrguard3 (ZDR *zdrs, sattrguard3 *objp) { if (!zdr_bool (zdrs, &objp->check)) return FALSE; switch (objp->check) { case TRUE: if (!zdr_nfstime3 (zdrs, &objp->sattrguard3_u.obj_ctime)) return FALSE; break; case FALSE: break; default: return FALSE; } return TRUE; } uint32_t zdr_SETATTR3args (ZDR *zdrs, SETATTR3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->object)) return FALSE; if (!zdr_sattr3 (zdrs, &objp->new_attributes)) return FALSE; if (!zdr_sattrguard3 (zdrs, &objp->guard)) return FALSE; return TRUE; } uint32_t zdr_SETATTR3resok (ZDR *zdrs, SETATTR3resok *objp) { if (!zdr_wcc_data (zdrs, &objp->obj_wcc)) return FALSE; return TRUE; } uint32_t zdr_SETATTR3resfail (ZDR *zdrs, SETATTR3resfail *objp) { if (!zdr_wcc_data (zdrs, &objp->obj_wcc)) return FALSE; return TRUE; } uint32_t zdr_SETATTR3res (ZDR *zdrs, SETATTR3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_SETATTR3resok (zdrs, &objp->SETATTR3res_u.resok)) return FALSE; break; default: if (!zdr_SETATTR3resfail (zdrs, &objp->SETATTR3res_u.resfail)) return FALSE; break; } return TRUE; } uint32_t zdr_fhandle2 (ZDR *zdrs, fhandle2 objp) { if (!zdr_opaque (zdrs, objp, FHSIZE2)) return FALSE; return TRUE; } uint32_t zdr_ftype2 (ZDR *zdrs, ftype2 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_fattr2 (ZDR *zdrs, fattr2 *objp) { register int32_t *buf; buf = NULL; if (zdrs->x_op == ZDR_ENCODE) { if (!zdr_ftype2 (zdrs, &objp->type)) return FALSE; buf = ZDR_INLINE (zdrs, 10 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->mode)) return FALSE; if (!zdr_u_int (zdrs, &objp->nlink)) return FALSE; if (!zdr_u_int (zdrs, &objp->uid)) return FALSE; if (!zdr_u_int (zdrs, &objp->gid)) return FALSE; if (!zdr_u_int (zdrs, &objp->size)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocksize)) return FALSE; if (!zdr_u_int (zdrs, &objp->rdev)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocks)) return FALSE; if (!zdr_u_int (zdrs, &objp->fsid)) return FALSE; if (!zdr_u_int (zdrs, &objp->fileid)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->mode); IZDR_PUT_U_LONG(buf, objp->nlink); IZDR_PUT_U_LONG(buf, objp->uid); IZDR_PUT_U_LONG(buf, objp->gid); IZDR_PUT_U_LONG(buf, objp->size); IZDR_PUT_U_LONG(buf, objp->blocksize); IZDR_PUT_U_LONG(buf, objp->rdev); IZDR_PUT_U_LONG(buf, objp->blocks); IZDR_PUT_U_LONG(buf, objp->fsid); IZDR_PUT_U_LONG(buf, objp->fileid); } if (!zdr_nfstime3 (zdrs, &objp->atime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->mtime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->ctime)) return FALSE; return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { if (!zdr_ftype2 (zdrs, &objp->type)) return FALSE; buf = ZDR_INLINE (zdrs, 10 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->mode)) return FALSE; if (!zdr_u_int (zdrs, &objp->nlink)) return FALSE; if (!zdr_u_int (zdrs, &objp->uid)) return FALSE; if (!zdr_u_int (zdrs, &objp->gid)) return FALSE; if (!zdr_u_int (zdrs, &objp->size)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocksize)) return FALSE; if (!zdr_u_int (zdrs, &objp->rdev)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocks)) return FALSE; if (!zdr_u_int (zdrs, &objp->fsid)) return FALSE; if (!zdr_u_int (zdrs, &objp->fileid)) return FALSE; } else { objp->mode = IZDR_GET_U_LONG(buf); objp->nlink = IZDR_GET_U_LONG(buf); objp->uid = IZDR_GET_U_LONG(buf); objp->gid = IZDR_GET_U_LONG(buf); objp->size = IZDR_GET_U_LONG(buf); objp->blocksize = IZDR_GET_U_LONG(buf); objp->rdev = IZDR_GET_U_LONG(buf); objp->blocks = IZDR_GET_U_LONG(buf); objp->fsid = IZDR_GET_U_LONG(buf); objp->fileid = IZDR_GET_U_LONG(buf); } if (!zdr_nfstime3 (zdrs, &objp->atime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->mtime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->ctime)) return FALSE; return TRUE; } if (!zdr_ftype2 (zdrs, &objp->type)) return FALSE; if (!zdr_u_int (zdrs, &objp->mode)) return FALSE; if (!zdr_u_int (zdrs, &objp->nlink)) return FALSE; if (!zdr_u_int (zdrs, &objp->uid)) return FALSE; if (!zdr_u_int (zdrs, &objp->gid)) return FALSE; if (!zdr_u_int (zdrs, &objp->size)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocksize)) return FALSE; if (!zdr_u_int (zdrs, &objp->rdev)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocks)) return FALSE; if (!zdr_u_int (zdrs, &objp->fsid)) return FALSE; if (!zdr_u_int (zdrs, &objp->fileid)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->atime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->mtime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->ctime)) return FALSE; return TRUE; } uint32_t zdr_sattr2 (ZDR *zdrs, sattr2 *objp) { register int32_t *buf; buf = NULL; if (zdrs->x_op == ZDR_ENCODE) { buf = ZDR_INLINE (zdrs, 4 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->mode)) return FALSE; if (!zdr_u_int (zdrs, &objp->uid)) return FALSE; if (!zdr_u_int (zdrs, &objp->gid)) return FALSE; if (!zdr_u_int (zdrs, &objp->size)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->mode); IZDR_PUT_U_LONG(buf, objp->uid); IZDR_PUT_U_LONG(buf, objp->gid); IZDR_PUT_U_LONG(buf, objp->size); } if (!zdr_nfstime3 (zdrs, &objp->atime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->mtime)) return FALSE; return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { buf = ZDR_INLINE (zdrs, 4 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->mode)) return FALSE; if (!zdr_u_int (zdrs, &objp->uid)) return FALSE; if (!zdr_u_int (zdrs, &objp->gid)) return FALSE; if (!zdr_u_int (zdrs, &objp->size)) return FALSE; } else { objp->mode = IZDR_GET_U_LONG(buf); objp->uid = IZDR_GET_U_LONG(buf); objp->gid = IZDR_GET_U_LONG(buf); objp->size = IZDR_GET_U_LONG(buf); } if (!zdr_nfstime3 (zdrs, &objp->atime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->mtime)) return FALSE; return TRUE; } if (!zdr_u_int (zdrs, &objp->mode)) return FALSE; if (!zdr_u_int (zdrs, &objp->uid)) return FALSE; if (!zdr_u_int (zdrs, &objp->gid)) return FALSE; if (!zdr_u_int (zdrs, &objp->size)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->atime)) return FALSE; if (!zdr_nfstime3 (zdrs, &objp->mtime)) return FALSE; return TRUE; } uint32_t zdr_filename2 (ZDR *zdrs, filename2 *objp) { if (!zdr_string (zdrs, objp, MAXNAMLEN2)) return FALSE; return TRUE; } uint32_t zdr_path2 (ZDR *zdrs, path2 *objp) { if (!zdr_string (zdrs, objp, MAXPATHLEN2)) return FALSE; return TRUE; } uint32_t zdr_nfsdata2 (ZDR *zdrs, nfsdata2 *objp) { if (!zdr_bytes (zdrs, (char **)&objp->nfsdata2_val, (u_int *) &objp->nfsdata2_len, NFSMAXDATA2)) return FALSE; return TRUE; } uint32_t zdr_nfscookie2 (ZDR *zdrs, nfscookie2 objp) { if (!zdr_opaque (zdrs, objp, NFSCOOKIESIZE2)) return FALSE; return TRUE; } uint32_t zdr_entry2 (ZDR *zdrs, entry2 *objp) { if (!zdr_u_int (zdrs, &objp->fileid)) return FALSE; if (!zdr_filename2 (zdrs, &objp->name)) return FALSE; if (!zdr_nfscookie2 (zdrs, objp->cookie)) return FALSE; if (!zdr_pointer (zdrs, (char **)&objp->nextentry, sizeof (entry2), (zdrproc_t) zdr_entry2)) return FALSE; return TRUE; } uint32_t zdr_diropargs2 (ZDR *zdrs, diropargs2 *objp) { if (!zdr_fhandle2 (zdrs, objp->dir)) return FALSE; if (!zdr_filename2 (zdrs, &objp->name)) return FALSE; return TRUE; } uint32_t zdr_GETATTR2args (ZDR *zdrs, GETATTR2args *objp) { if (!zdr_fhandle2 (zdrs, objp->fhandle)) return FALSE; return TRUE; } uint32_t zdr_GETATTR2resok (ZDR *zdrs, GETATTR2resok *objp) { if (!zdr_fattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_GETATTR2res (ZDR *zdrs, GETATTR2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_GETATTR2resok (zdrs, &objp->GETATTR2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_SETATTR2args (ZDR *zdrs, SETATTR2args *objp) { if (!zdr_fhandle2 (zdrs, objp->fhandle)) return FALSE; if (!zdr_sattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_SETATTR2resok (ZDR *zdrs, SETATTR2resok *objp) { if (!zdr_fattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_SETATTR2res (ZDR *zdrs, SETATTR2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_SETATTR2resok (zdrs, &objp->SETATTR2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_LOOKUP2args (ZDR *zdrs, LOOKUP2args *objp) { if (!zdr_diropargs2 (zdrs, &objp->what)) return FALSE; return TRUE; } uint32_t zdr_LOOKUP2resok (ZDR *zdrs, LOOKUP2resok *objp) { if (!zdr_fhandle2 (zdrs, objp->file)) return FALSE; if (!zdr_fattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_LOOKUP2res (ZDR *zdrs, LOOKUP2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_LOOKUP2resok (zdrs, &objp->LOOKUP2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_READLINK2args (ZDR *zdrs, READLINK2args *objp) { if (!zdr_fhandle2 (zdrs, objp->file)) return FALSE; return TRUE; } uint32_t zdr_READLINK2resok (ZDR *zdrs, READLINK2resok *objp) { if (!zdr_path2 (zdrs, &objp->data)) return FALSE; return TRUE; } uint32_t zdr_READLINK2res (ZDR *zdrs, READLINK2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_READLINK2resok (zdrs, &objp->READLINK2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_READ2args (ZDR *zdrs, READ2args *objp) { if (!zdr_fhandle2 (zdrs, objp->file)) return FALSE; if (!zdr_u_int (zdrs, &objp->offset)) return FALSE; if (!zdr_u_int (zdrs, &objp->count)) return FALSE; if (!zdr_u_int (zdrs, &objp->totalcount)) return FALSE; return TRUE; } uint32_t zdr_READ2resok (ZDR *zdrs, READ2resok *objp) { if (!zdr_fattr2 (zdrs, &objp->attributes)) return FALSE; if (!zdr_nfsdata2 (zdrs, &objp->data)) return FALSE; return TRUE; } uint32_t zdr_READ2res (ZDR *zdrs, READ2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_READ2resok (zdrs, &objp->READ2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_WRITE2args (ZDR *zdrs, WRITE2args *objp) { register int32_t *buf; buf = NULL; if (zdrs->x_op == ZDR_ENCODE) { if (!zdr_fhandle2 (zdrs, objp->file)) return FALSE; buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->beginoffset)) return FALSE; if (!zdr_u_int (zdrs, &objp->offset)) return FALSE; if (!zdr_u_int (zdrs, &objp->totalcount)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->beginoffset); IZDR_PUT_U_LONG(buf, objp->offset); IZDR_PUT_U_LONG(buf, objp->totalcount); } if (!zdr_nfsdata2 (zdrs, &objp->data)) return FALSE; return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { if (!zdr_fhandle2 (zdrs, objp->file)) return FALSE; buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->beginoffset)) return FALSE; if (!zdr_u_int (zdrs, &objp->offset)) return FALSE; if (!zdr_u_int (zdrs, &objp->totalcount)) return FALSE; } else { objp->beginoffset = IZDR_GET_U_LONG(buf); objp->offset = IZDR_GET_U_LONG(buf); objp->totalcount = IZDR_GET_U_LONG(buf); } if (!zdr_nfsdata2 (zdrs, &objp->data)) return FALSE; return TRUE; } if (!zdr_fhandle2 (zdrs, objp->file)) return FALSE; if (!zdr_u_int (zdrs, &objp->beginoffset)) return FALSE; if (!zdr_u_int (zdrs, &objp->offset)) return FALSE; if (!zdr_u_int (zdrs, &objp->totalcount)) return FALSE; if (!zdr_nfsdata2 (zdrs, &objp->data)) return FALSE; return TRUE; } uint32_t zdr_WRITE2resok (ZDR *zdrs, WRITE2resok *objp) { if (!zdr_fattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_WRITE2res (ZDR *zdrs, WRITE2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_WRITE2resok (zdrs, &objp->WRITE2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_CREATE2args (ZDR *zdrs, CREATE2args *objp) { if (!zdr_diropargs2 (zdrs, &objp->where)) return FALSE; if (!zdr_sattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_CREATE2resok (ZDR *zdrs, CREATE2resok *objp) { if (!zdr_fhandle2 (zdrs, objp->file)) return FALSE; if (!zdr_fattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_CREATE2res (ZDR *zdrs, CREATE2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_CREATE2resok (zdrs, &objp->CREATE2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_REMOVE2args (ZDR *zdrs, REMOVE2args *objp) { if (!zdr_diropargs2 (zdrs, &objp->what)) return FALSE; return TRUE; } uint32_t zdr_REMOVE2res (ZDR *zdrs, REMOVE2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_RENAME2args (ZDR *zdrs, RENAME2args *objp) { if (!zdr_diropargs2 (zdrs, &objp->from)) return FALSE; if (!zdr_diropargs2 (zdrs, &objp->to)) return FALSE; return TRUE; } uint32_t zdr_RENAME2res (ZDR *zdrs, RENAME2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_LINK2args (ZDR *zdrs, LINK2args *objp) { if (!zdr_fhandle2 (zdrs, objp->from)) return FALSE; if (!zdr_diropargs2 (zdrs, &objp->to)) return FALSE; return TRUE; } uint32_t zdr_LINK2res (ZDR *zdrs, LINK2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_SYMLINK2args (ZDR *zdrs, SYMLINK2args *objp) { if (!zdr_diropargs2 (zdrs, &objp->from)) return FALSE; if (!zdr_path2 (zdrs, &objp->to)) return FALSE; if (!zdr_sattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_SYMLINK2res (ZDR *zdrs, SYMLINK2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_MKDIR2args (ZDR *zdrs, MKDIR2args *objp) { if (!zdr_diropargs2 (zdrs, &objp->where)) return FALSE; if (!zdr_sattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_MKDIR2resok (ZDR *zdrs, MKDIR2resok *objp) { if (!zdr_fhandle2 (zdrs, objp->file)) return FALSE; if (!zdr_fattr2 (zdrs, &objp->attributes)) return FALSE; return TRUE; } uint32_t zdr_MKDIR2res (ZDR *zdrs, MKDIR2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_MKDIR2resok (zdrs, &objp->MKDIR2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_RMDIR2args (ZDR *zdrs, RMDIR2args *objp) { if (!zdr_diropargs2 (zdrs, &objp->what)) return FALSE; return TRUE; } uint32_t zdr_RMDIR2res (ZDR *zdrs, RMDIR2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_READDIR2args (ZDR *zdrs, READDIR2args *objp) { if (!zdr_fhandle2 (zdrs, objp->dir)) return FALSE; if (!zdr_nfscookie2 (zdrs, objp->cookie)) return FALSE; if (!zdr_u_int (zdrs, &objp->count)) return FALSE; return TRUE; } uint32_t zdr_READDIR2resok (ZDR *zdrs, READDIR2resok *objp) { if (!zdr_pointer (zdrs, (char **)&objp->entries, sizeof (entry2), (zdrproc_t) zdr_entry2)) return FALSE; if (!zdr_bool (zdrs, &objp->eof)) return FALSE; return TRUE; } uint32_t zdr_READDIR2res (ZDR *zdrs, READDIR2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_READDIR2resok (zdrs, &objp->READDIR2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_STATFS2args (ZDR *zdrs, STATFS2args *objp) { if (!zdr_fhandle2 (zdrs, objp->dir)) return FALSE; return TRUE; } uint32_t zdr_STATFS2resok (ZDR *zdrs, STATFS2resok *objp) { register int32_t *buf; buf = NULL; if (zdrs->x_op == ZDR_ENCODE) { buf = ZDR_INLINE (zdrs, 5 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->tsize)) return FALSE; if (!zdr_u_int (zdrs, &objp->bsize)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocks)) return FALSE; if (!zdr_u_int (zdrs, &objp->bfree)) return FALSE; if (!zdr_u_int (zdrs, &objp->bavail)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->tsize); IZDR_PUT_U_LONG(buf, objp->bsize); IZDR_PUT_U_LONG(buf, objp->blocks); IZDR_PUT_U_LONG(buf, objp->bfree); IZDR_PUT_U_LONG(buf, objp->bavail); } return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { buf = ZDR_INLINE (zdrs, 5 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->tsize)) return FALSE; if (!zdr_u_int (zdrs, &objp->bsize)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocks)) return FALSE; if (!zdr_u_int (zdrs, &objp->bfree)) return FALSE; if (!zdr_u_int (zdrs, &objp->bavail)) return FALSE; } else { objp->tsize = IZDR_GET_U_LONG(buf); objp->bsize = IZDR_GET_U_LONG(buf); objp->blocks = IZDR_GET_U_LONG(buf); objp->bfree = IZDR_GET_U_LONG(buf); objp->bavail = IZDR_GET_U_LONG(buf); } return TRUE; } if (!zdr_u_int (zdrs, &objp->tsize)) return FALSE; if (!zdr_u_int (zdrs, &objp->bsize)) return FALSE; if (!zdr_u_int (zdrs, &objp->blocks)) return FALSE; if (!zdr_u_int (zdrs, &objp->bfree)) return FALSE; if (!zdr_u_int (zdrs, &objp->bavail)) return FALSE; return TRUE; } uint32_t zdr_STATFS2res (ZDR *zdrs, STATFS2res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_STATFS2resok (zdrs, &objp->STATFS2res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_nfsacl_type (ZDR *zdrs, nfsacl_type *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_nfsacl_ace (ZDR *zdrs, nfsacl_ace *objp) { if (!zdr_nfsacl_type (zdrs, &objp->type)) return FALSE; if (!zdr_u_int (zdrs, &objp->id)) return FALSE; if (!zdr_u_int (zdrs, &objp->perm)) return FALSE; return TRUE; } uint32_t zdr_GETACL3args (ZDR *zdrs, GETACL3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->dir)) return FALSE; if (!zdr_u_int (zdrs, &objp->mask)) return FALSE; return TRUE; } uint32_t zdr_GETACL3resok (ZDR *zdrs, GETACL3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->attr)) return FALSE; if (!zdr_u_int (zdrs, &objp->mask)) return FALSE; if (!zdr_u_int (zdrs, &objp->ace_count)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->ace.ace_val, (u_int *) &objp->ace.ace_len, ~0, sizeof (nfsacl_ace), (zdrproc_t) zdr_nfsacl_ace)) return FALSE; if (!zdr_u_int (zdrs, &objp->default_ace_count)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->default_ace.default_ace_val, (u_int *) &objp->default_ace.default_ace_len, ~0, sizeof (nfsacl_ace), (zdrproc_t) zdr_nfsacl_ace)) return FALSE; return TRUE; } uint32_t zdr_GETACL3res (ZDR *zdrs, GETACL3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_GETACL3resok (zdrs, &objp->GETACL3res_u.resok)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_SETACL3args (ZDR *zdrs, SETACL3args *objp) { if (!zdr_nfs_fh3 (zdrs, &objp->dir)) return FALSE; if (!zdr_u_int (zdrs, &objp->mask)) return FALSE; if (!zdr_u_int (zdrs, &objp->ace_count)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->ace.ace_val, (u_int *) &objp->ace.ace_len, ~0, sizeof (nfsacl_ace), (zdrproc_t) zdr_nfsacl_ace)) return FALSE; if (!zdr_u_int (zdrs, &objp->default_ace_count)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->default_ace.default_ace_val, (u_int *) &objp->default_ace.default_ace_len, ~0, sizeof (nfsacl_ace), (zdrproc_t) zdr_nfsacl_ace)) return FALSE; return TRUE; } uint32_t zdr_SETACL3resok (ZDR *zdrs, SETACL3resok *objp) { if (!zdr_post_op_attr (zdrs, &objp->attr)) return FALSE; return TRUE; } uint32_t zdr_SETACL3res (ZDR *zdrs, SETACL3res *objp) { if (!zdr_nfsstat3 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS3_OK: if (!zdr_SETACL3resok (zdrs, &objp->SETACL3res_u.resok)) return FALSE; break; default: break; } return TRUE; } libnfs-libnfs-4.0.0/nfs/libnfs-raw-nfs.h000066400000000000000000001470621343063627400200540ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _NFS_H_RPCGEN #define _NFS_H_RPCGEN #include #include #ifdef __cplusplus extern "C" { #endif #define NFS3_FHSIZE 64 #define NFS3_WRITEVERFSIZE 8 #define NFS3_CREATEVERFSIZE 8 #define NFS3_COOKIEVERFSIZE 8 typedef char cookieverf3[NFS3_COOKIEVERFSIZE]; typedef uint64_t cookie3; struct nfs_fh3 { struct { u_int data_len; char *data_val; } data; }; typedef struct nfs_fh3 nfs_fh3; typedef char *filename3; struct diropargs3 { nfs_fh3 dir; filename3 name; }; typedef struct diropargs3 diropargs3; enum ftype3 { NF3REG = 1, NF3DIR = 2, NF3BLK = 3, NF3CHR = 4, NF3LNK = 5, NF3SOCK = 6, NF3FIFO = 7, }; typedef enum ftype3 ftype3; typedef u_int mode3; typedef u_int uid3; typedef u_int gid3; typedef uint64_t size3; typedef uint64_t fileid3; struct specdata3 { u_int specdata1; u_int specdata2; }; typedef struct specdata3 specdata3; struct nfstime3 { u_int seconds; u_int nseconds; }; typedef struct nfstime3 nfstime3; struct fattr3 { ftype3 type; mode3 mode; u_int nlink; uid3 uid; gid3 gid; size3 size; size3 used; specdata3 rdev; uint64_t fsid; fileid3 fileid; nfstime3 atime; nfstime3 mtime; nfstime3 ctime; }; typedef struct fattr3 fattr3; struct post_op_attr { uint32_t attributes_follow; union { fattr3 attributes; } post_op_attr_u; }; typedef struct post_op_attr post_op_attr; enum nfsstat3 { NFS3_OK = 0, NFS3ERR_PERM = 1, NFS3ERR_NOENT = 2, NFS3ERR_IO = 5, NFS3ERR_NXIO = 6, NFS3ERR_ACCES = 13, NFS3ERR_EXIST = 17, NFS3ERR_XDEV = 18, NFS3ERR_NODEV = 19, NFS3ERR_NOTDIR = 20, NFS3ERR_ISDIR = 21, NFS3ERR_INVAL = 22, NFS3ERR_FBIG = 27, NFS3ERR_NOSPC = 28, NFS3ERR_ROFS = 30, NFS3ERR_MLINK = 31, NFS3ERR_NAMETOOLONG = 63, NFS3ERR_NOTEMPTY = 66, NFS3ERR_DQUOT = 69, NFS3ERR_STALE = 70, NFS3ERR_REMOTE = 71, NFS3ERR_BADHANDLE = 10001, NFS3ERR_NOT_SYNC = 10002, NFS3ERR_BAD_COOKIE = 10003, NFS3ERR_NOTSUPP = 10004, NFS3ERR_TOOSMALL = 10005, NFS3ERR_SERVERFAULT = 10006, NFS3ERR_BADTYPE = 10007, NFS3ERR_JUKEBOX = 10008, }; typedef enum nfsstat3 nfsstat3; enum stable_how { UNSTABLE = 0, DATA_SYNC = 1, FILE_SYNC = 2, }; typedef enum stable_how stable_how; typedef uint64_t offset3; typedef u_int count3; struct wcc_attr { size3 size; nfstime3 mtime; nfstime3 ctime; }; typedef struct wcc_attr wcc_attr; struct pre_op_attr { uint32_t attributes_follow; union { wcc_attr attributes; } pre_op_attr_u; }; typedef struct pre_op_attr pre_op_attr; struct wcc_data { pre_op_attr before; post_op_attr after; }; typedef struct wcc_data wcc_data; struct WRITE3args { nfs_fh3 file; offset3 offset; count3 count; stable_how stable; struct { u_int data_len; char *data_val; } data; }; typedef struct WRITE3args WRITE3args; typedef char writeverf3[NFS3_WRITEVERFSIZE]; struct WRITE3resok { wcc_data file_wcc; count3 count; stable_how committed; writeverf3 verf; }; typedef struct WRITE3resok WRITE3resok; struct WRITE3resfail { wcc_data file_wcc; }; typedef struct WRITE3resfail WRITE3resfail; struct WRITE3res { nfsstat3 status; union { WRITE3resok resok; WRITE3resfail resfail; } WRITE3res_u; }; typedef struct WRITE3res WRITE3res; struct LOOKUP3args { diropargs3 what; }; typedef struct LOOKUP3args LOOKUP3args; struct LOOKUP3resok { nfs_fh3 object; post_op_attr obj_attributes; post_op_attr dir_attributes; }; typedef struct LOOKUP3resok LOOKUP3resok; struct LOOKUP3resfail { post_op_attr dir_attributes; }; typedef struct LOOKUP3resfail LOOKUP3resfail; struct LOOKUP3res { nfsstat3 status; union { LOOKUP3resok resok; LOOKUP3resfail resfail; } LOOKUP3res_u; }; typedef struct LOOKUP3res LOOKUP3res; struct COMMIT3args { nfs_fh3 file; offset3 offset; count3 count; }; typedef struct COMMIT3args COMMIT3args; struct COMMIT3resok { wcc_data file_wcc; writeverf3 verf; }; typedef struct COMMIT3resok COMMIT3resok; struct COMMIT3resfail { wcc_data file_wcc; }; typedef struct COMMIT3resfail COMMIT3resfail; struct COMMIT3res { nfsstat3 status; union { COMMIT3resok resok; COMMIT3resfail resfail; } COMMIT3res_u; }; typedef struct COMMIT3res COMMIT3res; #define ACCESS3_READ 0x0001 #define ACCESS3_LOOKUP 0x0002 #define ACCESS3_MODIFY 0x0004 #define ACCESS3_EXTEND 0x0008 #define ACCESS3_DELETE 0x0010 #define ACCESS3_EXECUTE 0x0020 struct ACCESS3args { nfs_fh3 object; u_int access; }; typedef struct ACCESS3args ACCESS3args; struct ACCESS3resok { post_op_attr obj_attributes; u_int access; }; typedef struct ACCESS3resok ACCESS3resok; struct ACCESS3resfail { post_op_attr obj_attributes; }; typedef struct ACCESS3resfail ACCESS3resfail; struct ACCESS3res { nfsstat3 status; union { ACCESS3resok resok; ACCESS3resfail resfail; } ACCESS3res_u; }; typedef struct ACCESS3res ACCESS3res; struct GETATTR3args { nfs_fh3 object; }; typedef struct GETATTR3args GETATTR3args; struct GETATTR3resok { fattr3 obj_attributes; }; typedef struct GETATTR3resok GETATTR3resok; struct GETATTR3res { nfsstat3 status; union { GETATTR3resok resok; } GETATTR3res_u; }; typedef struct GETATTR3res GETATTR3res; enum time_how { DONT_CHANGE = 0, SET_TO_SERVER_TIME = 1, SET_TO_CLIENT_TIME = 2, }; typedef enum time_how time_how; struct set_mode3 { uint32_t set_it; union { mode3 mode; } set_mode3_u; }; typedef struct set_mode3 set_mode3; struct set_uid3 { uint32_t set_it; union { uid3 uid; } set_uid3_u; }; typedef struct set_uid3 set_uid3; struct set_gid3 { uint32_t set_it; union { gid3 gid; } set_gid3_u; }; typedef struct set_gid3 set_gid3; struct set_size3 { uint32_t set_it; union { size3 size; } set_size3_u; }; typedef struct set_size3 set_size3; struct set_atime { time_how set_it; union { nfstime3 atime; } set_atime_u; }; typedef struct set_atime set_atime; struct set_mtime { time_how set_it; union { nfstime3 mtime; } set_mtime_u; }; typedef struct set_mtime set_mtime; struct sattr3 { set_mode3 mode; set_uid3 uid; set_gid3 gid; set_size3 size; set_atime atime; set_mtime mtime; }; typedef struct sattr3 sattr3; enum createmode3 { UNCHECKED = 0, GUARDED = 1, EXCLUSIVE = 2, }; typedef enum createmode3 createmode3; typedef char createverf3[NFS3_CREATEVERFSIZE]; struct createhow3 { createmode3 mode; union { sattr3 obj_attributes; sattr3 g_obj_attributes; createverf3 verf; } createhow3_u; }; typedef struct createhow3 createhow3; struct CREATE3args { diropargs3 where; createhow3 how; }; typedef struct CREATE3args CREATE3args; struct post_op_fh3 { uint32_t handle_follows; union { nfs_fh3 handle; } post_op_fh3_u; }; typedef struct post_op_fh3 post_op_fh3; struct CREATE3resok { post_op_fh3 obj; post_op_attr obj_attributes; wcc_data dir_wcc; }; typedef struct CREATE3resok CREATE3resok; struct CREATE3resfail { wcc_data dir_wcc; }; typedef struct CREATE3resfail CREATE3resfail; struct CREATE3res { nfsstat3 status; union { CREATE3resok resok; CREATE3resfail resfail; } CREATE3res_u; }; typedef struct CREATE3res CREATE3res; struct REMOVE3args { diropargs3 object; }; typedef struct REMOVE3args REMOVE3args; struct REMOVE3resok { wcc_data dir_wcc; }; typedef struct REMOVE3resok REMOVE3resok; struct REMOVE3resfail { wcc_data dir_wcc; }; typedef struct REMOVE3resfail REMOVE3resfail; struct REMOVE3res { nfsstat3 status; union { REMOVE3resok resok; REMOVE3resfail resfail; } REMOVE3res_u; }; typedef struct REMOVE3res REMOVE3res; struct READ3args { nfs_fh3 file; offset3 offset; count3 count; }; typedef struct READ3args READ3args; struct READ3resok { post_op_attr file_attributes; count3 count; uint32_t eof; struct { u_int data_len; char *data_val; } data; }; typedef struct READ3resok READ3resok; struct READ3resfail { post_op_attr file_attributes; }; typedef struct READ3resfail READ3resfail; struct READ3res { nfsstat3 status; union { READ3resok resok; READ3resfail resfail; } READ3res_u; }; typedef struct READ3res READ3res; #define FSF3_LINK 0x0001 #define FSF3_SYMLINK 0x0002 #define FSF3_HOMOGENEOUS 0x0008 #define FSF3_CANSETTIME 0x0010 struct FSINFO3args { nfs_fh3 fsroot; }; typedef struct FSINFO3args FSINFO3args; struct FSINFO3resok { post_op_attr obj_attributes; u_int rtmax; u_int rtpref; u_int rtmult; u_int wtmax; u_int wtpref; u_int wtmult; u_int dtpref; size3 maxfilesize; nfstime3 time_delta; u_int properties; }; typedef struct FSINFO3resok FSINFO3resok; struct FSINFO3resfail { post_op_attr obj_attributes; }; typedef struct FSINFO3resfail FSINFO3resfail; struct FSINFO3res { nfsstat3 status; union { FSINFO3resok resok; FSINFO3resfail resfail; } FSINFO3res_u; }; typedef struct FSINFO3res FSINFO3res; struct FSSTAT3args { nfs_fh3 fsroot; }; typedef struct FSSTAT3args FSSTAT3args; struct FSSTAT3resok { post_op_attr obj_attributes; size3 tbytes; size3 fbytes; size3 abytes; size3 tfiles; size3 ffiles; size3 afiles; u_int invarsec; }; typedef struct FSSTAT3resok FSSTAT3resok; struct FSSTAT3resfail { post_op_attr obj_attributes; }; typedef struct FSSTAT3resfail FSSTAT3resfail; struct FSSTAT3res { nfsstat3 status; union { FSSTAT3resok resok; FSSTAT3resfail resfail; } FSSTAT3res_u; }; typedef struct FSSTAT3res FSSTAT3res; struct PATHCONF3args { nfs_fh3 object; }; typedef struct PATHCONF3args PATHCONF3args; struct PATHCONF3resok { post_op_attr obj_attributes; u_int linkmax; u_int name_max; uint32_t no_trunc; uint32_t chown_restricted; uint32_t case_insensitive; uint32_t case_preserving; }; typedef struct PATHCONF3resok PATHCONF3resok; struct PATHCONF3resfail { post_op_attr obj_attributes; }; typedef struct PATHCONF3resfail PATHCONF3resfail; struct PATHCONF3res { nfsstat3 status; union { PATHCONF3resok resok; PATHCONF3resfail resfail; } PATHCONF3res_u; }; typedef struct PATHCONF3res PATHCONF3res; typedef char *nfspath3; struct symlinkdata3 { sattr3 symlink_attributes; nfspath3 symlink_data; }; typedef struct symlinkdata3 symlinkdata3; struct SYMLINK3args { diropargs3 where; symlinkdata3 symlink; }; typedef struct SYMLINK3args SYMLINK3args; struct SYMLINK3resok { post_op_fh3 obj; post_op_attr obj_attributes; wcc_data dir_wcc; }; typedef struct SYMLINK3resok SYMLINK3resok; struct SYMLINK3resfail { wcc_data dir_wcc; }; typedef struct SYMLINK3resfail SYMLINK3resfail; struct SYMLINK3res { nfsstat3 status; union { SYMLINK3resok resok; SYMLINK3resfail resfail; } SYMLINK3res_u; }; typedef struct SYMLINK3res SYMLINK3res; struct READLINK3args { nfs_fh3 symlink; }; typedef struct READLINK3args READLINK3args; struct READLINK3resok { post_op_attr symlink_attributes; nfspath3 data; }; typedef struct READLINK3resok READLINK3resok; struct READLINK3resfail { post_op_attr symlink_attributes; }; typedef struct READLINK3resfail READLINK3resfail; struct READLINK3res { nfsstat3 status; union { READLINK3resok resok; READLINK3resfail resfail; } READLINK3res_u; }; typedef struct READLINK3res READLINK3res; struct devicedata3 { sattr3 dev_attributes; specdata3 spec; }; typedef struct devicedata3 devicedata3; struct mknoddata3 { ftype3 type; union { devicedata3 chr_device; devicedata3 blk_device; sattr3 sock_attributes; sattr3 pipe_attributes; } mknoddata3_u; }; typedef struct mknoddata3 mknoddata3; struct MKNOD3args { diropargs3 where; mknoddata3 what; }; typedef struct MKNOD3args MKNOD3args; struct MKNOD3resok { post_op_fh3 obj; post_op_attr obj_attributes; wcc_data dir_wcc; }; typedef struct MKNOD3resok MKNOD3resok; struct MKNOD3resfail { wcc_data dir_wcc; }; typedef struct MKNOD3resfail MKNOD3resfail; struct MKNOD3res { nfsstat3 status; union { MKNOD3resok resok; MKNOD3resfail resfail; } MKNOD3res_u; }; typedef struct MKNOD3res MKNOD3res; struct MKDIR3args { diropargs3 where; sattr3 attributes; }; typedef struct MKDIR3args MKDIR3args; struct MKDIR3resok { post_op_fh3 obj; post_op_attr obj_attributes; wcc_data dir_wcc; }; typedef struct MKDIR3resok MKDIR3resok; struct MKDIR3resfail { wcc_data dir_wcc; }; typedef struct MKDIR3resfail MKDIR3resfail; struct MKDIR3res { nfsstat3 status; union { MKDIR3resok resok; MKDIR3resfail resfail; } MKDIR3res_u; }; typedef struct MKDIR3res MKDIR3res; struct RMDIR3args { diropargs3 object; }; typedef struct RMDIR3args RMDIR3args; struct RMDIR3resok { wcc_data dir_wcc; }; typedef struct RMDIR3resok RMDIR3resok; struct RMDIR3resfail { wcc_data dir_wcc; }; typedef struct RMDIR3resfail RMDIR3resfail; struct RMDIR3res { nfsstat3 status; union { RMDIR3resok resok; RMDIR3resfail resfail; } RMDIR3res_u; }; typedef struct RMDIR3res RMDIR3res; struct RENAME3args { diropargs3 from; diropargs3 to; }; typedef struct RENAME3args RENAME3args; struct RENAME3resok { wcc_data fromdir_wcc; wcc_data todir_wcc; }; typedef struct RENAME3resok RENAME3resok; struct RENAME3resfail { wcc_data fromdir_wcc; wcc_data todir_wcc; }; typedef struct RENAME3resfail RENAME3resfail; struct RENAME3res { nfsstat3 status; union { RENAME3resok resok; RENAME3resfail resfail; } RENAME3res_u; }; typedef struct RENAME3res RENAME3res; struct READDIRPLUS3args { nfs_fh3 dir; cookie3 cookie; cookieverf3 cookieverf; count3 dircount; count3 maxcount; }; typedef struct READDIRPLUS3args READDIRPLUS3args; struct entryplus3 { fileid3 fileid; filename3 name; cookie3 cookie; post_op_attr name_attributes; post_op_fh3 name_handle; struct entryplus3 *nextentry; }; typedef struct entryplus3 entryplus3; struct dirlistplus3 { entryplus3 *entries; uint32_t eof; }; typedef struct dirlistplus3 dirlistplus3; struct READDIRPLUS3resok { post_op_attr dir_attributes; cookieverf3 cookieverf; dirlistplus3 reply; }; typedef struct READDIRPLUS3resok READDIRPLUS3resok; struct READDIRPLUS3resfail { post_op_attr dir_attributes; }; typedef struct READDIRPLUS3resfail READDIRPLUS3resfail; struct READDIRPLUS3res { nfsstat3 status; union { READDIRPLUS3resok resok; READDIRPLUS3resfail resfail; } READDIRPLUS3res_u; }; typedef struct READDIRPLUS3res READDIRPLUS3res; struct READDIR3args { nfs_fh3 dir; cookie3 cookie; cookieverf3 cookieverf; count3 count; }; typedef struct READDIR3args READDIR3args; struct entry3 { fileid3 fileid; filename3 name; cookie3 cookie; struct entry3 *nextentry; }; typedef struct entry3 entry3; struct dirlist3 { entry3 *entries; uint32_t eof; }; typedef struct dirlist3 dirlist3; struct READDIR3resok { post_op_attr dir_attributes; cookieverf3 cookieverf; dirlist3 reply; }; typedef struct READDIR3resok READDIR3resok; struct READDIR3resfail { post_op_attr dir_attributes; }; typedef struct READDIR3resfail READDIR3resfail; struct READDIR3res { nfsstat3 status; union { READDIR3resok resok; READDIR3resfail resfail; } READDIR3res_u; }; typedef struct READDIR3res READDIR3res; struct LINK3args { nfs_fh3 file; diropargs3 link; }; typedef struct LINK3args LINK3args; struct LINK3resok { post_op_attr file_attributes; wcc_data linkdir_wcc; }; typedef struct LINK3resok LINK3resok; struct LINK3resfail { post_op_attr file_attributes; wcc_data linkdir_wcc; }; typedef struct LINK3resfail LINK3resfail; struct LINK3res { nfsstat3 status; union { LINK3resok resok; LINK3resfail resfail; } LINK3res_u; }; typedef struct LINK3res LINK3res; struct sattrguard3 { uint32_t check; union { nfstime3 obj_ctime; } sattrguard3_u; }; typedef struct sattrguard3 sattrguard3; struct SETATTR3args { nfs_fh3 object; sattr3 new_attributes; sattrguard3 guard; }; typedef struct SETATTR3args SETATTR3args; struct SETATTR3resok { wcc_data obj_wcc; }; typedef struct SETATTR3resok SETATTR3resok; struct SETATTR3resfail { wcc_data obj_wcc; }; typedef struct SETATTR3resfail SETATTR3resfail; struct SETATTR3res { nfsstat3 status; union { SETATTR3resok resok; SETATTR3resfail resfail; } SETATTR3res_u; }; typedef struct SETATTR3res SETATTR3res; #define FHSIZE2 32 typedef char fhandle2[FHSIZE2]; enum ftype2 { NF2NON = 0, NF2REG = 1, NF2DIR = 2, NF2BLK = 3, NF2CHR = 4, NF2LNK = 5, }; typedef enum ftype2 ftype2; struct fattr2 { ftype2 type; u_int mode; u_int nlink; u_int uid; u_int gid; u_int size; u_int blocksize; u_int rdev; u_int blocks; u_int fsid; u_int fileid; nfstime3 atime; nfstime3 mtime; nfstime3 ctime; }; typedef struct fattr2 fattr2; struct sattr2 { u_int mode; u_int uid; u_int gid; u_int size; nfstime3 atime; nfstime3 mtime; }; typedef struct sattr2 sattr2; #define MAXNAMLEN2 255 typedef char *filename2; #define MAXPATHLEN2 1024 typedef char *path2; #define NFSMAXDATA2 8192 typedef struct { u_int nfsdata2_len; char *nfsdata2_val; } nfsdata2; #define NFSCOOKIESIZE2 4 typedef char nfscookie2[NFSCOOKIESIZE2]; struct entry2 { u_int fileid; filename2 name; nfscookie2 cookie; struct entry2 *nextentry; }; typedef struct entry2 entry2; struct diropargs2 { fhandle2 dir; filename2 name; }; typedef struct diropargs2 diropargs2; struct GETATTR2args { fhandle2 fhandle; }; typedef struct GETATTR2args GETATTR2args; struct GETATTR2resok { fattr2 attributes; }; typedef struct GETATTR2resok GETATTR2resok; struct GETATTR2res { nfsstat3 status; union { GETATTR2resok resok; } GETATTR2res_u; }; typedef struct GETATTR2res GETATTR2res; struct SETATTR2args { fhandle2 fhandle; sattr2 attributes; }; typedef struct SETATTR2args SETATTR2args; struct SETATTR2resok { fattr2 attributes; }; typedef struct SETATTR2resok SETATTR2resok; struct SETATTR2res { nfsstat3 status; union { SETATTR2resok resok; } SETATTR2res_u; }; typedef struct SETATTR2res SETATTR2res; struct LOOKUP2args { diropargs2 what; }; typedef struct LOOKUP2args LOOKUP2args; struct LOOKUP2resok { fhandle2 file; fattr2 attributes; }; typedef struct LOOKUP2resok LOOKUP2resok; struct LOOKUP2res { nfsstat3 status; union { LOOKUP2resok resok; } LOOKUP2res_u; }; typedef struct LOOKUP2res LOOKUP2res; struct READLINK2args { fhandle2 file; }; typedef struct READLINK2args READLINK2args; struct READLINK2resok { path2 data; }; typedef struct READLINK2resok READLINK2resok; struct READLINK2res { nfsstat3 status; union { READLINK2resok resok; } READLINK2res_u; }; typedef struct READLINK2res READLINK2res; struct READ2args { fhandle2 file; u_int offset; u_int count; u_int totalcount; }; typedef struct READ2args READ2args; struct READ2resok { fattr2 attributes; nfsdata2 data; }; typedef struct READ2resok READ2resok; struct READ2res { nfsstat3 status; union { READ2resok resok; } READ2res_u; }; typedef struct READ2res READ2res; struct WRITE2args { fhandle2 file; u_int beginoffset; u_int offset; u_int totalcount; nfsdata2 data; }; typedef struct WRITE2args WRITE2args; struct WRITE2resok { fattr2 attributes; }; typedef struct WRITE2resok WRITE2resok; struct WRITE2res { nfsstat3 status; union { WRITE2resok resok; } WRITE2res_u; }; typedef struct WRITE2res WRITE2res; struct CREATE2args { diropargs2 where; sattr2 attributes; }; typedef struct CREATE2args CREATE2args; struct CREATE2resok { fhandle2 file; fattr2 attributes; }; typedef struct CREATE2resok CREATE2resok; struct CREATE2res { nfsstat3 status; union { CREATE2resok resok; } CREATE2res_u; }; typedef struct CREATE2res CREATE2res; struct REMOVE2args { diropargs2 what; }; typedef struct REMOVE2args REMOVE2args; struct REMOVE2res { nfsstat3 status; }; typedef struct REMOVE2res REMOVE2res; struct RENAME2args { diropargs2 from; diropargs2 to; }; typedef struct RENAME2args RENAME2args; struct RENAME2res { nfsstat3 status; }; typedef struct RENAME2res RENAME2res; struct LINK2args { fhandle2 from; diropargs2 to; }; typedef struct LINK2args LINK2args; struct LINK2res { nfsstat3 status; }; typedef struct LINK2res LINK2res; struct SYMLINK2args { diropargs2 from; path2 to; sattr2 attributes; }; typedef struct SYMLINK2args SYMLINK2args; struct SYMLINK2res { nfsstat3 status; }; typedef struct SYMLINK2res SYMLINK2res; struct MKDIR2args { diropargs2 where; sattr2 attributes; }; typedef struct MKDIR2args MKDIR2args; struct MKDIR2resok { fhandle2 file; fattr2 attributes; }; typedef struct MKDIR2resok MKDIR2resok; struct MKDIR2res { nfsstat3 status; union { MKDIR2resok resok; } MKDIR2res_u; }; typedef struct MKDIR2res MKDIR2res; struct RMDIR2args { diropargs2 what; }; typedef struct RMDIR2args RMDIR2args; struct RMDIR2res { nfsstat3 status; }; typedef struct RMDIR2res RMDIR2res; struct READDIR2args { fhandle2 dir; nfscookie2 cookie; u_int count; }; typedef struct READDIR2args READDIR2args; struct READDIR2resok { entry2 *entries; uint32_t eof; }; typedef struct READDIR2resok READDIR2resok; struct READDIR2res { nfsstat3 status; union { READDIR2resok resok; } READDIR2res_u; }; typedef struct READDIR2res READDIR2res; struct STATFS2args { fhandle2 dir; }; typedef struct STATFS2args STATFS2args; struct STATFS2resok { u_int tsize; u_int bsize; u_int blocks; u_int bfree; u_int bavail; }; typedef struct STATFS2resok STATFS2resok; struct STATFS2res { nfsstat3 status; union { STATFS2resok resok; } STATFS2res_u; }; typedef struct STATFS2res STATFS2res; enum nfsacl_type { NFSACL_TYPE_USER_OBJ = 0x0001, NFSACL_TYPE_USER = 0x0002, NFSACL_TYPE_GROUP_OBJ = 0x0004, NFSACL_TYPE_GROUP = 0x0008, NFSACL_TYPE_CLASS_OBJ = 0x0010, NFSACL_TYPE_CLASS = 0x0020, NFSACL_TYPE_DEFAULT = 0x1000, NFSACL_TYPE_DEFAULT_USER_OBJ = 0x1001, NFSACL_TYPE_DEFAULT_USER = 0x1002, NFSACL_TYPE_DEFAULT_GROUP_OBJ = 0x1004, NFSACL_TYPE_DEFAULT_GROUP = 0x1008, NFSACL_TYPE_DEFAULT_CLASS_OBJ = 0x1010, NFSACL_TYPE_DEFAULT_OTHER_OBJ = 0x1020, }; typedef enum nfsacl_type nfsacl_type; #define NFSACL_PERM_READ 0x04 #define NFSACL_PERM_WRITE 0x02 #define NFSACL_PERM_EXEC 0x01 struct nfsacl_ace { enum nfsacl_type type; u_int id; u_int perm; }; typedef struct nfsacl_ace nfsacl_ace; #define NFSACL_MASK_ACL_ENTRY 0x0001 #define NFSACL_MASK_ACL_COUNT 0x0002 #define NFSACL_MASK_ACL_DEFAULT_ENTRY 0x0004 #define NFSACL_MASK_ACL_DEFAULT_COUNT 0x0008 struct GETACL3args { nfs_fh3 dir; u_int mask; }; typedef struct GETACL3args GETACL3args; struct GETACL3resok { post_op_attr attr; u_int mask; u_int ace_count; struct { u_int ace_len; struct nfsacl_ace *ace_val; } ace; u_int default_ace_count; struct { u_int default_ace_len; struct nfsacl_ace *default_ace_val; } default_ace; }; typedef struct GETACL3resok GETACL3resok; struct GETACL3res { nfsstat3 status; union { GETACL3resok resok; } GETACL3res_u; }; typedef struct GETACL3res GETACL3res; struct SETACL3args { nfs_fh3 dir; u_int mask; u_int ace_count; struct { u_int ace_len; struct nfsacl_ace *ace_val; } ace; u_int default_ace_count; struct { u_int default_ace_len; struct nfsacl_ace *default_ace_val; } default_ace; }; typedef struct SETACL3args SETACL3args; struct SETACL3resok { post_op_attr attr; }; typedef struct SETACL3resok SETACL3resok; struct SETACL3res { nfsstat3 status; union { SETACL3resok resok; } SETACL3res_u; }; typedef struct SETACL3res SETACL3res; #define NFS_PROGRAM 100003 #define NFS_V2 2 #if defined(__STDC__) || defined(__cplusplus) #define NFS2_NULL 0 extern void * nfs2_null_2(void *, void *); extern void * nfs2_null_2_svc(void *, struct svc_req *); #define NFS2_GETATTR 1 extern GETATTR2res * nfs2_getattr_2(GETATTR2args *, void *); extern GETATTR2res * nfs2_getattr_2_svc(GETATTR2args *, struct svc_req *); #define NFS2_SETATTR 2 extern SETATTR2res * nfs2_setattr_2(SETATTR2args *, void *); extern SETATTR2res * nfs2_setattr_2_svc(SETATTR2args *, struct svc_req *); #define NFS2_LOOKUP 4 extern LOOKUP2res * nfs2_lookup_2(LOOKUP2args *, void *); extern LOOKUP2res * nfs2_lookup_2_svc(LOOKUP2args *, struct svc_req *); #define NFS2_READLINK 5 extern READLINK2res * nfs2_readlink_2(READLINK2args *, void *); extern READLINK2res * nfs2_readlink_2_svc(READLINK2args *, struct svc_req *); #define NFS2_READ 6 extern READ2res * nfs2_read_2(READ2args *, void *); extern READ2res * nfs2_read_2_svc(READ2args *, struct svc_req *); #define NFS2_WRITE 8 extern WRITE2res * nfs2_write_2(WRITE2args *, void *); extern WRITE2res * nfs2_write_2_svc(WRITE2args *, struct svc_req *); #define NFS2_CREATE 9 extern CREATE2res * nfs2_create_2(CREATE2args *, void *); extern CREATE2res * nfs2_create_2_svc(CREATE2args *, struct svc_req *); #define NFS2_REMOVE 10 extern REMOVE2res * nfs2_remove_2(REMOVE2args *, void *); extern REMOVE2res * nfs2_remove_2_svc(REMOVE2args *, struct svc_req *); #define NFS2_RENAME 11 extern RENAME2res * nfs2_rename_2(RENAME2args *, void *); extern RENAME2res * nfs2_rename_2_svc(RENAME2args *, struct svc_req *); #define NFS2_LINK 12 extern LINK2res * nfs2_link_2(LINK2args *, void *); extern LINK2res * nfs2_link_2_svc(LINK2args *, struct svc_req *); #define NFS2_SYMLINK 13 extern SYMLINK2res * nfs2_symlink_2(SYMLINK2args *, void *); extern SYMLINK2res * nfs2_symlink_2_svc(SYMLINK2args *, struct svc_req *); #define NFS2_MKDIR 14 extern MKDIR2res * nfs2_mkdir_2(MKDIR2args *, void *); extern MKDIR2res * nfs2_mkdir_2_svc(MKDIR2args *, struct svc_req *); #define NFS2_RMDIR 15 extern RMDIR2res * nfs2_rmdir_2(RMDIR2args *, void *); extern RMDIR2res * nfs2_rmdir_2_svc(RMDIR2args *, struct svc_req *); #define NFS2_READDIR 16 extern READDIR2res * nfs2_readdir_2(READDIR2args *, void *); extern READDIR2res * nfs2_readdir_2_svc(READDIR2args *, struct svc_req *); #define NFS2_STATFS 17 extern STATFS2res * nfs2_statfs_2(STATFS2args *, void *); extern STATFS2res * nfs2_statfs_2_svc(STATFS2args *, struct svc_req *); extern int nfs_program_2_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define NFS2_NULL 0 extern void * nfs2_null_2(); extern void * nfs2_null_2_svc(); #define NFS2_GETATTR 1 extern GETATTR2res * nfs2_getattr_2(); extern GETATTR2res * nfs2_getattr_2_svc(); #define NFS2_SETATTR 2 extern SETATTR2res * nfs2_setattr_2(); extern SETATTR2res * nfs2_setattr_2_svc(); #define NFS2_LOOKUP 4 extern LOOKUP2res * nfs2_lookup_2(); extern LOOKUP2res * nfs2_lookup_2_svc(); #define NFS2_READLINK 5 extern READLINK2res * nfs2_readlink_2(); extern READLINK2res * nfs2_readlink_2_svc(); #define NFS2_READ 6 extern READ2res * nfs2_read_2(); extern READ2res * nfs2_read_2_svc(); #define NFS2_WRITE 8 extern WRITE2res * nfs2_write_2(); extern WRITE2res * nfs2_write_2_svc(); #define NFS2_CREATE 9 extern CREATE2res * nfs2_create_2(); extern CREATE2res * nfs2_create_2_svc(); #define NFS2_REMOVE 10 extern REMOVE2res * nfs2_remove_2(); extern REMOVE2res * nfs2_remove_2_svc(); #define NFS2_RENAME 11 extern RENAME2res * nfs2_rename_2(); extern RENAME2res * nfs2_rename_2_svc(); #define NFS2_LINK 12 extern LINK2res * nfs2_link_2(); extern LINK2res * nfs2_link_2_svc(); #define NFS2_SYMLINK 13 extern SYMLINK2res * nfs2_symlink_2(); extern SYMLINK2res * nfs2_symlink_2_svc(); #define NFS2_MKDIR 14 extern MKDIR2res * nfs2_mkdir_2(); extern MKDIR2res * nfs2_mkdir_2_svc(); #define NFS2_RMDIR 15 extern RMDIR2res * nfs2_rmdir_2(); extern RMDIR2res * nfs2_rmdir_2_svc(); #define NFS2_READDIR 16 extern READDIR2res * nfs2_readdir_2(); extern READDIR2res * nfs2_readdir_2_svc(); #define NFS2_STATFS 17 extern STATFS2res * nfs2_statfs_2(); extern STATFS2res * nfs2_statfs_2_svc(); extern int nfs_program_2_freeresult (); #endif /* K&R C */ #define NFS_V3 3 #if defined(__STDC__) || defined(__cplusplus) #define NFS3_NULL 0 extern void * nfs3_null_3(void *, void *); extern void * nfs3_null_3_svc(void *, struct svc_req *); #define NFS3_GETATTR 1 extern GETATTR3res * nfs3_getattr_3(GETATTR3args *, void *); extern GETATTR3res * nfs3_getattr_3_svc(GETATTR3args *, struct svc_req *); #define NFS3_SETATTR 2 extern SETATTR3res * nfs3_setattr_3(SETATTR3args *, void *); extern SETATTR3res * nfs3_setattr_3_svc(SETATTR3args *, struct svc_req *); #define NFS3_LOOKUP 3 extern LOOKUP3res * nfs3_lookup_3(LOOKUP3args *, void *); extern LOOKUP3res * nfs3_lookup_3_svc(LOOKUP3args *, struct svc_req *); #define NFS3_ACCESS 4 extern ACCESS3res * nfs3_access_3(ACCESS3args *, void *); extern ACCESS3res * nfs3_access_3_svc(ACCESS3args *, struct svc_req *); #define NFS3_READLINK 5 extern READLINK3res * nfs3_readlink_3(READLINK3args *, void *); extern READLINK3res * nfs3_readlink_3_svc(READLINK3args *, struct svc_req *); #define NFS3_READ 6 extern READ3res * nfs3_read_3(READ3args *, void *); extern READ3res * nfs3_read_3_svc(READ3args *, struct svc_req *); #define NFS3_WRITE 7 extern WRITE3res * nfs3_write_3(WRITE3args *, void *); extern WRITE3res * nfs3_write_3_svc(WRITE3args *, struct svc_req *); #define NFS3_CREATE 8 extern CREATE3res * nfs3_create_3(CREATE3args *, void *); extern CREATE3res * nfs3_create_3_svc(CREATE3args *, struct svc_req *); #define NFS3_MKDIR 9 extern MKDIR3res * nfs3_mkdir_3(MKDIR3args *, void *); extern MKDIR3res * nfs3_mkdir_3_svc(MKDIR3args *, struct svc_req *); #define NFS3_SYMLINK 10 extern SYMLINK3res * nfs3_symlink_3(SYMLINK3args *, void *); extern SYMLINK3res * nfs3_symlink_3_svc(SYMLINK3args *, struct svc_req *); #define NFS3_MKNOD 11 extern MKNOD3res * nfs3_mknod_3(MKNOD3args *, void *); extern MKNOD3res * nfs3_mknod_3_svc(MKNOD3args *, struct svc_req *); #define NFS3_REMOVE 12 extern REMOVE3res * nfs3_remove_3(REMOVE3args *, void *); extern REMOVE3res * nfs3_remove_3_svc(REMOVE3args *, struct svc_req *); #define NFS3_RMDIR 13 extern RMDIR3res * nfs3_rmdir_3(RMDIR3args *, void *); extern RMDIR3res * nfs3_rmdir_3_svc(RMDIR3args *, struct svc_req *); #define NFS3_RENAME 14 extern RENAME3res * nfs3_rename_3(RENAME3args *, void *); extern RENAME3res * nfs3_rename_3_svc(RENAME3args *, struct svc_req *); #define NFS3_LINK 15 extern LINK3res * nfs3_link_3(LINK3args *, void *); extern LINK3res * nfs3_link_3_svc(LINK3args *, struct svc_req *); #define NFS3_READDIR 16 extern READDIR3res * nfs3_readdir_3(READDIR3args *, void *); extern READDIR3res * nfs3_readdir_3_svc(READDIR3args *, struct svc_req *); #define NFS3_READDIRPLUS 17 extern READDIRPLUS3res * nfs3_readdirplus_3(READDIRPLUS3args *, void *); extern READDIRPLUS3res * nfs3_readdirplus_3_svc(READDIRPLUS3args *, struct svc_req *); #define NFS3_FSSTAT 18 extern FSSTAT3res * nfs3_fsstat_3(FSSTAT3args *, void *); extern FSSTAT3res * nfs3_fsstat_3_svc(FSSTAT3args *, struct svc_req *); #define NFS3_FSINFO 19 extern FSINFO3res * nfs3_fsinfo_3(FSINFO3args *, void *); extern FSINFO3res * nfs3_fsinfo_3_svc(FSINFO3args *, struct svc_req *); #define NFS3_PATHCONF 20 extern PATHCONF3res * nfs3_pathconf_3(PATHCONF3args *, void *); extern PATHCONF3res * nfs3_pathconf_3_svc(PATHCONF3args *, struct svc_req *); #define NFS3_COMMIT 21 extern COMMIT3res * nfs3_commit_3(COMMIT3args *, void *); extern COMMIT3res * nfs3_commit_3_svc(COMMIT3args *, struct svc_req *); extern int nfs_program_3_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define NFS3_NULL 0 extern void * nfs3_null_3(); extern void * nfs3_null_3_svc(); #define NFS3_GETATTR 1 extern GETATTR3res * nfs3_getattr_3(); extern GETATTR3res * nfs3_getattr_3_svc(); #define NFS3_SETATTR 2 extern SETATTR3res * nfs3_setattr_3(); extern SETATTR3res * nfs3_setattr_3_svc(); #define NFS3_LOOKUP 3 extern LOOKUP3res * nfs3_lookup_3(); extern LOOKUP3res * nfs3_lookup_3_svc(); #define NFS3_ACCESS 4 extern ACCESS3res * nfs3_access_3(); extern ACCESS3res * nfs3_access_3_svc(); #define NFS3_READLINK 5 extern READLINK3res * nfs3_readlink_3(); extern READLINK3res * nfs3_readlink_3_svc(); #define NFS3_READ 6 extern READ3res * nfs3_read_3(); extern READ3res * nfs3_read_3_svc(); #define NFS3_WRITE 7 extern WRITE3res * nfs3_write_3(); extern WRITE3res * nfs3_write_3_svc(); #define NFS3_CREATE 8 extern CREATE3res * nfs3_create_3(); extern CREATE3res * nfs3_create_3_svc(); #define NFS3_MKDIR 9 extern MKDIR3res * nfs3_mkdir_3(); extern MKDIR3res * nfs3_mkdir_3_svc(); #define NFS3_SYMLINK 10 extern SYMLINK3res * nfs3_symlink_3(); extern SYMLINK3res * nfs3_symlink_3_svc(); #define NFS3_MKNOD 11 extern MKNOD3res * nfs3_mknod_3(); extern MKNOD3res * nfs3_mknod_3_svc(); #define NFS3_REMOVE 12 extern REMOVE3res * nfs3_remove_3(); extern REMOVE3res * nfs3_remove_3_svc(); #define NFS3_RMDIR 13 extern RMDIR3res * nfs3_rmdir_3(); extern RMDIR3res * nfs3_rmdir_3_svc(); #define NFS3_RENAME 14 extern RENAME3res * nfs3_rename_3(); extern RENAME3res * nfs3_rename_3_svc(); #define NFS3_LINK 15 extern LINK3res * nfs3_link_3(); extern LINK3res * nfs3_link_3_svc(); #define NFS3_READDIR 16 extern READDIR3res * nfs3_readdir_3(); extern READDIR3res * nfs3_readdir_3_svc(); #define NFS3_READDIRPLUS 17 extern READDIRPLUS3res * nfs3_readdirplus_3(); extern READDIRPLUS3res * nfs3_readdirplus_3_svc(); #define NFS3_FSSTAT 18 extern FSSTAT3res * nfs3_fsstat_3(); extern FSSTAT3res * nfs3_fsstat_3_svc(); #define NFS3_FSINFO 19 extern FSINFO3res * nfs3_fsinfo_3(); extern FSINFO3res * nfs3_fsinfo_3_svc(); #define NFS3_PATHCONF 20 extern PATHCONF3res * nfs3_pathconf_3(); extern PATHCONF3res * nfs3_pathconf_3_svc(); #define NFS3_COMMIT 21 extern COMMIT3res * nfs3_commit_3(); extern COMMIT3res * nfs3_commit_3_svc(); extern int nfs_program_3_freeresult (); #endif /* K&R C */ #define NFSACL_PROGRAM 100227 #define NFSACL_V3 3 #if defined(__STDC__) || defined(__cplusplus) #define NFSACL3_NULL 0 extern void * nfsacl3_null_3(void *, void *); extern void * nfsacl3_null_3_svc(void *, struct svc_req *); #define NFSACL3_GETACL 1 extern GETACL3res * nfsacl3_getacl_3(GETACL3args *, void *); extern GETACL3res * nfsacl3_getacl_3_svc(GETACL3args *, struct svc_req *); #define NFSACL3_SETACL 2 extern SETACL3res * nfsacl3_setacl_3(SETACL3args *, void *); extern SETACL3res * nfsacl3_setacl_3_svc(SETACL3args *, struct svc_req *); extern int nfsacl_program_3_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define NFSACL3_NULL 0 extern void * nfsacl3_null_3(); extern void * nfsacl3_null_3_svc(); #define NFSACL3_GETACL 1 extern GETACL3res * nfsacl3_getacl_3(); extern GETACL3res * nfsacl3_getacl_3_svc(); #define NFSACL3_SETACL 2 extern SETACL3res * nfsacl3_setacl_3(); extern SETACL3res * nfsacl3_setacl_3_svc(); extern int nfsacl_program_3_freeresult (); #endif /* K&R C */ /* the zdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern uint32_t zdr_cookieverf3 (ZDR *, cookieverf3); extern uint32_t zdr_cookie3 (ZDR *, cookie3*); extern uint32_t zdr_nfs_fh3 (ZDR *, nfs_fh3*); extern uint32_t zdr_filename3 (ZDR *, filename3*); extern uint32_t zdr_diropargs3 (ZDR *, diropargs3*); extern uint32_t zdr_ftype3 (ZDR *, ftype3*); extern uint32_t zdr_mode3 (ZDR *, mode3*); extern uint32_t zdr_uid3 (ZDR *, uid3*); extern uint32_t zdr_gid3 (ZDR *, gid3*); extern uint32_t zdr_size3 (ZDR *, size3*); extern uint32_t zdr_fileid3 (ZDR *, fileid3*); extern uint32_t zdr_specdata3 (ZDR *, specdata3*); extern uint32_t zdr_nfstime3 (ZDR *, nfstime3*); extern uint32_t zdr_fattr3 (ZDR *, fattr3*); extern uint32_t zdr_post_op_attr (ZDR *, post_op_attr*); extern uint32_t zdr_nfsstat3 (ZDR *, nfsstat3*); extern uint32_t zdr_stable_how (ZDR *, stable_how*); extern uint32_t zdr_offset3 (ZDR *, offset3*); extern uint32_t zdr_count3 (ZDR *, count3*); extern uint32_t zdr_wcc_attr (ZDR *, wcc_attr*); extern uint32_t zdr_pre_op_attr (ZDR *, pre_op_attr*); extern uint32_t zdr_wcc_data (ZDR *, wcc_data*); extern uint32_t zdr_WRITE3args (ZDR *, WRITE3args*); extern uint32_t zdr_writeverf3 (ZDR *, writeverf3); extern uint32_t zdr_WRITE3resok (ZDR *, WRITE3resok*); extern uint32_t zdr_WRITE3resfail (ZDR *, WRITE3resfail*); extern uint32_t zdr_WRITE3res (ZDR *, WRITE3res*); extern uint32_t zdr_LOOKUP3args (ZDR *, LOOKUP3args*); extern uint32_t zdr_LOOKUP3resok (ZDR *, LOOKUP3resok*); extern uint32_t zdr_LOOKUP3resfail (ZDR *, LOOKUP3resfail*); extern uint32_t zdr_LOOKUP3res (ZDR *, LOOKUP3res*); extern uint32_t zdr_COMMIT3args (ZDR *, COMMIT3args*); extern uint32_t zdr_COMMIT3resok (ZDR *, COMMIT3resok*); extern uint32_t zdr_COMMIT3resfail (ZDR *, COMMIT3resfail*); extern uint32_t zdr_COMMIT3res (ZDR *, COMMIT3res*); extern uint32_t zdr_ACCESS3args (ZDR *, ACCESS3args*); extern uint32_t zdr_ACCESS3resok (ZDR *, ACCESS3resok*); extern uint32_t zdr_ACCESS3resfail (ZDR *, ACCESS3resfail*); extern uint32_t zdr_ACCESS3res (ZDR *, ACCESS3res*); extern uint32_t zdr_GETATTR3args (ZDR *, GETATTR3args*); extern uint32_t zdr_GETATTR3resok (ZDR *, GETATTR3resok*); extern uint32_t zdr_GETATTR3res (ZDR *, GETATTR3res*); extern uint32_t zdr_time_how (ZDR *, time_how*); extern uint32_t zdr_set_mode3 (ZDR *, set_mode3*); extern uint32_t zdr_set_uid3 (ZDR *, set_uid3*); extern uint32_t zdr_set_gid3 (ZDR *, set_gid3*); extern uint32_t zdr_set_size3 (ZDR *, set_size3*); extern uint32_t zdr_set_atime (ZDR *, set_atime*); extern uint32_t zdr_set_mtime (ZDR *, set_mtime*); extern uint32_t zdr_sattr3 (ZDR *, sattr3*); extern uint32_t zdr_createmode3 (ZDR *, createmode3*); extern uint32_t zdr_createverf3 (ZDR *, createverf3); extern uint32_t zdr_createhow3 (ZDR *, createhow3*); extern uint32_t zdr_CREATE3args (ZDR *, CREATE3args*); extern uint32_t zdr_post_op_fh3 (ZDR *, post_op_fh3*); extern uint32_t zdr_CREATE3resok (ZDR *, CREATE3resok*); extern uint32_t zdr_CREATE3resfail (ZDR *, CREATE3resfail*); extern uint32_t zdr_CREATE3res (ZDR *, CREATE3res*); extern uint32_t zdr_REMOVE3args (ZDR *, REMOVE3args*); extern uint32_t zdr_REMOVE3resok (ZDR *, REMOVE3resok*); extern uint32_t zdr_REMOVE3resfail (ZDR *, REMOVE3resfail*); extern uint32_t zdr_REMOVE3res (ZDR *, REMOVE3res*); extern uint32_t zdr_READ3args (ZDR *, READ3args*); extern uint32_t zdr_READ3resok (ZDR *, READ3resok*); extern uint32_t zdr_READ3resfail (ZDR *, READ3resfail*); extern uint32_t zdr_READ3res (ZDR *, READ3res*); extern uint32_t zdr_FSINFO3args (ZDR *, FSINFO3args*); extern uint32_t zdr_FSINFO3resok (ZDR *, FSINFO3resok*); extern uint32_t zdr_FSINFO3resfail (ZDR *, FSINFO3resfail*); extern uint32_t zdr_FSINFO3res (ZDR *, FSINFO3res*); extern uint32_t zdr_FSSTAT3args (ZDR *, FSSTAT3args*); extern uint32_t zdr_FSSTAT3resok (ZDR *, FSSTAT3resok*); extern uint32_t zdr_FSSTAT3resfail (ZDR *, FSSTAT3resfail*); extern uint32_t zdr_FSSTAT3res (ZDR *, FSSTAT3res*); extern uint32_t zdr_PATHCONF3args (ZDR *, PATHCONF3args*); extern uint32_t zdr_PATHCONF3resok (ZDR *, PATHCONF3resok*); extern uint32_t zdr_PATHCONF3resfail (ZDR *, PATHCONF3resfail*); extern uint32_t zdr_PATHCONF3res (ZDR *, PATHCONF3res*); extern uint32_t zdr_nfspath3 (ZDR *, nfspath3*); extern uint32_t zdr_symlinkdata3 (ZDR *, symlinkdata3*); extern uint32_t zdr_SYMLINK3args (ZDR *, SYMLINK3args*); extern uint32_t zdr_SYMLINK3resok (ZDR *, SYMLINK3resok*); extern uint32_t zdr_SYMLINK3resfail (ZDR *, SYMLINK3resfail*); extern uint32_t zdr_SYMLINK3res (ZDR *, SYMLINK3res*); extern uint32_t zdr_READLINK3args (ZDR *, READLINK3args*); extern uint32_t zdr_READLINK3resok (ZDR *, READLINK3resok*); extern uint32_t zdr_READLINK3resfail (ZDR *, READLINK3resfail*); extern uint32_t zdr_READLINK3res (ZDR *, READLINK3res*); extern uint32_t zdr_devicedata3 (ZDR *, devicedata3*); extern uint32_t zdr_mknoddata3 (ZDR *, mknoddata3*); extern uint32_t zdr_MKNOD3args (ZDR *, MKNOD3args*); extern uint32_t zdr_MKNOD3resok (ZDR *, MKNOD3resok*); extern uint32_t zdr_MKNOD3resfail (ZDR *, MKNOD3resfail*); extern uint32_t zdr_MKNOD3res (ZDR *, MKNOD3res*); extern uint32_t zdr_MKDIR3args (ZDR *, MKDIR3args*); extern uint32_t zdr_MKDIR3resok (ZDR *, MKDIR3resok*); extern uint32_t zdr_MKDIR3resfail (ZDR *, MKDIR3resfail*); extern uint32_t zdr_MKDIR3res (ZDR *, MKDIR3res*); extern uint32_t zdr_RMDIR3args (ZDR *, RMDIR3args*); extern uint32_t zdr_RMDIR3resok (ZDR *, RMDIR3resok*); extern uint32_t zdr_RMDIR3resfail (ZDR *, RMDIR3resfail*); extern uint32_t zdr_RMDIR3res (ZDR *, RMDIR3res*); extern uint32_t zdr_RENAME3args (ZDR *, RENAME3args*); extern uint32_t zdr_RENAME3resok (ZDR *, RENAME3resok*); extern uint32_t zdr_RENAME3resfail (ZDR *, RENAME3resfail*); extern uint32_t zdr_RENAME3res (ZDR *, RENAME3res*); extern uint32_t zdr_READDIRPLUS3args (ZDR *, READDIRPLUS3args*); extern uint32_t zdr_entryplus3 (ZDR *, entryplus3*); extern uint32_t zdr_dirlistplus3 (ZDR *, dirlistplus3*); extern uint32_t zdr_READDIRPLUS3resok (ZDR *, READDIRPLUS3resok*); extern uint32_t zdr_READDIRPLUS3resfail (ZDR *, READDIRPLUS3resfail*); extern uint32_t zdr_READDIRPLUS3res (ZDR *, READDIRPLUS3res*); extern uint32_t zdr_READDIR3args (ZDR *, READDIR3args*); extern uint32_t zdr_entry3 (ZDR *, entry3*); extern uint32_t zdr_dirlist3 (ZDR *, dirlist3*); extern uint32_t zdr_READDIR3resok (ZDR *, READDIR3resok*); extern uint32_t zdr_READDIR3resfail (ZDR *, READDIR3resfail*); extern uint32_t zdr_READDIR3res (ZDR *, READDIR3res*); extern uint32_t zdr_LINK3args (ZDR *, LINK3args*); extern uint32_t zdr_LINK3resok (ZDR *, LINK3resok*); extern uint32_t zdr_LINK3resfail (ZDR *, LINK3resfail*); extern uint32_t zdr_LINK3res (ZDR *, LINK3res*); extern uint32_t zdr_sattrguard3 (ZDR *, sattrguard3*); extern uint32_t zdr_SETATTR3args (ZDR *, SETATTR3args*); extern uint32_t zdr_SETATTR3resok (ZDR *, SETATTR3resok*); extern uint32_t zdr_SETATTR3resfail (ZDR *, SETATTR3resfail*); extern uint32_t zdr_SETATTR3res (ZDR *, SETATTR3res*); extern uint32_t zdr_fhandle2 (ZDR *, fhandle2); extern uint32_t zdr_ftype2 (ZDR *, ftype2*); extern uint32_t zdr_fattr2 (ZDR *, fattr2*); extern uint32_t zdr_sattr2 (ZDR *, sattr2*); extern uint32_t zdr_filename2 (ZDR *, filename2*); extern uint32_t zdr_path2 (ZDR *, path2*); extern uint32_t zdr_nfsdata2 (ZDR *, nfsdata2*); extern uint32_t zdr_nfscookie2 (ZDR *, nfscookie2); extern uint32_t zdr_entry2 (ZDR *, entry2*); extern uint32_t zdr_diropargs2 (ZDR *, diropargs2*); extern uint32_t zdr_GETATTR2args (ZDR *, GETATTR2args*); extern uint32_t zdr_GETATTR2resok (ZDR *, GETATTR2resok*); extern uint32_t zdr_GETATTR2res (ZDR *, GETATTR2res*); extern uint32_t zdr_SETATTR2args (ZDR *, SETATTR2args*); extern uint32_t zdr_SETATTR2resok (ZDR *, SETATTR2resok*); extern uint32_t zdr_SETATTR2res (ZDR *, SETATTR2res*); extern uint32_t zdr_LOOKUP2args (ZDR *, LOOKUP2args*); extern uint32_t zdr_LOOKUP2resok (ZDR *, LOOKUP2resok*); extern uint32_t zdr_LOOKUP2res (ZDR *, LOOKUP2res*); extern uint32_t zdr_READLINK2args (ZDR *, READLINK2args*); extern uint32_t zdr_READLINK2resok (ZDR *, READLINK2resok*); extern uint32_t zdr_READLINK2res (ZDR *, READLINK2res*); extern uint32_t zdr_READ2args (ZDR *, READ2args*); extern uint32_t zdr_READ2resok (ZDR *, READ2resok*); extern uint32_t zdr_READ2res (ZDR *, READ2res*); extern uint32_t zdr_WRITE2args (ZDR *, WRITE2args*); extern uint32_t zdr_WRITE2resok (ZDR *, WRITE2resok*); extern uint32_t zdr_WRITE2res (ZDR *, WRITE2res*); extern uint32_t zdr_CREATE2args (ZDR *, CREATE2args*); extern uint32_t zdr_CREATE2resok (ZDR *, CREATE2resok*); extern uint32_t zdr_CREATE2res (ZDR *, CREATE2res*); extern uint32_t zdr_REMOVE2args (ZDR *, REMOVE2args*); extern uint32_t zdr_REMOVE2res (ZDR *, REMOVE2res*); extern uint32_t zdr_RENAME2args (ZDR *, RENAME2args*); extern uint32_t zdr_RENAME2res (ZDR *, RENAME2res*); extern uint32_t zdr_LINK2args (ZDR *, LINK2args*); extern uint32_t zdr_LINK2res (ZDR *, LINK2res*); extern uint32_t zdr_SYMLINK2args (ZDR *, SYMLINK2args*); extern uint32_t zdr_SYMLINK2res (ZDR *, SYMLINK2res*); extern uint32_t zdr_MKDIR2args (ZDR *, MKDIR2args*); extern uint32_t zdr_MKDIR2resok (ZDR *, MKDIR2resok*); extern uint32_t zdr_MKDIR2res (ZDR *, MKDIR2res*); extern uint32_t zdr_RMDIR2args (ZDR *, RMDIR2args*); extern uint32_t zdr_RMDIR2res (ZDR *, RMDIR2res*); extern uint32_t zdr_READDIR2args (ZDR *, READDIR2args*); extern uint32_t zdr_READDIR2resok (ZDR *, READDIR2resok*); extern uint32_t zdr_READDIR2res (ZDR *, READDIR2res*); extern uint32_t zdr_STATFS2args (ZDR *, STATFS2args*); extern uint32_t zdr_STATFS2resok (ZDR *, STATFS2resok*); extern uint32_t zdr_STATFS2res (ZDR *, STATFS2res*); extern uint32_t zdr_nfsacl_type (ZDR *, nfsacl_type*); extern uint32_t zdr_nfsacl_ace (ZDR *, nfsacl_ace*); extern uint32_t zdr_GETACL3args (ZDR *, GETACL3args*); extern uint32_t zdr_GETACL3resok (ZDR *, GETACL3resok*); extern uint32_t zdr_GETACL3res (ZDR *, GETACL3res*); extern uint32_t zdr_SETACL3args (ZDR *, SETACL3args*); extern uint32_t zdr_SETACL3resok (ZDR *, SETACL3resok*); extern uint32_t zdr_SETACL3res (ZDR *, SETACL3res*); #else /* K&R C */ extern uint32_t zdr_cookieverf3 (); extern uint32_t zdr_cookie3 (); extern uint32_t zdr_nfs_fh3 (); extern uint32_t zdr_filename3 (); extern uint32_t zdr_diropargs3 (); extern uint32_t zdr_ftype3 (); extern uint32_t zdr_mode3 (); extern uint32_t zdr_uid3 (); extern uint32_t zdr_gid3 (); extern uint32_t zdr_size3 (); extern uint32_t zdr_fileid3 (); extern uint32_t zdr_specdata3 (); extern uint32_t zdr_nfstime3 (); extern uint32_t zdr_fattr3 (); extern uint32_t zdr_post_op_attr (); extern uint32_t zdr_nfsstat3 (); extern uint32_t zdr_stable_how (); extern uint32_t zdr_offset3 (); extern uint32_t zdr_count3 (); extern uint32_t zdr_wcc_attr (); extern uint32_t zdr_pre_op_attr (); extern uint32_t zdr_wcc_data (); extern uint32_t zdr_WRITE3args (); extern uint32_t zdr_writeverf3 (); extern uint32_t zdr_WRITE3resok (); extern uint32_t zdr_WRITE3resfail (); extern uint32_t zdr_WRITE3res (); extern uint32_t zdr_LOOKUP3args (); extern uint32_t zdr_LOOKUP3resok (); extern uint32_t zdr_LOOKUP3resfail (); extern uint32_t zdr_LOOKUP3res (); extern uint32_t zdr_COMMIT3args (); extern uint32_t zdr_COMMIT3resok (); extern uint32_t zdr_COMMIT3resfail (); extern uint32_t zdr_COMMIT3res (); extern uint32_t zdr_ACCESS3args (); extern uint32_t zdr_ACCESS3resok (); extern uint32_t zdr_ACCESS3resfail (); extern uint32_t zdr_ACCESS3res (); extern uint32_t zdr_GETATTR3args (); extern uint32_t zdr_GETATTR3resok (); extern uint32_t zdr_GETATTR3res (); extern uint32_t zdr_time_how (); extern uint32_t zdr_set_mode3 (); extern uint32_t zdr_set_uid3 (); extern uint32_t zdr_set_gid3 (); extern uint32_t zdr_set_size3 (); extern uint32_t zdr_set_atime (); extern uint32_t zdr_set_mtime (); extern uint32_t zdr_sattr3 (); extern uint32_t zdr_createmode3 (); extern uint32_t zdr_createverf3 (); extern uint32_t zdr_createhow3 (); extern uint32_t zdr_CREATE3args (); extern uint32_t zdr_post_op_fh3 (); extern uint32_t zdr_CREATE3resok (); extern uint32_t zdr_CREATE3resfail (); extern uint32_t zdr_CREATE3res (); extern uint32_t zdr_REMOVE3args (); extern uint32_t zdr_REMOVE3resok (); extern uint32_t zdr_REMOVE3resfail (); extern uint32_t zdr_REMOVE3res (); extern uint32_t zdr_READ3args (); extern uint32_t zdr_READ3resok (); extern uint32_t zdr_READ3resfail (); extern uint32_t zdr_READ3res (); extern uint32_t zdr_FSINFO3args (); extern uint32_t zdr_FSINFO3resok (); extern uint32_t zdr_FSINFO3resfail (); extern uint32_t zdr_FSINFO3res (); extern uint32_t zdr_FSSTAT3args (); extern uint32_t zdr_FSSTAT3resok (); extern uint32_t zdr_FSSTAT3resfail (); extern uint32_t zdr_FSSTAT3res (); extern uint32_t zdr_PATHCONF3args (); extern uint32_t zdr_PATHCONF3resok (); extern uint32_t zdr_PATHCONF3resfail (); extern uint32_t zdr_PATHCONF3res (); extern uint32_t zdr_nfspath3 (); extern uint32_t zdr_symlinkdata3 (); extern uint32_t zdr_SYMLINK3args (); extern uint32_t zdr_SYMLINK3resok (); extern uint32_t zdr_SYMLINK3resfail (); extern uint32_t zdr_SYMLINK3res (); extern uint32_t zdr_READLINK3args (); extern uint32_t zdr_READLINK3resok (); extern uint32_t zdr_READLINK3resfail (); extern uint32_t zdr_READLINK3res (); extern uint32_t zdr_devicedata3 (); extern uint32_t zdr_mknoddata3 (); extern uint32_t zdr_MKNOD3args (); extern uint32_t zdr_MKNOD3resok (); extern uint32_t zdr_MKNOD3resfail (); extern uint32_t zdr_MKNOD3res (); extern uint32_t zdr_MKDIR3args (); extern uint32_t zdr_MKDIR3resok (); extern uint32_t zdr_MKDIR3resfail (); extern uint32_t zdr_MKDIR3res (); extern uint32_t zdr_RMDIR3args (); extern uint32_t zdr_RMDIR3resok (); extern uint32_t zdr_RMDIR3resfail (); extern uint32_t zdr_RMDIR3res (); extern uint32_t zdr_RENAME3args (); extern uint32_t zdr_RENAME3resok (); extern uint32_t zdr_RENAME3resfail (); extern uint32_t zdr_RENAME3res (); extern uint32_t zdr_READDIRPLUS3args (); extern uint32_t zdr_entryplus3 (); extern uint32_t zdr_dirlistplus3 (); extern uint32_t zdr_READDIRPLUS3resok (); extern uint32_t zdr_READDIRPLUS3resfail (); extern uint32_t zdr_READDIRPLUS3res (); extern uint32_t zdr_READDIR3args (); extern uint32_t zdr_entry3 (); extern uint32_t zdr_dirlist3 (); extern uint32_t zdr_READDIR3resok (); extern uint32_t zdr_READDIR3resfail (); extern uint32_t zdr_READDIR3res (); extern uint32_t zdr_LINK3args (); extern uint32_t zdr_LINK3resok (); extern uint32_t zdr_LINK3resfail (); extern uint32_t zdr_LINK3res (); extern uint32_t zdr_sattrguard3 (); extern uint32_t zdr_SETATTR3args (); extern uint32_t zdr_SETATTR3resok (); extern uint32_t zdr_SETATTR3resfail (); extern uint32_t zdr_SETATTR3res (); extern uint32_t zdr_fhandle2 (); extern uint32_t zdr_ftype2 (); extern uint32_t zdr_fattr2 (); extern uint32_t zdr_sattr2 (); extern uint32_t zdr_filename2 (); extern uint32_t zdr_path2 (); extern uint32_t zdr_nfsdata2 (); extern uint32_t zdr_nfscookie2 (); extern uint32_t zdr_entry2 (); extern uint32_t zdr_diropargs2 (); extern uint32_t zdr_GETATTR2args (); extern uint32_t zdr_GETATTR2resok (); extern uint32_t zdr_GETATTR2res (); extern uint32_t zdr_SETATTR2args (); extern uint32_t zdr_SETATTR2resok (); extern uint32_t zdr_SETATTR2res (); extern uint32_t zdr_LOOKUP2args (); extern uint32_t zdr_LOOKUP2resok (); extern uint32_t zdr_LOOKUP2res (); extern uint32_t zdr_READLINK2args (); extern uint32_t zdr_READLINK2resok (); extern uint32_t zdr_READLINK2res (); extern uint32_t zdr_READ2args (); extern uint32_t zdr_READ2resok (); extern uint32_t zdr_READ2res (); extern uint32_t zdr_WRITE2args (); extern uint32_t zdr_WRITE2resok (); extern uint32_t zdr_WRITE2res (); extern uint32_t zdr_CREATE2args (); extern uint32_t zdr_CREATE2resok (); extern uint32_t zdr_CREATE2res (); extern uint32_t zdr_REMOVE2args (); extern uint32_t zdr_REMOVE2res (); extern uint32_t zdr_RENAME2args (); extern uint32_t zdr_RENAME2res (); extern uint32_t zdr_LINK2args (); extern uint32_t zdr_LINK2res (); extern uint32_t zdr_SYMLINK2args (); extern uint32_t zdr_SYMLINK2res (); extern uint32_t zdr_MKDIR2args (); extern uint32_t zdr_MKDIR2resok (); extern uint32_t zdr_MKDIR2res (); extern uint32_t zdr_RMDIR2args (); extern uint32_t zdr_RMDIR2res (); extern uint32_t zdr_READDIR2args (); extern uint32_t zdr_READDIR2resok (); extern uint32_t zdr_READDIR2res (); extern uint32_t zdr_STATFS2args (); extern uint32_t zdr_STATFS2resok (); extern uint32_t zdr_STATFS2res (); extern uint32_t zdr_nfsacl_type (); extern uint32_t zdr_nfsacl_ace (); extern uint32_t zdr_GETACL3args (); extern uint32_t zdr_GETACL3resok (); extern uint32_t zdr_GETACL3res (); extern uint32_t zdr_SETACL3args (); extern uint32_t zdr_SETACL3resok (); extern uint32_t zdr_SETACL3res (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_NFS_H_RPCGEN */ libnfs-libnfs-4.0.0/nfs/nfs.c000066400000000000000000001134661343063627400160060ustar00rootroot00000000000000/* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef WIN32 #include #else #include #endif/*WIN32*/ #include #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-nfs.h" char *nfsstat3_to_str(int error) { switch (error) { case NFS3_OK: return "NFS3_OK"; break; case NFS3ERR_PERM: return "NFS3ERR_PERM"; break; case NFS3ERR_NOENT: return "NFS3ERR_NOENT"; break; case NFS3ERR_IO: return "NFS3ERR_IO"; break; case NFS3ERR_NXIO: return "NFS3ERR_NXIO"; break; case NFS3ERR_ACCES: return "NFS3ERR_ACCES"; break; case NFS3ERR_EXIST: return "NFS3ERR_EXIST"; break; case NFS3ERR_XDEV: return "NFS3ERR_XDEV"; break; case NFS3ERR_NODEV: return "NFS3ERR_NODEV"; break; case NFS3ERR_NOTDIR: return "NFS3ERR_NOTDIR"; break; case NFS3ERR_ISDIR: return "NFS3ERR_ISDIR"; break; case NFS3ERR_INVAL: return "NFS3ERR_INVAL"; break; case NFS3ERR_FBIG: return "NFS3ERR_FBIG"; break; case NFS3ERR_NOSPC: return "NFS3ERR_NOSPC"; break; case NFS3ERR_ROFS: return "NFS3ERR_ROFS"; break; case NFS3ERR_MLINK: return "NFS3ERR_MLINK"; break; case NFS3ERR_NAMETOOLONG: return "NFS3ERR_NAMETOOLONG"; break; case NFS3ERR_NOTEMPTY: return "NFS3ERR_NOTEMPTY"; break; case NFS3ERR_DQUOT: return "NFS3ERR_DQUOT"; break; case NFS3ERR_STALE: return "NFS3ERR_STALE"; break; case NFS3ERR_REMOTE: return "NFS3ERR_REMOTE"; break; case NFS3ERR_BADHANDLE: return "NFS3ERR_BADHANDLE"; break; case NFS3ERR_NOT_SYNC: return "NFS3ERR_NOT_SYNC"; break; case NFS3ERR_BAD_COOKIE: return "NFS3ERR_BAD_COOKIE"; break; case NFS3ERR_NOTSUPP: return "NFS3ERR_NOTSUPP"; break; case NFS3ERR_TOOSMALL: return "NFS3ERR_TOOSMALL"; break; case NFS3ERR_SERVERFAULT: return "NFS3ERR_SERVERFAULT"; break; case NFS3ERR_BADTYPE: return "NFS3ERR_BADTYPE"; break; case NFS3ERR_JUKEBOX: return "NFS3ERR_JUKEBOX"; break; }; return "unknown nfs error"; } int nfsstat3_to_errno(int error) { switch (error) { case NFS3_OK: return 0; break; case NFS3ERR_PERM: return -EPERM; break; case NFS3ERR_NOENT: return -ENOENT; break; case NFS3ERR_IO: return -EIO; break; case NFS3ERR_NXIO: return -ENXIO; break; case NFS3ERR_ACCES: return -EACCES; break; case NFS3ERR_EXIST: return -EEXIST; break; case NFS3ERR_XDEV: return -EXDEV; break; case NFS3ERR_NODEV: return -ENODEV; break; case NFS3ERR_NOTDIR: return -ENOTDIR; break; case NFS3ERR_ISDIR: return -EISDIR; break; case NFS3ERR_INVAL: return -EINVAL; break; case NFS3ERR_FBIG: return -EFBIG; break; case NFS3ERR_NOSPC: return -ENOSPC; break; case NFS3ERR_ROFS: return -EROFS; break; case NFS3ERR_MLINK: return -EMLINK; break; case NFS3ERR_NAMETOOLONG: return -ENAMETOOLONG; break; case NFS3ERR_NOTEMPTY: return -ENOTEMPTY; break; case NFS3ERR_DQUOT: return -ERANGE; break; case NFS3ERR_STALE: return -ESTALE; break; case NFS3ERR_REMOTE: return -EIO; break; case NFS3ERR_BADHANDLE: return -EIO; break; case NFS3ERR_NOT_SYNC: return -EIO; break; case NFS3ERR_BAD_COOKIE: return -EIO; break; case NFS3ERR_NOTSUPP: return -EINVAL; break; case NFS3ERR_TOOSMALL: return -EIO; break; case NFS3ERR_SERVERFAULT: return -EIO; break; case NFS3ERR_BADTYPE: return -EINVAL; break; case NFS3ERR_JUKEBOX: return -EAGAIN; break; }; return -ERANGE; } /* * NFSv3 */ int rpc_nfs3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/NULL call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/NULL call"); return -2; } return 0; } int rpc_nfs_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { return rpc_nfs3_null_async(rpc, cb, private_data); } int rpc_nfs3_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct GETATTR3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_GETATTR, cb, private_data, (zdrproc_t)zdr_GETATTR3res, sizeof(GETATTR3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/GETATTR call"); return -1; } if (zdr_GETATTR3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode GETATTR3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/GETATTR call"); return -3; } return 0; } int rpc_nfs_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data) { GETATTR3args args; memset(&args, 0, sizeof(GETATTR3args)); args.object.data.data_len = fh->data.data_len; args.object.data.data_val = fh->data.data_val; return rpc_nfs3_getattr_async(rpc, cb, &args, private_data); } int rpc_nfs3_pathconf_async(struct rpc_context *rpc, rpc_cb cb, struct PATHCONF3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_PATHCONF, cb, private_data, (zdrproc_t)zdr_PATHCONF3res, sizeof(PATHCONF3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/PATHCONF call"); return -1; } if (zdr_PATHCONF3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode PATHCONF3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/PATHCONF call"); return -3; } return 0; } int rpc_nfs_pathconf_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data) { PATHCONF3args args; memset(&args, 0, sizeof(PATHCONF3args)); args.object.data.data_len = fh->data.data_len; args.object.data.data_val = fh->data.data_val; return rpc_nfs3_pathconf_async(rpc, cb, &args, private_data); } int rpc_nfs3_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct LOOKUP3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_LOOKUP, cb, private_data, (zdrproc_t)zdr_LOOKUP3res, sizeof(LOOKUP3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/LOOKUP call"); return -1; } if (zdr_LOOKUP3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode LOOKUP3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/LOOKUP call"); return -3; } return 0; } int rpc_nfs_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *name, void *private_data) { LOOKUP3args args; memset(&args, 0, sizeof(LOOKUP3args)); args.what.dir.data.data_len = fh->data.data_len; args.what.dir.data.data_val = fh->data.data_val; args.what.name = name; return rpc_nfs3_lookup_async(rpc, cb, &args, private_data); } int rpc_nfs3_access_async(struct rpc_context *rpc, rpc_cb cb, struct ACCESS3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_ACCESS, cb, private_data, (zdrproc_t)zdr_ACCESS3res, sizeof(ACCESS3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/ACCESS call"); return -1; } if (zdr_ACCESS3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode ACCESS3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/ACCESS call"); return -3; } return 0; } int rpc_nfs_access_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, int access, void *private_data) { ACCESS3args args; memset(&args, 0, sizeof(ACCESS3args)); args.object.data.data_len = fh->data.data_len; args.object.data.data_val = fh->data.data_val; args.access = access; return rpc_nfs3_access_async(rpc, cb, &args, private_data); } int rpc_nfs3_read_async(struct rpc_context *rpc, rpc_cb cb, struct READ3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READ, cb, private_data, (zdrproc_t)zdr_READ3res, sizeof(READ3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/READ call"); return -1; } if (zdr_READ3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode READ3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/READ call"); return -3; } return 0; } int rpc_nfs_read_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t offset, uint64_t count, void *private_data) { READ3args args; memset(&args, 0, sizeof(READ3args)); args.file.data.data_len = fh->data.data_len; args.file.data.data_val = fh->data.data_val; args.offset = offset; args.count = (count3)count; return rpc_nfs3_read_async(rpc, cb, &args, private_data); } int rpc_nfs3_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu2(rpc, NFS_PROGRAM, NFS_V3, NFS3_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE3res, sizeof(WRITE3res), args->count); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/WRITE call"); return -1; } if (zdr_WRITE3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode WRITE3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/WRITE call"); return -3; } return 0; } int rpc_nfs_write_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *buf, uint64_t offset, uint64_t count, int stable_how, void *private_data) { WRITE3args args; memset(&args, 0, sizeof(WRITE3args)); args.file.data.data_len = fh->data.data_len; args.file.data.data_val = fh->data.data_val; args.offset = offset; args.count = (count3)count; args.stable = stable_how; args.data.data_len = (count3)count; args.data.data_val = buf; return rpc_nfs3_write_async(rpc, cb, &args, private_data); } int rpc_nfs3_commit_async(struct rpc_context *rpc, rpc_cb cb, struct COMMIT3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_COMMIT, cb, private_data, (zdrproc_t)zdr_COMMIT3res, sizeof(COMMIT3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/COMMIT call"); return -1; } if (zdr_COMMIT3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode COMMIT3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/COMMIT call"); return -3; } return 0; } int rpc_nfs_commit_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data) { COMMIT3args args; memset(&args, 0, sizeof(COMMIT3args)); args.file.data.data_len = fh->data.data_len; args.file.data.data_val = fh->data.data_val; args.offset = 0; args.count = 0; return rpc_nfs3_commit_async(rpc, cb, &args, private_data); } int rpc_nfs3_setattr_async(struct rpc_context *rpc, rpc_cb cb, SETATTR3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_SETATTR, cb, private_data, (zdrproc_t)zdr_SETATTR3res, sizeof(SETATTR3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/SETATTR call"); return -1; } if (zdr_SETATTR3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode SETATTR3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/SETATTR call"); return -3; } return 0; } int rpc_nfs_setattr_async(struct rpc_context *rpc, rpc_cb cb, SETATTR3args *args, void *private_data) { return rpc_nfs3_setattr_async(rpc, cb, args, private_data); } int rpc_nfs3_mkdir_async(struct rpc_context *rpc, rpc_cb cb, MKDIR3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_MKDIR, cb, private_data, (zdrproc_t)zdr_MKDIR3res, sizeof(MKDIR3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/MKDIR call"); return -1; } if (zdr_MKDIR3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode MKDIR3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/MKDIR call"); return -3; } return 0; } int rpc_nfs_mkdir_async(struct rpc_context *rpc, rpc_cb cb, MKDIR3args *args, void *private_data) { return rpc_nfs3_mkdir_async(rpc, cb, args, private_data); } int rpc_nfs3_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct RMDIR3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_RMDIR, cb, private_data, (zdrproc_t)zdr_RMDIR3res, sizeof(RMDIR3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/RMDIR call"); return -1; } if (zdr_RMDIR3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode RMDIR3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/RMDIR call"); return -3; } return 0; } int rpc_nfs_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *dir, void *private_data) { RMDIR3args args; memset(&args, 0, sizeof(RMDIR3args)); args.object.dir.data.data_len = fh->data.data_len; args.object.dir.data.data_val = fh->data.data_val; args.object.name = dir; return rpc_nfs3_rmdir_async(rpc, cb, &args, private_data); } int rpc_nfs3_create_async(struct rpc_context *rpc, rpc_cb cb, CREATE3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_CREATE, cb, private_data, (zdrproc_t)zdr_CREATE3res, sizeof(CREATE3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/CREATE call"); return -1; } if (zdr_CREATE3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode CREATE3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/CREATE call"); return -3; } return 0; } int rpc_nfs_create_async(struct rpc_context *rpc, rpc_cb cb, CREATE3args *args, void *private_data) { return rpc_nfs3_create_async(rpc, cb, args, private_data); } int rpc_nfs3_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct MKNOD3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_MKNOD, cb, private_data, (zdrproc_t)zdr_MKNOD3res, sizeof(MKNOD3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/MKNOD call"); return -1; } if (zdr_MKNOD3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode MKNOD3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/MKNOD call"); return -3; } return 0; } int rpc_nfs_mknod_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, int mode, int major, int minor, void *private_data) { MKNOD3args args; memset(&args, 0, sizeof(MKNOD3args)); args.where.dir.data.data_len = fh->data.data_len; args.where.dir.data.data_val = fh->data.data_val; args.where.name = file; switch (mode & S_IFMT) { case S_IFCHR: args.what.type = NF3CHR; args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_it = 1; args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); args.what.mknoddata3_u.chr_device.spec.specdata1 = major; args.what.mknoddata3_u.chr_device.spec.specdata2 = minor; break; case S_IFBLK: args.what.type = NF3BLK; args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_it = 1; args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); args.what.mknoddata3_u.blk_device.spec.specdata1 = major; args.what.mknoddata3_u.blk_device.spec.specdata2 = minor; case S_IFSOCK: args.what.type = NF3SOCK; args.what.mknoddata3_u.sock_attributes.mode.set_it = 1; args.what.mknoddata3_u.sock_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); break; case S_IFIFO: args.what.type = NF3FIFO; args.what.mknoddata3_u.pipe_attributes.mode.set_it = 1; args.what.mknoddata3_u.pipe_attributes.mode.set_mode3_u.mode = mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); break; default: rpc_set_error(rpc, "Invalid file type for NFS3/MKNOD call"); return -1; } return rpc_nfs3_mknod_async(rpc, cb, &args, private_data); } int rpc_nfs3_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_REMOVE, cb, private_data, (zdrproc_t)zdr_REMOVE3res, sizeof(REMOVE3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/REMOVE call"); return -1; } if (zdr_REMOVE3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode REMOVE3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/REMOVE call"); return -3; } return 0; } int rpc_nfs_remove_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, char *file, void *private_data) { REMOVE3args args; memset(&args, 0, sizeof(REMOVE3args)); args.object.dir.data.data_len = fh->data.data_len; args.object.dir.data.data_val = fh->data.data_val; args.object.name = file; return rpc_nfs3_remove_async(rpc, cb, &args, private_data); } int rpc_nfs3_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct READDIR3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READDIR, cb, private_data, (zdrproc_t)zdr_READDIR3res, sizeof(READDIR3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/READDIR call"); return -1; } if (zdr_READDIR3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode READDIR3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/READDIR call"); return -3; } return 0; } int rpc_nfs_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data) { READDIR3args args; memset(&args, 0, sizeof(READDIR3args)); args.dir.data.data_len = fh->data.data_len; args.dir.data.data_val = fh->data.data_val; args.cookie = cookie; memcpy(&args.cookieverf, cookieverf, sizeof(cookieverf3)); args.count = count; return rpc_nfs3_readdir_async(rpc, cb, &args, private_data); } int rpc_nfs3_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct READDIRPLUS3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READDIRPLUS, cb, private_data, (zdrproc_t)zdr_READDIRPLUS3res, sizeof(READDIRPLUS3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/READDIRPLUS call"); return -1; } if (zdr_READDIRPLUS3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode READDIRPLUS3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/READDIRPLUS call"); return -3; } return 0; } int rpc_nfs_readdirplus_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint64_t cookie, char *cookieverf, int count, void *private_data) { READDIRPLUS3args args; memset(&args, 0, sizeof(READDIRPLUS3args)); args.dir.data.data_len = fh->data.data_len; args.dir.data.data_val = fh->data.data_val; args.cookie = cookie; memcpy(&args.cookieverf, cookieverf, sizeof(cookieverf3)); args.dircount = count; args.maxcount = count * 8; return rpc_nfs3_readdirplus_async(rpc, cb, &args, private_data); } int rpc_nfs3_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct FSSTAT3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_FSSTAT, cb, private_data, (zdrproc_t)zdr_FSSTAT3res, sizeof(FSSTAT3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/FSSTAT call"); return -1; } if (zdr_FSSTAT3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode FSSTAT3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/FSSTAT call"); return -3; } return 0; } int rpc_nfs_fsstat_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data) { FSSTAT3args args; memset(&args, 0, sizeof(FSSTAT3args)); args.fsroot.data.data_len = fh->data.data_len; args.fsroot.data.data_val = fh->data.data_val; return rpc_nfs3_fsstat_async(rpc, cb, &args, private_data); } int rpc_nfs3_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct FSINFO3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_FSINFO, cb, private_data, (zdrproc_t)zdr_FSINFO3res, sizeof(FSINFO3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/FSINFO call"); return -1; } if (zdr_FSINFO3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode FSINFO3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/FSINFO call"); return -3; } return 0; } int rpc_nfs_fsinfo_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, void *private_data) { FSINFO3args args; memset(&args, 0, sizeof(FSINFO3args)); args.fsroot.data.data_len = fh->data.data_len; args.fsroot.data.data_val = fh->data.data_val; return rpc_nfs3_fsinfo_async(rpc, cb, &args, private_data); } int rpc_nfs3_readlink_async(struct rpc_context *rpc, rpc_cb cb, READLINK3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_READLINK, cb, private_data, (zdrproc_t)zdr_READLINK3res, sizeof(READLINK3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/READLINK call"); return -1; } if (zdr_READLINK3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode READLINK3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/READLINK call"); return -3; } return 0; } int rpc_nfs_readlink_async(struct rpc_context *rpc, rpc_cb cb, READLINK3args *args, void *private_data) { return rpc_nfs3_readlink_async(rpc, cb, args, private_data); } int rpc_nfs3_symlink_async(struct rpc_context *rpc, rpc_cb cb, SYMLINK3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_SYMLINK, cb, private_data, (zdrproc_t)zdr_SYMLINK3res, sizeof(SYMLINK3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/SYMLINK call"); return -1; } if (zdr_SYMLINK3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode SYMLINK3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/SYMLINK call"); return -3; } return 0; } int rpc_nfs_symlink_async(struct rpc_context *rpc, rpc_cb cb, SYMLINK3args *args, void *private_data) { return rpc_nfs3_symlink_async(rpc, cb, args, private_data); } int rpc_nfs3_rename_async(struct rpc_context *rpc, rpc_cb cb, struct RENAME3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_RENAME, cb, private_data, (zdrproc_t)zdr_RENAME3res, sizeof(RENAME3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/RENAME call"); return -1; } if (zdr_RENAME3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode RENAME3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/RENAME call"); return -3; } return 0; } int rpc_nfs_rename_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *olddir, char *oldname, struct nfs_fh3 *newdir, char *newname, void *private_data) { RENAME3args args; memset(&args, 0, sizeof(RENAME3args)); args.from.dir.data.data_len = olddir->data.data_len; args.from.dir.data.data_val = olddir->data.data_val; args.from.name = oldname; args.to.dir.data.data_len = newdir->data.data_len; args.to.dir.data.data_val = newdir->data.data_val; args.to.name = newname; return rpc_nfs3_rename_async(rpc, cb, &args, private_data); } int rpc_nfs3_link_async(struct rpc_context *rpc, rpc_cb cb, struct LINK3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V3, NFS3_LINK, cb, private_data, (zdrproc_t)zdr_LINK3res, sizeof(LINK3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/LINK call"); return -1; } if (zdr_LINK3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode LINK3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS3/LINK call"); return -3; } return 0; } int rpc_nfs_link_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *file, struct nfs_fh3 *newdir, char *newname, void *private_data) { LINK3args args; memset(&args, 0, sizeof(LINK3args)); args.file.data.data_len = file->data.data_len; args.file.data.data_val = file->data.data_val; args.link.dir.data.data_len = newdir->data.data_len; args.link.dir.data.data_val = newdir->data.data_val; args.link.name = newname; return rpc_nfs3_link_async(rpc, cb, &args, private_data); } /* * NFSv2 */ int rpc_nfs2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/NULL call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/NULL call"); return -2; } return 0; } int rpc_nfs2_getattr_async(struct rpc_context *rpc, rpc_cb cb, struct GETATTR2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_GETATTR, cb, private_data, (zdrproc_t)zdr_GETATTR2res, sizeof(GETATTR2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/GETATTR call"); return -1; } if (zdr_GETATTR2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode GETATTR2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/GETATTR call"); return -3; } return 0; } int rpc_nfs2_setattr_async(struct rpc_context *rpc, rpc_cb cb, SETATTR2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_SETATTR, cb, private_data, (zdrproc_t)zdr_SETATTR2res, sizeof(SETATTR2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/SETATTR call"); return -1; } if (zdr_SETATTR2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode SETATTR2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/SETATTR call"); return -3; } return 0; } int rpc_nfs2_lookup_async(struct rpc_context *rpc, rpc_cb cb, struct LOOKUP2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_LOOKUP, cb, private_data, (zdrproc_t)zdr_LOOKUP2res, sizeof(LOOKUP2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/LOOKUP call"); return -1; } if (zdr_LOOKUP2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode LOOKUP2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/LOOKUP call"); return -3; } return 0; } int rpc_nfs2_readlink_async(struct rpc_context *rpc, rpc_cb cb, READLINK2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_READLINK, cb, private_data, (zdrproc_t)zdr_READLINK2res, sizeof(READLINK2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/READLINK call"); return -1; } if (zdr_READLINK2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode READLINK2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/READLINK call"); return -3; } return 0; } int rpc_nfs2_read_async(struct rpc_context *rpc, rpc_cb cb, struct READ2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_READ, cb, private_data, (zdrproc_t)zdr_READ2res, sizeof(READ2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/READ call"); return -1; } if (zdr_READ2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode READ2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/READ call"); return -3; } return 0; } int rpc_nfs2_write_async(struct rpc_context *rpc, rpc_cb cb, struct WRITE2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu2(rpc, NFS_PROGRAM, NFS_V2, NFS2_WRITE, cb, private_data, (zdrproc_t)zdr_WRITE2res, sizeof(WRITE2res), args->totalcount); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/WRITE call"); return -1; } if (zdr_WRITE2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode WRITE2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/WRITE call"); return -3; } return 0; } int rpc_nfs2_create_async(struct rpc_context *rpc, rpc_cb cb, CREATE2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_CREATE, cb, private_data, (zdrproc_t)zdr_CREATE2res, sizeof(CREATE2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/CREATE call"); return -1; } if (zdr_CREATE2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode CREATE2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/CREATE call"); return -3; } return 0; } int rpc_nfs2_remove_async(struct rpc_context *rpc, rpc_cb cb, struct REMOVE2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_REMOVE, cb, private_data, (zdrproc_t)zdr_REMOVE2res, sizeof(REMOVE2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS3/REMOVE call"); return -1; } if (zdr_REMOVE2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode REMOVE2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/REMOVE call"); return -3; } return 0; } int rpc_nfs2_rename_async(struct rpc_context *rpc, rpc_cb cb, struct RENAME2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_RENAME, cb, private_data, (zdrproc_t)zdr_RENAME2res, sizeof(RENAME2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/RENAME call"); return -1; } if (zdr_RENAME2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode RENAME2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/RENAME call"); return -3; } return 0; } int rpc_nfs2_link_async(struct rpc_context *rpc, rpc_cb cb, LINK2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_LINK, cb, private_data, (zdrproc_t)zdr_LINK2res, sizeof(LINK2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/LINK call"); return -1; } if (zdr_LINK2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode LINK2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/LINK call"); return -3; } return 0; } int rpc_nfs2_symlink_async(struct rpc_context *rpc, rpc_cb cb, SYMLINK2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_SYMLINK, cb, private_data, (zdrproc_t)zdr_SYMLINK2res, sizeof(SYMLINK2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/SYMLINK call"); return -1; } if (zdr_SYMLINK2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode SYMLINK2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/SYMLINK call"); return -3; } return 0; } int rpc_nfs2_mkdir_async(struct rpc_context *rpc, rpc_cb cb, MKDIR2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_MKDIR, cb, private_data, (zdrproc_t)zdr_MKDIR2res, sizeof(MKDIR2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/MKDIR call"); return -1; } if (zdr_MKDIR2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode MKDIR2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/MKDIR call"); return -3; } return 0; } int rpc_nfs2_rmdir_async(struct rpc_context *rpc, rpc_cb cb, struct RMDIR2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_RMDIR, cb, private_data, (zdrproc_t)zdr_RMDIR2res, sizeof(RMDIR2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/RMDIR call"); return -1; } if (zdr_RMDIR2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode RMDIR2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/RMDIR call"); return -3; } return 0; } int rpc_nfs2_readdir_async(struct rpc_context *rpc, rpc_cb cb, struct READDIR2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_READDIR, cb, private_data, (zdrproc_t)zdr_READDIR2res, sizeof(READDIR2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/READDIR call"); return -1; } if (zdr_READDIR2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode READDIR2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/READDIR call"); return -3; } return 0; } int rpc_nfs2_statfs_async(struct rpc_context *rpc, rpc_cb cb, struct STATFS2args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS_PROGRAM, NFS_V2, NFS2_STATFS, cb, private_data, (zdrproc_t)zdr_STATFS2res, sizeof(STATFS2res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for NFS2/STATFS call"); return -1; } if (zdr_STATFS2args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode STATFS2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for NFS2/STATFS call"); return -3; } return 0; } libnfs-libnfs-4.0.0/nfs/nfs.x000066400000000000000000000533071343063627400160300ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * NFS v3 Definitions */ const NFS3_FHSIZE = 64; /* Maximum bytes in a V3 file handle */ const NFS3_WRITEVERFSIZE = 8; const NFS3_CREATEVERFSIZE = 8; const NFS3_COOKIEVERFSIZE = 8; typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; typedef uint64_t cookie3; struct nfs_fh3 { opaque data; }; typedef string filename3<>; struct diropargs3 { nfs_fh3 dir; filename3 name; }; enum ftype3 { NF3REG = 1, NF3DIR = 2, NF3BLK = 3, NF3CHR = 4, NF3LNK = 5, NF3SOCK = 6, NF3FIFO = 7 }; typedef unsigned int mode3; typedef unsigned int uid3; typedef unsigned int gid3; typedef uint64_t size3; typedef uint64_t fileid3; struct specdata3 { unsigned int specdata1; unsigned int specdata2; }; struct nfstime3 { unsigned int seconds; unsigned int nseconds; }; struct fattr3 { ftype3 type; mode3 mode; unsigned int nlink; uid3 uid; gid3 gid; size3 size; size3 used; specdata3 rdev; uint64_t fsid; fileid3 fileid; nfstime3 atime; nfstime3 mtime; nfstime3 ctime; }; union post_op_attr switch (bool attributes_follow) { case TRUE: fattr3 attributes; case FALSE: void; }; enum nfsstat3 { NFS3_OK = 0, NFS3ERR_PERM = 1, NFS3ERR_NOENT = 2, NFS3ERR_IO = 5, NFS3ERR_NXIO = 6, NFS3ERR_ACCES = 13, NFS3ERR_EXIST = 17, NFS3ERR_XDEV = 18, NFS3ERR_NODEV = 19, NFS3ERR_NOTDIR = 20, NFS3ERR_ISDIR = 21, NFS3ERR_INVAL = 22, NFS3ERR_FBIG = 27, NFS3ERR_NOSPC = 28, NFS3ERR_ROFS = 30, NFS3ERR_MLINK = 31, NFS3ERR_NAMETOOLONG = 63, NFS3ERR_NOTEMPTY = 66, NFS3ERR_DQUOT = 69, NFS3ERR_STALE = 70, NFS3ERR_REMOTE = 71, NFS3ERR_BADHANDLE = 10001, NFS3ERR_NOT_SYNC = 10002, NFS3ERR_BAD_COOKIE = 10003, NFS3ERR_NOTSUPP = 10004, NFS3ERR_TOOSMALL = 10005, NFS3ERR_SERVERFAULT = 10006, NFS3ERR_BADTYPE = 10007, NFS3ERR_JUKEBOX = 10008 }; enum stable_how { UNSTABLE = 0, DATA_SYNC = 1, FILE_SYNC = 2 }; typedef uint64_t offset3; typedef unsigned int count3; struct wcc_attr { size3 size; nfstime3 mtime; nfstime3 ctime; }; union pre_op_attr switch (bool attributes_follow) { case TRUE: wcc_attr attributes; case FALSE: void; }; struct wcc_data { pre_op_attr before; post_op_attr after; }; struct WRITE3args { nfs_fh3 file; offset3 offset; count3 count; stable_how stable; opaque data<>; }; typedef opaque writeverf3[NFS3_WRITEVERFSIZE]; struct WRITE3resok { wcc_data file_wcc; count3 count; stable_how committed; writeverf3 verf; }; struct WRITE3resfail { wcc_data file_wcc; }; union WRITE3res switch (nfsstat3 status) { case NFS3_OK: WRITE3resok resok; default: WRITE3resfail resfail; }; struct LOOKUP3args { diropargs3 what; }; struct LOOKUP3resok { nfs_fh3 object; post_op_attr obj_attributes; post_op_attr dir_attributes; }; struct LOOKUP3resfail { post_op_attr dir_attributes; }; union LOOKUP3res switch (nfsstat3 status) { case NFS3_OK: LOOKUP3resok resok; default: LOOKUP3resfail resfail; }; struct COMMIT3args { nfs_fh3 file; offset3 offset; count3 count; }; struct COMMIT3resok { wcc_data file_wcc; writeverf3 verf; }; struct COMMIT3resfail { wcc_data file_wcc; }; union COMMIT3res switch (nfsstat3 status) { case NFS3_OK: COMMIT3resok resok; default: COMMIT3resfail resfail; }; const ACCESS3_READ = 0x0001; const ACCESS3_LOOKUP = 0x0002; const ACCESS3_MODIFY = 0x0004; const ACCESS3_EXTEND = 0x0008; const ACCESS3_DELETE = 0x0010; const ACCESS3_EXECUTE = 0x0020; struct ACCESS3args { nfs_fh3 object; unsigned int access; }; struct ACCESS3resok { post_op_attr obj_attributes; unsigned int access; }; struct ACCESS3resfail { post_op_attr obj_attributes; }; union ACCESS3res switch (nfsstat3 status) { case NFS3_OK: ACCESS3resok resok; default: ACCESS3resfail resfail; }; struct GETATTR3args { nfs_fh3 object; }; struct GETATTR3resok { fattr3 obj_attributes; }; union GETATTR3res switch (nfsstat3 status) { case NFS3_OK: GETATTR3resok resok; default: void; }; enum time_how { DONT_CHANGE = 0, SET_TO_SERVER_TIME = 1, SET_TO_CLIENT_TIME = 2 }; union set_mode3 switch (bool set_it) { case TRUE: mode3 mode; default: void; }; union set_uid3 switch (bool set_it) { case TRUE: uid3 uid; default: void; }; union set_gid3 switch (bool set_it) { case TRUE: gid3 gid; default: void; }; union set_size3 switch (bool set_it) { case TRUE: size3 size; default: void; }; union set_atime switch (time_how set_it) { case SET_TO_CLIENT_TIME: nfstime3 atime; default: void; }; union set_mtime switch (time_how set_it) { case SET_TO_CLIENT_TIME: nfstime3 mtime; default: void; }; struct sattr3 { set_mode3 mode; set_uid3 uid; set_gid3 gid; set_size3 size; set_atime atime; set_mtime mtime; }; enum createmode3 { UNCHECKED = 0, GUARDED = 1, EXCLUSIVE = 2 }; typedef opaque createverf3[NFS3_CREATEVERFSIZE]; union createhow3 switch (createmode3 mode) { case UNCHECKED: sattr3 obj_attributes; case GUARDED: sattr3 g_obj_attributes; case EXCLUSIVE: createverf3 verf; }; struct CREATE3args { diropargs3 where; createhow3 how; }; union post_op_fh3 switch (bool handle_follows) { case TRUE: nfs_fh3 handle; case FALSE: void; }; struct CREATE3resok { post_op_fh3 obj; post_op_attr obj_attributes; wcc_data dir_wcc; }; struct CREATE3resfail { wcc_data dir_wcc; }; union CREATE3res switch (nfsstat3 status) { case NFS3_OK: CREATE3resok resok; default: CREATE3resfail resfail; }; struct REMOVE3args { diropargs3 object; }; struct REMOVE3resok { wcc_data dir_wcc; }; struct REMOVE3resfail { wcc_data dir_wcc; }; union REMOVE3res switch (nfsstat3 status) { case NFS3_OK: REMOVE3resok resok; default: REMOVE3resfail resfail; }; struct READ3args { nfs_fh3 file; offset3 offset; count3 count; }; struct READ3resok { post_op_attr file_attributes; count3 count; bool eof; opaque data<>; }; struct READ3resfail { post_op_attr file_attributes; }; union READ3res switch (nfsstat3 status) { case NFS3_OK: READ3resok resok; default: READ3resfail resfail; }; const FSF3_LINK = 0x0001; const FSF3_SYMLINK = 0x0002; const FSF3_HOMOGENEOUS = 0x0008; const FSF3_CANSETTIME = 0x0010; struct FSINFO3args { nfs_fh3 fsroot; }; struct FSINFO3resok { post_op_attr obj_attributes; unsigned int rtmax; unsigned int rtpref; unsigned int rtmult; unsigned int wtmax; unsigned int wtpref; unsigned int wtmult; unsigned int dtpref; size3 maxfilesize; nfstime3 time_delta; unsigned int properties; }; struct FSINFO3resfail { post_op_attr obj_attributes; }; union FSINFO3res switch (nfsstat3 status) { case NFS3_OK: FSINFO3resok resok; default: FSINFO3resfail resfail; }; struct FSSTAT3args { nfs_fh3 fsroot; }; struct FSSTAT3resok { post_op_attr obj_attributes; size3 tbytes; size3 fbytes; size3 abytes; size3 tfiles; size3 ffiles; size3 afiles; unsigned int invarsec; }; struct FSSTAT3resfail { post_op_attr obj_attributes; }; union FSSTAT3res switch (nfsstat3 status) { case NFS3_OK: FSSTAT3resok resok; default: FSSTAT3resfail resfail; }; struct PATHCONF3args { nfs_fh3 object; }; struct PATHCONF3resok { post_op_attr obj_attributes; unsigned int linkmax; unsigned int name_max; bool no_trunc; bool chown_restricted; bool case_insensitive; bool case_preserving; }; struct PATHCONF3resfail { post_op_attr obj_attributes; }; union PATHCONF3res switch (nfsstat3 status) { case NFS3_OK: PATHCONF3resok resok; default: PATHCONF3resfail resfail; }; typedef string nfspath3<>; struct symlinkdata3 { sattr3 symlink_attributes; nfspath3 symlink_data; }; struct SYMLINK3args { diropargs3 where; symlinkdata3 symlink; }; struct SYMLINK3resok { post_op_fh3 obj; post_op_attr obj_attributes; wcc_data dir_wcc; }; struct SYMLINK3resfail { wcc_data dir_wcc; }; union SYMLINK3res switch (nfsstat3 status) { case NFS3_OK: SYMLINK3resok resok; default: SYMLINK3resfail resfail; }; struct READLINK3args { nfs_fh3 symlink; }; struct READLINK3resok { post_op_attr symlink_attributes; nfspath3 data; }; struct READLINK3resfail { post_op_attr symlink_attributes; }; union READLINK3res switch (nfsstat3 status) { case NFS3_OK: READLINK3resok resok; default: READLINK3resfail resfail; }; struct devicedata3 { sattr3 dev_attributes; specdata3 spec; }; union mknoddata3 switch (ftype3 type) { case NF3CHR: devicedata3 chr_device; case NF3BLK: devicedata3 blk_device; case NF3SOCK: sattr3 sock_attributes; case NF3FIFO: sattr3 pipe_attributes; default: void; }; struct MKNOD3args { diropargs3 where; mknoddata3 what; }; struct MKNOD3resok { post_op_fh3 obj; post_op_attr obj_attributes; wcc_data dir_wcc; }; struct MKNOD3resfail { wcc_data dir_wcc; }; union MKNOD3res switch (nfsstat3 status) { case NFS3_OK: MKNOD3resok resok; default: MKNOD3resfail resfail; }; struct MKDIR3args { diropargs3 where; sattr3 attributes; }; struct MKDIR3resok { post_op_fh3 obj; post_op_attr obj_attributes; wcc_data dir_wcc; }; struct MKDIR3resfail { wcc_data dir_wcc; }; union MKDIR3res switch (nfsstat3 status) { case NFS3_OK: MKDIR3resok resok; default: MKDIR3resfail resfail; }; struct RMDIR3args { diropargs3 object; }; struct RMDIR3resok { wcc_data dir_wcc; }; struct RMDIR3resfail { wcc_data dir_wcc; }; union RMDIR3res switch (nfsstat3 status) { case NFS3_OK: RMDIR3resok resok; default: RMDIR3resfail resfail; }; struct RENAME3args { diropargs3 from; diropargs3 to; }; struct RENAME3resok { wcc_data fromdir_wcc; wcc_data todir_wcc; }; struct RENAME3resfail { wcc_data fromdir_wcc; wcc_data todir_wcc; }; union RENAME3res switch (nfsstat3 status) { case NFS3_OK: RENAME3resok resok; default: RENAME3resfail resfail; }; struct READDIRPLUS3args { nfs_fh3 dir; cookie3 cookie; cookieverf3 cookieverf; count3 dircount; count3 maxcount; }; struct entryplus3 { fileid3 fileid; filename3 name; cookie3 cookie; post_op_attr name_attributes; post_op_fh3 name_handle; entryplus3 *nextentry; }; struct dirlistplus3 { entryplus3 *entries; bool eof; }; struct READDIRPLUS3resok { post_op_attr dir_attributes; cookieverf3 cookieverf; dirlistplus3 reply; }; struct READDIRPLUS3resfail { post_op_attr dir_attributes; }; union READDIRPLUS3res switch (nfsstat3 status) { case NFS3_OK: READDIRPLUS3resok resok; default: READDIRPLUS3resfail resfail; }; struct READDIR3args { nfs_fh3 dir; cookie3 cookie; cookieverf3 cookieverf; count3 count; }; struct entry3 { fileid3 fileid; filename3 name; cookie3 cookie; entry3 *nextentry; }; struct dirlist3 { entry3 *entries; bool eof; }; struct READDIR3resok { post_op_attr dir_attributes; cookieverf3 cookieverf; dirlist3 reply; }; struct READDIR3resfail { post_op_attr dir_attributes; }; union READDIR3res switch (nfsstat3 status) { case NFS3_OK: READDIR3resok resok; default: READDIR3resfail resfail; }; struct LINK3args { nfs_fh3 file; diropargs3 link; }; struct LINK3resok { post_op_attr file_attributes; wcc_data linkdir_wcc; }; struct LINK3resfail { post_op_attr file_attributes; wcc_data linkdir_wcc; }; union LINK3res switch (nfsstat3 status) { case NFS3_OK: LINK3resok resok; default: LINK3resfail resfail; }; union sattrguard3 switch (bool check) { case TRUE: nfstime3 obj_ctime; case FALSE: void; }; struct SETATTR3args { nfs_fh3 object; sattr3 new_attributes; sattrguard3 guard; }; struct SETATTR3resok { wcc_data obj_wcc; }; struct SETATTR3resfail { wcc_data obj_wcc; }; union SETATTR3res switch (nfsstat3 status) { case NFS3_OK: SETATTR3resok resok; default: SETATTR3resfail resfail; }; /* * NFS v2 Definitions * We share many definitions from v3 */ const FHSIZE2 = 32; typedef opaque fhandle2[FHSIZE2]; enum ftype2 { NF2NON = 0, NF2REG = 1, NF2DIR = 2, NF2BLK = 3, NF2CHR = 4, NF2LNK = 5 }; struct fattr2 { ftype2 type; unsigned int mode; unsigned int nlink; unsigned int uid; unsigned int gid; unsigned int size; unsigned int blocksize; unsigned int rdev; unsigned int blocks; unsigned int fsid; unsigned int fileid; nfstime3 atime; nfstime3 mtime; nfstime3 ctime; }; struct sattr2 { unsigned int mode; unsigned int uid; unsigned int gid; unsigned int size; nfstime3 atime; nfstime3 mtime; }; const MAXNAMLEN2 = 255; typedef string filename2; const MAXPATHLEN2 = 1024; typedef string path2; const NFSMAXDATA2 = 8192; typedef opaque nfsdata2; const NFSCOOKIESIZE2 = 4; typedef opaque nfscookie2[NFSCOOKIESIZE2]; struct entry2 { unsigned int fileid; filename2 name; nfscookie2 cookie; entry2 *nextentry; }; struct diropargs2 { fhandle2 dir; filename2 name; }; struct GETATTR2args { fhandle2 fhandle; }; struct GETATTR2resok { fattr2 attributes; }; union GETATTR2res switch (nfsstat3 status) { case NFS3_OK: GETATTR2resok resok; default: void; }; struct SETATTR2args { fhandle2 fhandle; sattr2 attributes; }; struct SETATTR2resok { fattr2 attributes; }; union SETATTR2res switch (nfsstat3 status) { case NFS3_OK: SETATTR2resok resok; default: void; }; struct LOOKUP2args { diropargs2 what; }; struct LOOKUP2resok { fhandle2 file; fattr2 attributes; }; union LOOKUP2res switch (nfsstat3 status) { case NFS3_OK: LOOKUP2resok resok; default: void; }; struct READLINK2args { fhandle2 file; }; struct READLINK2resok { path2 data; }; union READLINK2res switch (nfsstat3 status) { case NFS3_OK: READLINK2resok resok; default: void; }; struct READ2args { fhandle2 file; unsigned int offset; unsigned int count; unsigned int totalcount; }; struct READ2resok { fattr2 attributes; nfsdata2 data; }; union READ2res switch (nfsstat3 status) { case NFS3_OK: READ2resok resok; default: void; }; struct WRITE2args { fhandle2 file; unsigned int beginoffset; unsigned int offset; unsigned int totalcount; nfsdata2 data; }; struct WRITE2resok { fattr2 attributes; }; union WRITE2res switch (nfsstat3 status) { case NFS3_OK: WRITE2resok resok; default: void; }; struct CREATE2args { diropargs2 where; sattr2 attributes; }; struct CREATE2resok { fhandle2 file; fattr2 attributes; }; union CREATE2res switch (nfsstat3 status) { case NFS3_OK: CREATE2resok resok; default: void; }; struct REMOVE2args { diropargs2 what; }; struct REMOVE2res { nfsstat3 status; }; struct RENAME2args { diropargs2 from; diropargs2 to; }; struct RENAME2res { nfsstat3 status; }; struct LINK2args { fhandle2 from; diropargs2 to; }; struct LINK2res { nfsstat3 status; }; struct SYMLINK2args { diropargs2 from; path2 to; sattr2 attributes; }; struct SYMLINK2res { nfsstat3 status; }; struct MKDIR2args { diropargs2 where; sattr2 attributes; }; struct MKDIR2resok { fhandle2 file; fattr2 attributes; }; union MKDIR2res switch (nfsstat3 status) { case NFS3_OK: MKDIR2resok resok; default: void; }; struct RMDIR2args { diropargs2 what; }; struct RMDIR2res { nfsstat3 status; }; struct READDIR2args { fhandle2 dir; nfscookie2 cookie; unsigned int count; }; struct READDIR2resok { entry2 *entries; bool eof; }; union READDIR2res switch (nfsstat3 status) { case NFS3_OK: READDIR2resok resok; default: void; }; struct STATFS2args { fhandle2 dir; }; struct STATFS2resok { unsigned int tsize; unsigned int bsize; unsigned int blocks; unsigned int bfree; unsigned int bavail; }; union STATFS2res switch (nfsstat3 status) { case NFS3_OK: STATFS2resok resok; default: void; }; program NFS_PROGRAM { version NFS_V2 { void NFS2_NULL(void) = 0; GETATTR2res NFS2_GETATTR(GETATTR2args) = 1; SETATTR2res NFS2_SETATTR(SETATTR2args) = 2; LOOKUP2res NFS2_LOOKUP(LOOKUP2args) = 4; READLINK2res NFS2_READLINK(READLINK2args) = 5; READ2res NFS2_READ(READ2args) = 6; WRITE2res NFS2_WRITE(WRITE2args) = 8; CREATE2res NFS2_CREATE(CREATE2args) = 9; REMOVE2res NFS2_REMOVE(REMOVE2args) = 10; RENAME2res NFS2_RENAME(RENAME2args) = 11; LINK2res NFS2_LINK(LINK2args) = 12; SYMLINK2res NFS2_SYMLINK(SYMLINK2args) = 13; MKDIR2res NFS2_MKDIR(MKDIR2args) = 14; RMDIR2res NFS2_RMDIR(RMDIR2args) = 15; READDIR2res NFS2_READDIR(READDIR2args) = 16; STATFS2res NFS2_STATFS(STATFS2args) = 17; } = 2; version NFS_V3 { void NFS3_NULL(void) = 0; GETATTR3res NFS3_GETATTR(GETATTR3args) = 1; SETATTR3res NFS3_SETATTR(SETATTR3args) = 2; LOOKUP3res NFS3_LOOKUP(LOOKUP3args) = 3; ACCESS3res NFS3_ACCESS(ACCESS3args) = 4; READLINK3res NFS3_READLINK(READLINK3args) = 5; READ3res NFS3_READ(READ3args) = 6; WRITE3res NFS3_WRITE(WRITE3args) = 7; CREATE3res NFS3_CREATE(CREATE3args) = 8; MKDIR3res NFS3_MKDIR(MKDIR3args) = 9; SYMLINK3res NFS3_SYMLINK(SYMLINK3args) = 10; MKNOD3res NFS3_MKNOD(MKNOD3args) = 11; REMOVE3res NFS3_REMOVE(REMOVE3args) = 12; RMDIR3res NFS3_RMDIR(RMDIR3args) = 13; RENAME3res NFS3_RENAME(RENAME3args) = 14; LINK3res NFS3_LINK(LINK3args) = 15; READDIR3res NFS3_READDIR(READDIR3args) = 16; READDIRPLUS3res NFS3_READDIRPLUS(READDIRPLUS3args) = 17; FSSTAT3res NFS3_FSSTAT(FSSTAT3args) = 18; FSINFO3res NFS3_FSINFO(FSINFO3args) = 19; PATHCONF3res NFS3_PATHCONF(PATHCONF3args) = 20; COMMIT3res NFS3_COMMIT(COMMIT3args) = 21; } = 3; } = 100003; /* NFS ACL definitions based on wireshark souces and network traces */ /* NFSACL interface. Uses same port/process as NFS */ enum nfsacl_type { NFSACL_TYPE_USER_OBJ = 0x0001, NFSACL_TYPE_USER = 0x0002, NFSACL_TYPE_GROUP_OBJ = 0x0004, NFSACL_TYPE_GROUP = 0x0008, NFSACL_TYPE_CLASS_OBJ = 0x0010, NFSACL_TYPE_CLASS = 0x0020, NFSACL_TYPE_DEFAULT = 0x1000, NFSACL_TYPE_DEFAULT_USER_OBJ = 0x1001, NFSACL_TYPE_DEFAULT_USER = 0x1002, NFSACL_TYPE_DEFAULT_GROUP_OBJ = 0x1004, NFSACL_TYPE_DEFAULT_GROUP = 0x1008, NFSACL_TYPE_DEFAULT_CLASS_OBJ = 0x1010, NFSACL_TYPE_DEFAULT_OTHER_OBJ = 0x1020 }; const NFSACL_PERM_READ = 0x04; const NFSACL_PERM_WRITE = 0x02; const NFSACL_PERM_EXEC = 0x01; struct nfsacl_ace { enum nfsacl_type type; unsigned int id; unsigned int perm; }; const NFSACL_MASK_ACL_ENTRY = 0x0001; const NFSACL_MASK_ACL_COUNT = 0x0002; const NFSACL_MASK_ACL_DEFAULT_ENTRY = 0x0004; const NFSACL_MASK_ACL_DEFAULT_COUNT = 0x0008; struct GETACL3args { nfs_fh3 dir; unsigned int mask; }; struct GETACL3resok { post_op_attr attr; unsigned int mask; unsigned int ace_count; struct nfsacl_ace ace<>; unsigned int default_ace_count; struct nfsacl_ace default_ace<>; }; union GETACL3res switch (nfsstat3 status) { case NFS3_OK: GETACL3resok resok; default: void; }; struct SETACL3args { nfs_fh3 dir; unsigned int mask; unsigned int ace_count; struct nfsacl_ace ace<>; unsigned int default_ace_count; struct nfsacl_ace default_ace<>; }; struct SETACL3resok { post_op_attr attr; }; union SETACL3res switch (nfsstat3 status) { case NFS3_OK: SETACL3resok resok; default: void; }; program NFSACL_PROGRAM { version NFSACL_V3 { void NFSACL3_NULL(void) = 0; GETACL3res NFSACL3_GETACL(GETACL3args) = 1; SETACL3res NFSACL3_SETACL(SETACL3args) = 2; } = 3; } = 100227; libnfs-libnfs-4.0.0/nfs/nfsacl.c000066400000000000000000000055311343063627400164570ustar00rootroot00000000000000/* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef WIN32 #include #else #include #endif/*WIN32*/ #include #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-nfs.h" int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFSACL_PROGRAM, NFSACL_V3, NFSACL3_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfsacl/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfsacl/null call"); return -2; } return 0; } int rpc_nfsacl_getacl_async(struct rpc_context *rpc, rpc_cb cb, struct GETACL3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFSACL_PROGRAM, NFSACL_V3, NFSACL3_GETACL, cb, private_data, (zdrproc_t)zdr_GETACL3res, sizeof(GETACL3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfsacl/getacl call"); return -1; } if (zdr_GETACL3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode GETACL3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfsacl/getacl call"); return -2; } return 0; } int rpc_nfsacl_setacl_async(struct rpc_context *rpc, rpc_cb cb, struct SETACL3args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFSACL_PROGRAM, NFSACL_V3, NFSACL3_SETACL, cb, private_data, (zdrproc_t)zdr_SETACL3res, sizeof(SETACL3res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfsacl/setacl call"); return -1; } if (zdr_SETACL3args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode SETACL3args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfsacl/setacl call"); return -2; } return 0; } libnfs-libnfs-4.0.0/nfs4/000077500000000000000000000000001343063627400151255ustar00rootroot00000000000000libnfs-libnfs-4.0.0/nfs4/CMakeLists.txt000066400000000000000000000001511343063627400176620ustar00rootroot00000000000000set(SOURCES libnfs-raw-nfs4.c nfs4.c) set(HEADERS libnfs-raw-nfs4.h) core_add_library(nfs4) libnfs-libnfs-4.0.0/nfs4/Makefile.am000066400000000000000000000023441343063627400171640ustar00rootroot00000000000000noinst_LTLIBRARIES = libnfs4.la nfs4_SOURCES_GENERATED = nfs4_HEADERS_GENERATED = nfs4_GENERATED = $(nfs4_SOURCES_GENERATED) $(nfs4_HEADERS_GENERATED) CLEANFILES = $(nfs_GENERATED) nfs4-stamp libnfs4_la_CPPFLAGS = -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/win32 libnfs4_la_SOURCES = \ $(nfs4_SOURCES_GENERATED) \ nfs4.c libnfs-raw-nfs4.c libnfs-raw-nfs4.h $(nfs4_GENERATED) : nfs4-stamp nfs4-stamp : nfs4.x rm -f $(nfs_GENERATED) touch nfs4-stamp compile_rpc: cat nfs4.x | head -29 >libnfs-raw-nfs4.h rpcgen -h nfs4.x | sed \ -e "s/#include /#include /" \ -e "s/xdr/zdr/g" \ -e "s/XDR/ZDR/g" \ -e "s/#define _NFS_H_RPCGEN/#define _NFS_H_RPCGEN\n#include /g" \ -e "s/#define NFS3_COOKIEVERFSIZE 8/#define NFS3_COOKIEVERFSIZE 8\n\n/g" \ -e "s/ CLIENT / void /g" \ -e "s/SVCXPRT /void /g" \ -e "s/bool_t/uint32_t/g" >> libnfs-raw-nfs4.h cat nfs4.x | head -29 >libnfs-raw-nfs4.c rpcgen -c nfs4.x | sed \ -e "s/#include \".*nfs4.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nfs4.h\"/" \ -e "s/xdr/zdr/g" \ -e "s/XDR/ZDR/g" \ -e "s/bool_t/uint32_t/g" \ -e "s/register int32_t \*buf;//" \ -e "s/int i;//" >> libnfs-raw-nfs4.c libnfs-libnfs-4.0.0/nfs4/libnfs-raw-nfs4.c000066400000000000000000001521251343063627400202130ustar00rootroot00000000000000/* This is based on RFC3530 which contains the following copyright statement: Copyright (C) The Internet Society (2003). All Rights Reserved. This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English. The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns. This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #include "libnfs-zdr.h" #include "libnfs-raw-nfs4.h" uint32_t zdr_nfs_ftype4 (ZDR *zdrs, nfs_ftype4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_nfsstat4 (ZDR *zdrs, nfsstat4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_bitmap4 (ZDR *zdrs, bitmap4 *objp) { if (!zdr_array (zdrs, (char **)&objp->bitmap4_val, (u_int *) &objp->bitmap4_len, ~0, sizeof (uint32_t), (zdrproc_t) zdr_uint32_t)) return FALSE; return TRUE; } uint32_t zdr_offset4 (ZDR *zdrs, offset4 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_count4 (ZDR *zdrs, count4 *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_length4 (ZDR *zdrs, length4 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_clientid4 (ZDR *zdrs, clientid4 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_seqid4 (ZDR *zdrs, seqid4 *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_utf8string (ZDR *zdrs, utf8string *objp) { if (!zdr_bytes (zdrs, (char **)&objp->utf8string_val, (u_int *) &objp->utf8string_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_utf8str_cis (ZDR *zdrs, utf8str_cis *objp) { if (!zdr_utf8string (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_utf8str_cs (ZDR *zdrs, utf8str_cs *objp) { if (!zdr_utf8string (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_utf8str_mixed (ZDR *zdrs, utf8str_mixed *objp) { if (!zdr_utf8string (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_component4 (ZDR *zdrs, component4 *objp) { if (!zdr_utf8str_cs (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_pathname4 (ZDR *zdrs, pathname4 *objp) { if (!zdr_array (zdrs, (char **)&objp->pathname4_val, (u_int *) &objp->pathname4_len, ~0, sizeof (component4), (zdrproc_t) zdr_component4)) return FALSE; return TRUE; } uint32_t zdr_nfs_lockid4 (ZDR *zdrs, nfs_lockid4 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_nfs_cookie4 (ZDR *zdrs, nfs_cookie4 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_linktext4 (ZDR *zdrs, linktext4 *objp) { if (!zdr_utf8str_cs (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_sec_oid4 (ZDR *zdrs, sec_oid4 *objp) { if (!zdr_bytes (zdrs, (char **)&objp->sec_oid4_val, (u_int *) &objp->sec_oid4_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_qop4 (ZDR *zdrs, qop4 *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_mode4 (ZDR *zdrs, mode4 *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_changeid4 (ZDR *zdrs, changeid4 *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_verifier4 (ZDR *zdrs, verifier4 objp) { if (!zdr_opaque (zdrs, objp, NFS4_VERIFIER_SIZE)) return FALSE; return TRUE; } uint32_t zdr_nfstime4 (ZDR *zdrs, nfstime4 *objp) { if (!zdr_int64_t (zdrs, &objp->seconds)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->nseconds)) return FALSE; return TRUE; } uint32_t zdr_time_how4 (ZDR *zdrs, time_how4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_settime4 (ZDR *zdrs, settime4 *objp) { if (!zdr_time_how4 (zdrs, &objp->set_it)) return FALSE; switch (objp->set_it) { case SET_TO_CLIENT_TIME4: if (!zdr_nfstime4 (zdrs, &objp->settime4_u.time)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_nfs_fh4 (ZDR *zdrs, nfs_fh4 *objp) { if (!zdr_bytes (zdrs, (char **)&objp->nfs_fh4_val, (u_int *) &objp->nfs_fh4_len, NFS4_FHSIZE)) return FALSE; return TRUE; } uint32_t zdr_fsid4 (ZDR *zdrs, fsid4 *objp) { if (!zdr_uint64_t (zdrs, &objp->major)) return FALSE; if (!zdr_uint64_t (zdrs, &objp->minor)) return FALSE; return TRUE; } uint32_t zdr_fs_location4 (ZDR *zdrs, fs_location4 *objp) { if (!zdr_array (zdrs, (char **)&objp->server.server_val, (u_int *) &objp->server.server_len, ~0, sizeof (utf8str_cis), (zdrproc_t) zdr_utf8str_cis)) return FALSE; if (!zdr_pathname4 (zdrs, &objp->rootpath)) return FALSE; return TRUE; } uint32_t zdr_fs_locations4 (ZDR *zdrs, fs_locations4 *objp) { if (!zdr_pathname4 (zdrs, &objp->fs_root)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->locations.locations_val, (u_int *) &objp->locations.locations_len, ~0, sizeof (fs_location4), (zdrproc_t) zdr_fs_location4)) return FALSE; return TRUE; } uint32_t zdr_acetype4 (ZDR *zdrs, acetype4 *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_aceflag4 (ZDR *zdrs, aceflag4 *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_acemask4 (ZDR *zdrs, acemask4 *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_nfsace4 (ZDR *zdrs, nfsace4 *objp) { if (!zdr_acetype4 (zdrs, &objp->type)) return FALSE; if (!zdr_aceflag4 (zdrs, &objp->flag)) return FALSE; if (!zdr_acemask4 (zdrs, &objp->access_mask)) return FALSE; if (!zdr_utf8str_mixed (zdrs, &objp->who)) return FALSE; return TRUE; } uint32_t zdr_specdata4 (ZDR *zdrs, specdata4 *objp) { if (!zdr_uint32_t (zdrs, &objp->specdata1)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->specdata2)) return FALSE; return TRUE; } uint32_t zdr_fattr4_supported_attrs (ZDR *zdrs, fattr4_supported_attrs *objp) { if (!zdr_bitmap4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_type (ZDR *zdrs, fattr4_type *objp) { if (!zdr_nfs_ftype4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_fh_expire_type (ZDR *zdrs, fattr4_fh_expire_type *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_change (ZDR *zdrs, fattr4_change *objp) { if (!zdr_changeid4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_size (ZDR *zdrs, fattr4_size *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_link_support (ZDR *zdrs, fattr4_link_support *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_symlink_support (ZDR *zdrs, fattr4_symlink_support *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_named_attr (ZDR *zdrs, fattr4_named_attr *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_fsid (ZDR *zdrs, fattr4_fsid *objp) { if (!zdr_fsid4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_unique_handles (ZDR *zdrs, fattr4_unique_handles *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_lease_time (ZDR *zdrs, fattr4_lease_time *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_rdattr_error (ZDR *zdrs, fattr4_rdattr_error *objp) { if (!zdr_nfsstat4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_acl (ZDR *zdrs, fattr4_acl *objp) { if (!zdr_array (zdrs, (char **)&objp->fattr4_acl_val, (u_int *) &objp->fattr4_acl_len, ~0, sizeof (nfsace4), (zdrproc_t) zdr_nfsace4)) return FALSE; return TRUE; } uint32_t zdr_fattr4_aclsupport (ZDR *zdrs, fattr4_aclsupport *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_archive (ZDR *zdrs, fattr4_archive *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_cansettime (ZDR *zdrs, fattr4_cansettime *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_case_insensitive (ZDR *zdrs, fattr4_case_insensitive *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_case_preserving (ZDR *zdrs, fattr4_case_preserving *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_chown_restricted (ZDR *zdrs, fattr4_chown_restricted *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_fileid (ZDR *zdrs, fattr4_fileid *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_files_avail (ZDR *zdrs, fattr4_files_avail *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_filehandle (ZDR *zdrs, fattr4_filehandle *objp) { if (!zdr_nfs_fh4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_files_free (ZDR *zdrs, fattr4_files_free *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_files_total (ZDR *zdrs, fattr4_files_total *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_fs_locations (ZDR *zdrs, fattr4_fs_locations *objp) { if (!zdr_fs_locations4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_hidden (ZDR *zdrs, fattr4_hidden *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_homogeneous (ZDR *zdrs, fattr4_homogeneous *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_maxfilesize (ZDR *zdrs, fattr4_maxfilesize *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_maxlink (ZDR *zdrs, fattr4_maxlink *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_maxname (ZDR *zdrs, fattr4_maxname *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_maxread (ZDR *zdrs, fattr4_maxread *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_maxwrite (ZDR *zdrs, fattr4_maxwrite *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_mimetype (ZDR *zdrs, fattr4_mimetype *objp) { if (!zdr_utf8str_cs (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_mode (ZDR *zdrs, fattr4_mode *objp) { if (!zdr_mode4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_mounted_on_fileid (ZDR *zdrs, fattr4_mounted_on_fileid *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_no_trunc (ZDR *zdrs, fattr4_no_trunc *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_numlinks (ZDR *zdrs, fattr4_numlinks *objp) { if (!zdr_uint32_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_owner (ZDR *zdrs, fattr4_owner *objp) { if (!zdr_utf8str_mixed (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_owner_group (ZDR *zdrs, fattr4_owner_group *objp) { if (!zdr_utf8str_mixed (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_quota_avail_hard (ZDR *zdrs, fattr4_quota_avail_hard *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_quota_avail_soft (ZDR *zdrs, fattr4_quota_avail_soft *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_quota_used (ZDR *zdrs, fattr4_quota_used *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_rawdev (ZDR *zdrs, fattr4_rawdev *objp) { if (!zdr_specdata4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_space_avail (ZDR *zdrs, fattr4_space_avail *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_space_free (ZDR *zdrs, fattr4_space_free *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_space_total (ZDR *zdrs, fattr4_space_total *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_space_used (ZDR *zdrs, fattr4_space_used *objp) { if (!zdr_uint64_t (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_system (ZDR *zdrs, fattr4_system *objp) { if (!zdr_bool (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_time_access (ZDR *zdrs, fattr4_time_access *objp) { if (!zdr_nfstime4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_time_access_set (ZDR *zdrs, fattr4_time_access_set *objp) { if (!zdr_settime4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_time_backup (ZDR *zdrs, fattr4_time_backup *objp) { if (!zdr_nfstime4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_time_create (ZDR *zdrs, fattr4_time_create *objp) { if (!zdr_nfstime4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_time_delta (ZDR *zdrs, fattr4_time_delta *objp) { if (!zdr_nfstime4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_time_metadata (ZDR *zdrs, fattr4_time_metadata *objp) { if (!zdr_nfstime4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_time_modify (ZDR *zdrs, fattr4_time_modify *objp) { if (!zdr_nfstime4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_fattr4_time_modify_set (ZDR *zdrs, fattr4_time_modify_set *objp) { if (!zdr_settime4 (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_attrlist4 (ZDR *zdrs, attrlist4 *objp) { if (!zdr_bytes (zdrs, (char **)&objp->attrlist4_val, (u_int *) &objp->attrlist4_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_fattr4 (ZDR *zdrs, fattr4 *objp) { if (!zdr_bitmap4 (zdrs, &objp->attrmask)) return FALSE; if (!zdr_attrlist4 (zdrs, &objp->attr_vals)) return FALSE; return TRUE; } uint32_t zdr_change_info4 (ZDR *zdrs, change_info4 *objp) { if (!zdr_bool (zdrs, &objp->atomic)) return FALSE; if (!zdr_changeid4 (zdrs, &objp->before)) return FALSE; if (!zdr_changeid4 (zdrs, &objp->after)) return FALSE; return TRUE; } uint32_t zdr_clientaddr4 (ZDR *zdrs, clientaddr4 *objp) { if (!zdr_string (zdrs, &objp->r_netid, ~0)) return FALSE; if (!zdr_string (zdrs, &objp->r_addr, ~0)) return FALSE; return TRUE; } uint32_t zdr_cb_client4 (ZDR *zdrs, cb_client4 *objp) { if (!zdr_uint32_t (zdrs, &objp->cb_program)) return FALSE; if (!zdr_clientaddr4 (zdrs, &objp->cb_location)) return FALSE; return TRUE; } uint32_t zdr_stateid4 (ZDR *zdrs, stateid4 *objp) { if (!zdr_uint32_t (zdrs, &objp->seqid)) return FALSE; if (!zdr_opaque (zdrs, objp->other, 12)) return FALSE; return TRUE; } uint32_t zdr_nfs_client_id4 (ZDR *zdrs, nfs_client_id4 *objp) { if (!zdr_verifier4 (zdrs, objp->verifier)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->id.id_val, (u_int *) &objp->id.id_len, NFS4_OPAQUE_LIMIT)) return FALSE; return TRUE; } uint32_t zdr_open_owner4 (ZDR *zdrs, open_owner4 *objp) { if (!zdr_clientid4 (zdrs, &objp->clientid)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->owner.owner_val, (u_int *) &objp->owner.owner_len, NFS4_OPAQUE_LIMIT)) return FALSE; return TRUE; } uint32_t zdr_lock_owner4 (ZDR *zdrs, lock_owner4 *objp) { if (!zdr_clientid4 (zdrs, &objp->clientid)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->owner.owner_val, (u_int *) &objp->owner.owner_len, NFS4_OPAQUE_LIMIT)) return FALSE; return TRUE; } uint32_t zdr_nfs_lock_type4 (ZDR *zdrs, nfs_lock_type4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_ACCESS4args (ZDR *zdrs, ACCESS4args *objp) { if (!zdr_uint32_t (zdrs, &objp->access)) return FALSE; return TRUE; } uint32_t zdr_ACCESS4resok (ZDR *zdrs, ACCESS4resok *objp) { if (!zdr_uint32_t (zdrs, &objp->supported)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->access)) return FALSE; return TRUE; } uint32_t zdr_ACCESS4res (ZDR *zdrs, ACCESS4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_ACCESS4resok (zdrs, &objp->ACCESS4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_CLOSE4args (ZDR *zdrs, CLOSE4args *objp) { if (!zdr_seqid4 (zdrs, &objp->seqid)) return FALSE; if (!zdr_stateid4 (zdrs, &objp->open_stateid)) return FALSE; return TRUE; } uint32_t zdr_CLOSE4res (ZDR *zdrs, CLOSE4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_stateid4 (zdrs, &objp->CLOSE4res_u.open_stateid)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_COMMIT4args (ZDR *zdrs, COMMIT4args *objp) { if (!zdr_offset4 (zdrs, &objp->offset)) return FALSE; if (!zdr_count4 (zdrs, &objp->count)) return FALSE; return TRUE; } uint32_t zdr_COMMIT4resok (ZDR *zdrs, COMMIT4resok *objp) { if (!zdr_verifier4 (zdrs, objp->writeverf)) return FALSE; return TRUE; } uint32_t zdr_COMMIT4res (ZDR *zdrs, COMMIT4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_COMMIT4resok (zdrs, &objp->COMMIT4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_createtype4 (ZDR *zdrs, createtype4 *objp) { if (!zdr_nfs_ftype4 (zdrs, &objp->type)) return FALSE; switch (objp->type) { case NF4LNK: if (!zdr_linktext4 (zdrs, &objp->createtype4_u.linkdata)) return FALSE; break; case NF4BLK: case NF4CHR: if (!zdr_specdata4 (zdrs, &objp->createtype4_u.devdata)) return FALSE; break; case NF4SOCK: case NF4FIFO: case NF4DIR: break; default: break; } return TRUE; } uint32_t zdr_CREATE4args (ZDR *zdrs, CREATE4args *objp) { if (!zdr_createtype4 (zdrs, &objp->objtype)) return FALSE; if (!zdr_component4 (zdrs, &objp->objname)) return FALSE; if (!zdr_fattr4 (zdrs, &objp->createattrs)) return FALSE; return TRUE; } uint32_t zdr_CREATE4resok (ZDR *zdrs, CREATE4resok *objp) { if (!zdr_change_info4 (zdrs, &objp->cinfo)) return FALSE; if (!zdr_bitmap4 (zdrs, &objp->attrset)) return FALSE; return TRUE; } uint32_t zdr_CREATE4res (ZDR *zdrs, CREATE4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_CREATE4resok (zdrs, &objp->CREATE4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_DELEGPURGE4args (ZDR *zdrs, DELEGPURGE4args *objp) { if (!zdr_clientid4 (zdrs, &objp->clientid)) return FALSE; return TRUE; } uint32_t zdr_DELEGPURGE4res (ZDR *zdrs, DELEGPURGE4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_DELEGRETURN4args (ZDR *zdrs, DELEGRETURN4args *objp) { if (!zdr_stateid4 (zdrs, &objp->deleg_stateid)) return FALSE; return TRUE; } uint32_t zdr_DELEGRETURN4res (ZDR *zdrs, DELEGRETURN4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_GETATTR4args (ZDR *zdrs, GETATTR4args *objp) { if (!zdr_bitmap4 (zdrs, &objp->attr_request)) return FALSE; return TRUE; } uint32_t zdr_GETATTR4resok (ZDR *zdrs, GETATTR4resok *objp) { if (!zdr_fattr4 (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_GETATTR4res (ZDR *zdrs, GETATTR4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_GETATTR4resok (zdrs, &objp->GETATTR4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_GETFH4resok (ZDR *zdrs, GETFH4resok *objp) { if (!zdr_nfs_fh4 (zdrs, &objp->object)) return FALSE; return TRUE; } uint32_t zdr_GETFH4res (ZDR *zdrs, GETFH4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_GETFH4resok (zdrs, &objp->GETFH4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_LINK4args (ZDR *zdrs, LINK4args *objp) { if (!zdr_component4 (zdrs, &objp->newname)) return FALSE; return TRUE; } uint32_t zdr_LINK4resok (ZDR *zdrs, LINK4resok *objp) { if (!zdr_change_info4 (zdrs, &objp->cinfo)) return FALSE; return TRUE; } uint32_t zdr_LINK4res (ZDR *zdrs, LINK4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_LINK4resok (zdrs, &objp->LINK4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_open_to_lock_owner4 (ZDR *zdrs, open_to_lock_owner4 *objp) { if (!zdr_seqid4 (zdrs, &objp->open_seqid)) return FALSE; if (!zdr_stateid4 (zdrs, &objp->open_stateid)) return FALSE; if (!zdr_seqid4 (zdrs, &objp->lock_seqid)) return FALSE; if (!zdr_lock_owner4 (zdrs, &objp->lock_owner)) return FALSE; return TRUE; } uint32_t zdr_exist_lock_owner4 (ZDR *zdrs, exist_lock_owner4 *objp) { if (!zdr_stateid4 (zdrs, &objp->lock_stateid)) return FALSE; if (!zdr_seqid4 (zdrs, &objp->lock_seqid)) return FALSE; return TRUE; } uint32_t zdr_locker4 (ZDR *zdrs, locker4 *objp) { if (!zdr_bool (zdrs, &objp->new_lock_owner)) return FALSE; switch (objp->new_lock_owner) { case TRUE: if (!zdr_open_to_lock_owner4 (zdrs, &objp->locker4_u.open_owner)) return FALSE; break; case FALSE: if (!zdr_exist_lock_owner4 (zdrs, &objp->locker4_u.lock_owner)) return FALSE; break; default: return FALSE; } return TRUE; } uint32_t zdr_LOCK4args (ZDR *zdrs, LOCK4args *objp) { if (!zdr_nfs_lock_type4 (zdrs, &objp->locktype)) return FALSE; if (!zdr_bool (zdrs, &objp->reclaim)) return FALSE; if (!zdr_offset4 (zdrs, &objp->offset)) return FALSE; if (!zdr_length4 (zdrs, &objp->length)) return FALSE; if (!zdr_locker4 (zdrs, &objp->locker)) return FALSE; return TRUE; } uint32_t zdr_LOCK4denied (ZDR *zdrs, LOCK4denied *objp) { if (!zdr_offset4 (zdrs, &objp->offset)) return FALSE; if (!zdr_length4 (zdrs, &objp->length)) return FALSE; if (!zdr_nfs_lock_type4 (zdrs, &objp->locktype)) return FALSE; if (!zdr_lock_owner4 (zdrs, &objp->owner)) return FALSE; return TRUE; } uint32_t zdr_LOCK4resok (ZDR *zdrs, LOCK4resok *objp) { if (!zdr_stateid4 (zdrs, &objp->lock_stateid)) return FALSE; return TRUE; } uint32_t zdr_LOCK4res (ZDR *zdrs, LOCK4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_LOCK4resok (zdrs, &objp->LOCK4res_u.resok4)) return FALSE; break; case NFS4ERR_DENIED: if (!zdr_LOCK4denied (zdrs, &objp->LOCK4res_u.denied)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_LOCKT4args (ZDR *zdrs, LOCKT4args *objp) { if (!zdr_nfs_lock_type4 (zdrs, &objp->locktype)) return FALSE; if (!zdr_offset4 (zdrs, &objp->offset)) return FALSE; if (!zdr_length4 (zdrs, &objp->length)) return FALSE; if (!zdr_lock_owner4 (zdrs, &objp->owner)) return FALSE; return TRUE; } uint32_t zdr_LOCKT4res (ZDR *zdrs, LOCKT4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4ERR_DENIED: if (!zdr_LOCK4denied (zdrs, &objp->LOCKT4res_u.denied)) return FALSE; break; case NFS4_OK: break; default: break; } return TRUE; } uint32_t zdr_LOCKU4args (ZDR *zdrs, LOCKU4args *objp) { if (!zdr_nfs_lock_type4 (zdrs, &objp->locktype)) return FALSE; if (!zdr_seqid4 (zdrs, &objp->seqid)) return FALSE; if (!zdr_stateid4 (zdrs, &objp->lock_stateid)) return FALSE; if (!zdr_offset4 (zdrs, &objp->offset)) return FALSE; if (!zdr_length4 (zdrs, &objp->length)) return FALSE; return TRUE; } uint32_t zdr_LOCKU4res (ZDR *zdrs, LOCKU4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_stateid4 (zdrs, &objp->LOCKU4res_u.lock_stateid)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_LOOKUP4args (ZDR *zdrs, LOOKUP4args *objp) { if (!zdr_component4 (zdrs, &objp->objname)) return FALSE; return TRUE; } uint32_t zdr_LOOKUP4res (ZDR *zdrs, LOOKUP4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_LOOKUPP4res (ZDR *zdrs, LOOKUPP4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_NVERIFY4args (ZDR *zdrs, NVERIFY4args *objp) { if (!zdr_fattr4 (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_NVERIFY4res (ZDR *zdrs, NVERIFY4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_createmode4 (ZDR *zdrs, createmode4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_createhow4 (ZDR *zdrs, createhow4 *objp) { if (!zdr_createmode4 (zdrs, &objp->mode)) return FALSE; switch (objp->mode) { case UNCHECKED4: case GUARDED4: if (!zdr_fattr4 (zdrs, &objp->createhow4_u.createattrs)) return FALSE; break; case EXCLUSIVE4: if (!zdr_verifier4 (zdrs, objp->createhow4_u.createverf)) return FALSE; break; default: return FALSE; } return TRUE; } uint32_t zdr_opentype4 (ZDR *zdrs, opentype4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_openflag4 (ZDR *zdrs, openflag4 *objp) { if (!zdr_opentype4 (zdrs, &objp->opentype)) return FALSE; switch (objp->opentype) { case OPEN4_CREATE: if (!zdr_createhow4 (zdrs, &objp->openflag4_u.how)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_limit_by4 (ZDR *zdrs, limit_by4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_nfs_modified_limit4 (ZDR *zdrs, nfs_modified_limit4 *objp) { if (!zdr_uint32_t (zdrs, &objp->num_blocks)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->bytes_per_block)) return FALSE; return TRUE; } uint32_t zdr_nfs_space_limit4 (ZDR *zdrs, nfs_space_limit4 *objp) { if (!zdr_limit_by4 (zdrs, &objp->limitby)) return FALSE; switch (objp->limitby) { case NFS_LIMIT_SIZE: if (!zdr_uint64_t (zdrs, &objp->nfs_space_limit4_u.filesize)) return FALSE; break; case NFS_LIMIT_BLOCKS: if (!zdr_nfs_modified_limit4 (zdrs, &objp->nfs_space_limit4_u.mod_blocks)) return FALSE; break; default: return FALSE; } return TRUE; } uint32_t zdr_open_delegation_type4 (ZDR *zdrs, open_delegation_type4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_open_claim_type4 (ZDR *zdrs, open_claim_type4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_open_claim_delegate_cur4 (ZDR *zdrs, open_claim_delegate_cur4 *objp) { if (!zdr_stateid4 (zdrs, &objp->delegate_stateid)) return FALSE; if (!zdr_component4 (zdrs, &objp->file)) return FALSE; return TRUE; } uint32_t zdr_open_claim4 (ZDR *zdrs, open_claim4 *objp) { if (!zdr_open_claim_type4 (zdrs, &objp->claim)) return FALSE; switch (objp->claim) { case CLAIM_NULL: if (!zdr_component4 (zdrs, &objp->open_claim4_u.file)) return FALSE; break; case CLAIM_PREVIOUS: if (!zdr_open_delegation_type4 (zdrs, &objp->open_claim4_u.delegate_type)) return FALSE; break; case CLAIM_DELEGATE_CUR: if (!zdr_open_claim_delegate_cur4 (zdrs, &objp->open_claim4_u.delegate_cur_info)) return FALSE; break; case CLAIM_DELEGATE_PREV: if (!zdr_component4 (zdrs, &objp->open_claim4_u.file_delegate_prev)) return FALSE; break; default: return FALSE; } return TRUE; } uint32_t zdr_OPEN4args (ZDR *zdrs, OPEN4args *objp) { if (!zdr_seqid4 (zdrs, &objp->seqid)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->share_access)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->share_deny)) return FALSE; if (!zdr_open_owner4 (zdrs, &objp->owner)) return FALSE; if (!zdr_openflag4 (zdrs, &objp->openhow)) return FALSE; if (!zdr_open_claim4 (zdrs, &objp->claim)) return FALSE; return TRUE; } uint32_t zdr_open_read_delegation4 (ZDR *zdrs, open_read_delegation4 *objp) { if (!zdr_stateid4 (zdrs, &objp->stateid)) return FALSE; if (!zdr_bool (zdrs, &objp->recall)) return FALSE; if (!zdr_nfsace4 (zdrs, &objp->permissions)) return FALSE; return TRUE; } uint32_t zdr_open_write_delegation4 (ZDR *zdrs, open_write_delegation4 *objp) { if (!zdr_stateid4 (zdrs, &objp->stateid)) return FALSE; if (!zdr_bool (zdrs, &objp->recall)) return FALSE; if (!zdr_nfs_space_limit4 (zdrs, &objp->space_limit)) return FALSE; if (!zdr_nfsace4 (zdrs, &objp->permissions)) return FALSE; return TRUE; } uint32_t zdr_open_delegation4 (ZDR *zdrs, open_delegation4 *objp) { if (!zdr_open_delegation_type4 (zdrs, &objp->delegation_type)) return FALSE; switch (objp->delegation_type) { case OPEN_DELEGATE_NONE: break; case OPEN_DELEGATE_READ: if (!zdr_open_read_delegation4 (zdrs, &objp->open_delegation4_u.read)) return FALSE; break; case OPEN_DELEGATE_WRITE: if (!zdr_open_write_delegation4 (zdrs, &objp->open_delegation4_u.write)) return FALSE; break; default: return FALSE; } return TRUE; } uint32_t zdr_OPEN4resok (ZDR *zdrs, OPEN4resok *objp) { if (!zdr_stateid4 (zdrs, &objp->stateid)) return FALSE; if (!zdr_change_info4 (zdrs, &objp->cinfo)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->rflags)) return FALSE; if (!zdr_bitmap4 (zdrs, &objp->attrset)) return FALSE; if (!zdr_open_delegation4 (zdrs, &objp->delegation)) return FALSE; return TRUE; } uint32_t zdr_OPEN4res (ZDR *zdrs, OPEN4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_OPEN4resok (zdrs, &objp->OPEN4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_OPENATTR4args (ZDR *zdrs, OPENATTR4args *objp) { if (!zdr_bool (zdrs, &objp->createdir)) return FALSE; return TRUE; } uint32_t zdr_OPENATTR4res (ZDR *zdrs, OPENATTR4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_OPEN_CONFIRM4args (ZDR *zdrs, OPEN_CONFIRM4args *objp) { if (!zdr_stateid4 (zdrs, &objp->open_stateid)) return FALSE; if (!zdr_seqid4 (zdrs, &objp->seqid)) return FALSE; return TRUE; } uint32_t zdr_OPEN_CONFIRM4resok (ZDR *zdrs, OPEN_CONFIRM4resok *objp) { if (!zdr_stateid4 (zdrs, &objp->open_stateid)) return FALSE; return TRUE; } uint32_t zdr_OPEN_CONFIRM4res (ZDR *zdrs, OPEN_CONFIRM4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_OPEN_CONFIRM4resok (zdrs, &objp->OPEN_CONFIRM4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_OPEN_DOWNGRADE4args (ZDR *zdrs, OPEN_DOWNGRADE4args *objp) { if (!zdr_stateid4 (zdrs, &objp->open_stateid)) return FALSE; if (!zdr_seqid4 (zdrs, &objp->seqid)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->share_access)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->share_deny)) return FALSE; return TRUE; } uint32_t zdr_OPEN_DOWNGRADE4resok (ZDR *zdrs, OPEN_DOWNGRADE4resok *objp) { if (!zdr_stateid4 (zdrs, &objp->open_stateid)) return FALSE; return TRUE; } uint32_t zdr_OPEN_DOWNGRADE4res (ZDR *zdrs, OPEN_DOWNGRADE4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_OPEN_DOWNGRADE4resok (zdrs, &objp->OPEN_DOWNGRADE4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_PUTFH4args (ZDR *zdrs, PUTFH4args *objp) { if (!zdr_nfs_fh4 (zdrs, &objp->object)) return FALSE; return TRUE; } uint32_t zdr_PUTFH4res (ZDR *zdrs, PUTFH4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_PUTPUBFH4res (ZDR *zdrs, PUTPUBFH4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_PUTROOTFH4res (ZDR *zdrs, PUTROOTFH4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_READ4args (ZDR *zdrs, READ4args *objp) { if (!zdr_stateid4 (zdrs, &objp->stateid)) return FALSE; if (!zdr_offset4 (zdrs, &objp->offset)) return FALSE; if (!zdr_count4 (zdrs, &objp->count)) return FALSE; return TRUE; } uint32_t zdr_READ4resok (ZDR *zdrs, READ4resok *objp) { if (!zdr_bool (zdrs, &objp->eof)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_READ4res (ZDR *zdrs, READ4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_READ4resok (zdrs, &objp->READ4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_READDIR4args (ZDR *zdrs, READDIR4args *objp) { if (!zdr_nfs_cookie4 (zdrs, &objp->cookie)) return FALSE; if (!zdr_verifier4 (zdrs, objp->cookieverf)) return FALSE; if (!zdr_count4 (zdrs, &objp->dircount)) return FALSE; if (!zdr_count4 (zdrs, &objp->maxcount)) return FALSE; if (!zdr_bitmap4 (zdrs, &objp->attr_request)) return FALSE; return TRUE; } uint32_t zdr_entry4 (ZDR *zdrs, entry4 *objp) { if (!zdr_nfs_cookie4 (zdrs, &objp->cookie)) return FALSE; if (!zdr_component4 (zdrs, &objp->name)) return FALSE; if (!zdr_fattr4 (zdrs, &objp->attrs)) return FALSE; if (!zdr_pointer (zdrs, (char **)&objp->nextentry, sizeof (entry4), (zdrproc_t) zdr_entry4)) return FALSE; return TRUE; } uint32_t zdr_dirlist4 (ZDR *zdrs, dirlist4 *objp) { if (!zdr_pointer (zdrs, (char **)&objp->entries, sizeof (entry4), (zdrproc_t) zdr_entry4)) return FALSE; if (!zdr_bool (zdrs, &objp->eof)) return FALSE; return TRUE; } uint32_t zdr_READDIR4resok (ZDR *zdrs, READDIR4resok *objp) { if (!zdr_verifier4 (zdrs, objp->cookieverf)) return FALSE; if (!zdr_dirlist4 (zdrs, &objp->reply)) return FALSE; return TRUE; } uint32_t zdr_READDIR4res (ZDR *zdrs, READDIR4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_READDIR4resok (zdrs, &objp->READDIR4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_READLINK4resok (ZDR *zdrs, READLINK4resok *objp) { if (!zdr_linktext4 (zdrs, &objp->link)) return FALSE; return TRUE; } uint32_t zdr_READLINK4res (ZDR *zdrs, READLINK4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_READLINK4resok (zdrs, &objp->READLINK4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_REMOVE4args (ZDR *zdrs, REMOVE4args *objp) { if (!zdr_component4 (zdrs, &objp->target)) return FALSE; return TRUE; } uint32_t zdr_REMOVE4resok (ZDR *zdrs, REMOVE4resok *objp) { if (!zdr_change_info4 (zdrs, &objp->cinfo)) return FALSE; return TRUE; } uint32_t zdr_REMOVE4res (ZDR *zdrs, REMOVE4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_REMOVE4resok (zdrs, &objp->REMOVE4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_RENAME4args (ZDR *zdrs, RENAME4args *objp) { if (!zdr_component4 (zdrs, &objp->oldname)) return FALSE; if (!zdr_component4 (zdrs, &objp->newname)) return FALSE; return TRUE; } uint32_t zdr_RENAME4resok (ZDR *zdrs, RENAME4resok *objp) { if (!zdr_change_info4 (zdrs, &objp->source_cinfo)) return FALSE; if (!zdr_change_info4 (zdrs, &objp->target_cinfo)) return FALSE; return TRUE; } uint32_t zdr_RENAME4res (ZDR *zdrs, RENAME4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_RENAME4resok (zdrs, &objp->RENAME4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_RENEW4args (ZDR *zdrs, RENEW4args *objp) { if (!zdr_clientid4 (zdrs, &objp->clientid)) return FALSE; return TRUE; } uint32_t zdr_RENEW4res (ZDR *zdrs, RENEW4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_RESTOREFH4res (ZDR *zdrs, RESTOREFH4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_SAVEFH4res (ZDR *zdrs, SAVEFH4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_SETATTR4args (ZDR *zdrs, SETATTR4args *objp) { if (!zdr_stateid4 (zdrs, &objp->stateid)) return FALSE; if (!zdr_fattr4 (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_SETATTR4res (ZDR *zdrs, SETATTR4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; if (!zdr_bitmap4 (zdrs, &objp->attrsset)) return FALSE; return TRUE; } uint32_t zdr_SETCLIENTID4args (ZDR *zdrs, SETCLIENTID4args *objp) { if (!zdr_nfs_client_id4 (zdrs, &objp->client)) return FALSE; if (!zdr_cb_client4 (zdrs, &objp->callback)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->callback_ident)) return FALSE; return TRUE; } uint32_t zdr_SETCLIENTID4resok (ZDR *zdrs, SETCLIENTID4resok *objp) { if (!zdr_clientid4 (zdrs, &objp->clientid)) return FALSE; if (!zdr_verifier4 (zdrs, objp->setclientid_confirm)) return FALSE; return TRUE; } uint32_t zdr_SETCLIENTID4res (ZDR *zdrs, SETCLIENTID4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_SETCLIENTID4resok (zdrs, &objp->SETCLIENTID4res_u.resok4)) return FALSE; break; case NFS4ERR_CLID_INUSE: if (!zdr_clientaddr4 (zdrs, &objp->SETCLIENTID4res_u.client_using)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_SETCLIENTID_CONFIRM4args (ZDR *zdrs, SETCLIENTID_CONFIRM4args *objp) { if (!zdr_clientid4 (zdrs, &objp->clientid)) return FALSE; if (!zdr_verifier4 (zdrs, objp->setclientid_confirm)) return FALSE; return TRUE; } uint32_t zdr_SETCLIENTID_CONFIRM4res (ZDR *zdrs, SETCLIENTID_CONFIRM4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_VERIFY4args (ZDR *zdrs, VERIFY4args *objp) { if (!zdr_fattr4 (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_VERIFY4res (ZDR *zdrs, VERIFY4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_stable_how4 (ZDR *zdrs, stable_how4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_WRITE4args (ZDR *zdrs, WRITE4args *objp) { if (!zdr_stateid4 (zdrs, &objp->stateid)) return FALSE; if (!zdr_offset4 (zdrs, &objp->offset)) return FALSE; if (!zdr_stable_how4 (zdrs, &objp->stable)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_WRITE4resok (ZDR *zdrs, WRITE4resok *objp) { if (!zdr_count4 (zdrs, &objp->count)) return FALSE; if (!zdr_stable_how4 (zdrs, &objp->committed)) return FALSE; if (!zdr_verifier4 (zdrs, objp->writeverf)) return FALSE; return TRUE; } uint32_t zdr_WRITE4res (ZDR *zdrs, WRITE4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_WRITE4resok (zdrs, &objp->WRITE4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_RELEASE_LOCKOWNER4args (ZDR *zdrs, RELEASE_LOCKOWNER4args *objp) { if (!zdr_lock_owner4 (zdrs, &objp->lock_owner)) return FALSE; return TRUE; } uint32_t zdr_RELEASE_LOCKOWNER4res (ZDR *zdrs, RELEASE_LOCKOWNER4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_ILLEGAL4res (ZDR *zdrs, ILLEGAL4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_nfs_opnum4 (ZDR *zdrs, nfs_opnum4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_nfs_argop4 (ZDR *zdrs, nfs_argop4 *objp) { if (!zdr_nfs_opnum4 (zdrs, &objp->argop)) return FALSE; switch (objp->argop) { case OP_ACCESS: if (!zdr_ACCESS4args (zdrs, &objp->nfs_argop4_u.opaccess)) return FALSE; break; case OP_CLOSE: if (!zdr_CLOSE4args (zdrs, &objp->nfs_argop4_u.opclose)) return FALSE; break; case OP_COMMIT: if (!zdr_COMMIT4args (zdrs, &objp->nfs_argop4_u.opcommit)) return FALSE; break; case OP_CREATE: if (!zdr_CREATE4args (zdrs, &objp->nfs_argop4_u.opcreate)) return FALSE; break; case OP_DELEGPURGE: if (!zdr_DELEGPURGE4args (zdrs, &objp->nfs_argop4_u.opdelegpurge)) return FALSE; break; case OP_DELEGRETURN: if (!zdr_DELEGRETURN4args (zdrs, &objp->nfs_argop4_u.opdelegreturn)) return FALSE; break; case OP_GETATTR: if (!zdr_GETATTR4args (zdrs, &objp->nfs_argop4_u.opgetattr)) return FALSE; break; case OP_GETFH: break; case OP_LINK: if (!zdr_LINK4args (zdrs, &objp->nfs_argop4_u.oplink)) return FALSE; break; case OP_LOCK: if (!zdr_LOCK4args (zdrs, &objp->nfs_argop4_u.oplock)) return FALSE; break; case OP_LOCKT: if (!zdr_LOCKT4args (zdrs, &objp->nfs_argop4_u.oplockt)) return FALSE; break; case OP_LOCKU: if (!zdr_LOCKU4args (zdrs, &objp->nfs_argop4_u.oplocku)) return FALSE; break; case OP_LOOKUP: if (!zdr_LOOKUP4args (zdrs, &objp->nfs_argop4_u.oplookup)) return FALSE; break; case OP_LOOKUPP: break; case OP_NVERIFY: if (!zdr_NVERIFY4args (zdrs, &objp->nfs_argop4_u.opnverify)) return FALSE; break; case OP_OPEN: if (!zdr_OPEN4args (zdrs, &objp->nfs_argop4_u.opopen)) return FALSE; break; case OP_OPENATTR: if (!zdr_OPENATTR4args (zdrs, &objp->nfs_argop4_u.opopenattr)) return FALSE; break; case OP_OPEN_CONFIRM: if (!zdr_OPEN_CONFIRM4args (zdrs, &objp->nfs_argop4_u.opopen_confirm)) return FALSE; break; case OP_OPEN_DOWNGRADE: if (!zdr_OPEN_DOWNGRADE4args (zdrs, &objp->nfs_argop4_u.opopen_downgrade)) return FALSE; break; case OP_PUTFH: if (!zdr_PUTFH4args (zdrs, &objp->nfs_argop4_u.opputfh)) return FALSE; break; case OP_PUTPUBFH: break; case OP_PUTROOTFH: break; case OP_READ: if (!zdr_READ4args (zdrs, &objp->nfs_argop4_u.opread)) return FALSE; break; case OP_READDIR: if (!zdr_READDIR4args (zdrs, &objp->nfs_argop4_u.opreaddir)) return FALSE; break; case OP_READLINK: break; case OP_REMOVE: if (!zdr_REMOVE4args (zdrs, &objp->nfs_argop4_u.opremove)) return FALSE; break; case OP_RENAME: if (!zdr_RENAME4args (zdrs, &objp->nfs_argop4_u.oprename)) return FALSE; break; case OP_RENEW: if (!zdr_RENEW4args (zdrs, &objp->nfs_argop4_u.oprenew)) return FALSE; break; case OP_RESTOREFH: break; case OP_SAVEFH: break; case OP_SETATTR: if (!zdr_SETATTR4args (zdrs, &objp->nfs_argop4_u.opsetattr)) return FALSE; break; case OP_SETCLIENTID: if (!zdr_SETCLIENTID4args (zdrs, &objp->nfs_argop4_u.opsetclientid)) return FALSE; break; case OP_SETCLIENTID_CONFIRM: if (!zdr_SETCLIENTID_CONFIRM4args (zdrs, &objp->nfs_argop4_u.opsetclientid_confirm)) return FALSE; break; case OP_VERIFY: if (!zdr_VERIFY4args (zdrs, &objp->nfs_argop4_u.opverify)) return FALSE; break; case OP_WRITE: if (!zdr_WRITE4args (zdrs, &objp->nfs_argop4_u.opwrite)) return FALSE; break; case OP_RELEASE_LOCKOWNER: if (!zdr_RELEASE_LOCKOWNER4args (zdrs, &objp->nfs_argop4_u.oprelease_lockowner)) return FALSE; break; case OP_ILLEGAL: break; default: return FALSE; } return TRUE; } uint32_t zdr_nfs_resop4 (ZDR *zdrs, nfs_resop4 *objp) { if (!zdr_nfs_opnum4 (zdrs, &objp->resop)) return FALSE; switch (objp->resop) { case OP_ACCESS: if (!zdr_ACCESS4res (zdrs, &objp->nfs_resop4_u.opaccess)) return FALSE; break; case OP_CLOSE: if (!zdr_CLOSE4res (zdrs, &objp->nfs_resop4_u.opclose)) return FALSE; break; case OP_COMMIT: if (!zdr_COMMIT4res (zdrs, &objp->nfs_resop4_u.opcommit)) return FALSE; break; case OP_CREATE: if (!zdr_CREATE4res (zdrs, &objp->nfs_resop4_u.opcreate)) return FALSE; break; case OP_DELEGPURGE: if (!zdr_DELEGPURGE4res (zdrs, &objp->nfs_resop4_u.opdelegpurge)) return FALSE; break; case OP_DELEGRETURN: if (!zdr_DELEGRETURN4res (zdrs, &objp->nfs_resop4_u.opdelegreturn)) return FALSE; break; case OP_GETATTR: if (!zdr_GETATTR4res (zdrs, &objp->nfs_resop4_u.opgetattr)) return FALSE; break; case OP_GETFH: if (!zdr_GETFH4res (zdrs, &objp->nfs_resop4_u.opgetfh)) return FALSE; break; case OP_LINK: if (!zdr_LINK4res (zdrs, &objp->nfs_resop4_u.oplink)) return FALSE; break; case OP_LOCK: if (!zdr_LOCK4res (zdrs, &objp->nfs_resop4_u.oplock)) return FALSE; break; case OP_LOCKT: if (!zdr_LOCKT4res (zdrs, &objp->nfs_resop4_u.oplockt)) return FALSE; break; case OP_LOCKU: if (!zdr_LOCKU4res (zdrs, &objp->nfs_resop4_u.oplocku)) return FALSE; break; case OP_LOOKUP: if (!zdr_LOOKUP4res (zdrs, &objp->nfs_resop4_u.oplookup)) return FALSE; break; case OP_LOOKUPP: if (!zdr_LOOKUPP4res (zdrs, &objp->nfs_resop4_u.oplookupp)) return FALSE; break; case OP_NVERIFY: if (!zdr_NVERIFY4res (zdrs, &objp->nfs_resop4_u.opnverify)) return FALSE; break; case OP_OPEN: if (!zdr_OPEN4res (zdrs, &objp->nfs_resop4_u.opopen)) return FALSE; break; case OP_OPENATTR: if (!zdr_OPENATTR4res (zdrs, &objp->nfs_resop4_u.opopenattr)) return FALSE; break; case OP_OPEN_CONFIRM: if (!zdr_OPEN_CONFIRM4res (zdrs, &objp->nfs_resop4_u.opopen_confirm)) return FALSE; break; case OP_OPEN_DOWNGRADE: if (!zdr_OPEN_DOWNGRADE4res (zdrs, &objp->nfs_resop4_u.opopen_downgrade)) return FALSE; break; case OP_PUTFH: if (!zdr_PUTFH4res (zdrs, &objp->nfs_resop4_u.opputfh)) return FALSE; break; case OP_PUTPUBFH: if (!zdr_PUTPUBFH4res (zdrs, &objp->nfs_resop4_u.opputpubfh)) return FALSE; break; case OP_PUTROOTFH: if (!zdr_PUTROOTFH4res (zdrs, &objp->nfs_resop4_u.opputrootfh)) return FALSE; break; case OP_READ: if (!zdr_READ4res (zdrs, &objp->nfs_resop4_u.opread)) return FALSE; break; case OP_READDIR: if (!zdr_READDIR4res (zdrs, &objp->nfs_resop4_u.opreaddir)) return FALSE; break; case OP_READLINK: if (!zdr_READLINK4res (zdrs, &objp->nfs_resop4_u.opreadlink)) return FALSE; break; case OP_REMOVE: if (!zdr_REMOVE4res (zdrs, &objp->nfs_resop4_u.opremove)) return FALSE; break; case OP_RENAME: if (!zdr_RENAME4res (zdrs, &objp->nfs_resop4_u.oprename)) return FALSE; break; case OP_RENEW: if (!zdr_RENEW4res (zdrs, &objp->nfs_resop4_u.oprenew)) return FALSE; break; case OP_RESTOREFH: if (!zdr_RESTOREFH4res (zdrs, &objp->nfs_resop4_u.oprestorefh)) return FALSE; break; case OP_SAVEFH: if (!zdr_SAVEFH4res (zdrs, &objp->nfs_resop4_u.opsavefh)) return FALSE; break; case OP_SETATTR: if (!zdr_SETATTR4res (zdrs, &objp->nfs_resop4_u.opsetattr)) return FALSE; break; case OP_SETCLIENTID: if (!zdr_SETCLIENTID4res (zdrs, &objp->nfs_resop4_u.opsetclientid)) return FALSE; break; case OP_SETCLIENTID_CONFIRM: if (!zdr_SETCLIENTID_CONFIRM4res (zdrs, &objp->nfs_resop4_u.opsetclientid_confirm)) return FALSE; break; case OP_VERIFY: if (!zdr_VERIFY4res (zdrs, &objp->nfs_resop4_u.opverify)) return FALSE; break; case OP_WRITE: if (!zdr_WRITE4res (zdrs, &objp->nfs_resop4_u.opwrite)) return FALSE; break; case OP_RELEASE_LOCKOWNER: if (!zdr_RELEASE_LOCKOWNER4res (zdrs, &objp->nfs_resop4_u.oprelease_lockowner)) return FALSE; break; case OP_ILLEGAL: if (!zdr_ILLEGAL4res (zdrs, &objp->nfs_resop4_u.opillegal)) return FALSE; break; default: return FALSE; } return TRUE; } uint32_t zdr_COMPOUND4args (ZDR *zdrs, COMPOUND4args *objp) { if (!zdr_utf8str_cs (zdrs, &objp->tag)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->minorversion)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->argarray.argarray_val, (u_int *) &objp->argarray.argarray_len, ~0, sizeof (nfs_argop4), (zdrproc_t) zdr_nfs_argop4)) return FALSE; return TRUE; } uint32_t zdr_COMPOUND4res (ZDR *zdrs, COMPOUND4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; if (!zdr_utf8str_cs (zdrs, &objp->tag)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->resarray.resarray_val, (u_int *) &objp->resarray.resarray_len, ~0, sizeof (nfs_resop4), (zdrproc_t) zdr_nfs_resop4)) return FALSE; return TRUE; } uint32_t zdr_CB_GETATTR4args (ZDR *zdrs, CB_GETATTR4args *objp) { if (!zdr_nfs_fh4 (zdrs, &objp->fh)) return FALSE; if (!zdr_bitmap4 (zdrs, &objp->attr_request)) return FALSE; return TRUE; } uint32_t zdr_CB_GETATTR4resok (ZDR *zdrs, CB_GETATTR4resok *objp) { if (!zdr_fattr4 (zdrs, &objp->obj_attributes)) return FALSE; return TRUE; } uint32_t zdr_CB_GETATTR4res (ZDR *zdrs, CB_GETATTR4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!zdr_CB_GETATTR4resok (zdrs, &objp->CB_GETATTR4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_CB_RECALL4args (ZDR *zdrs, CB_RECALL4args *objp) { if (!zdr_stateid4 (zdrs, &objp->stateid)) return FALSE; if (!zdr_bool (zdrs, &objp->truncate)) return FALSE; if (!zdr_nfs_fh4 (zdrs, &objp->fh)) return FALSE; return TRUE; } uint32_t zdr_CB_RECALL4res (ZDR *zdrs, CB_RECALL4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_CB_ILLEGAL4res (ZDR *zdrs, CB_ILLEGAL4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_nfs_cb_opnum4 (ZDR *zdrs, nfs_cb_opnum4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_nfs_cb_argop4 (ZDR *zdrs, nfs_cb_argop4 *objp) { if (!zdr_u_int (zdrs, &objp->argop)) return FALSE; switch (objp->argop) { case OP_CB_GETATTR: if (!zdr_CB_GETATTR4args (zdrs, &objp->nfs_cb_argop4_u.opcbgetattr)) return FALSE; break; case OP_CB_RECALL: if (!zdr_CB_RECALL4args (zdrs, &objp->nfs_cb_argop4_u.opcbrecall)) return FALSE; break; case OP_CB_ILLEGAL: break; default: return FALSE; } return TRUE; } uint32_t zdr_nfs_cb_resop4 (ZDR *zdrs, nfs_cb_resop4 *objp) { if (!zdr_u_int (zdrs, &objp->resop)) return FALSE; switch (objp->resop) { case OP_CB_GETATTR: if (!zdr_CB_GETATTR4res (zdrs, &objp->nfs_cb_resop4_u.opcbgetattr)) return FALSE; break; case OP_CB_RECALL: if (!zdr_CB_RECALL4res (zdrs, &objp->nfs_cb_resop4_u.opcbrecall)) return FALSE; break; case OP_CB_ILLEGAL: if (!zdr_CB_ILLEGAL4res (zdrs, &objp->nfs_cb_resop4_u.opcbillegal)) return FALSE; break; default: return FALSE; } return TRUE; } uint32_t zdr_CB_COMPOUND4args (ZDR *zdrs, CB_COMPOUND4args *objp) { if (!zdr_utf8str_cs (zdrs, &objp->tag)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->minorversion)) return FALSE; if (!zdr_uint32_t (zdrs, &objp->callback_ident)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->argarray.argarray_val, (u_int *) &objp->argarray.argarray_len, ~0, sizeof (nfs_cb_argop4), (zdrproc_t) zdr_nfs_cb_argop4)) return FALSE; return TRUE; } uint32_t zdr_CB_COMPOUND4res (ZDR *zdrs, CB_COMPOUND4res *objp) { if (!zdr_nfsstat4 (zdrs, &objp->status)) return FALSE; if (!zdr_utf8str_cs (zdrs, &objp->tag)) return FALSE; if (!zdr_array (zdrs, (char **)&objp->resarray.resarray_val, (u_int *) &objp->resarray.resarray_len, ~0, sizeof (nfs_cb_resop4), (zdrproc_t) zdr_nfs_cb_resop4)) return FALSE; return TRUE; } libnfs-libnfs-4.0.0/nfs4/libnfs-raw-nfs4.h000066400000000000000000001511121343063627400202130ustar00rootroot00000000000000/* This is based on RFC3530 which contains the following copyright statement: Copyright (C) The Internet Society (2003). All Rights Reserved. This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English. The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns. This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _NFS4_H_RPCGEN #define _NFS4_H_RPCGEN #include #ifdef __cplusplus extern "C" { #endif #define NFS4_FHSIZE 128 #define NFS4_VERIFIER_SIZE 8 #define NFS4_OPAQUE_LIMIT 1024 enum nfs_ftype4 { NF4REG = 1, NF4DIR = 2, NF4BLK = 3, NF4CHR = 4, NF4LNK = 5, NF4SOCK = 6, NF4FIFO = 7, NF4ATTRDIR = 8, NF4NAMEDATTR = 9, }; typedef enum nfs_ftype4 nfs_ftype4; enum nfsstat4 { NFS4_OK = 0, NFS4ERR_PERM = 1, NFS4ERR_NOENT = 2, NFS4ERR_IO = 5, NFS4ERR_NXIO = 6, NFS4ERR_ACCESS = 13, NFS4ERR_EXIST = 17, NFS4ERR_XDEV = 18, NFS4ERR_NOTDIR = 20, NFS4ERR_ISDIR = 21, NFS4ERR_INVAL = 22, NFS4ERR_FBIG = 27, NFS4ERR_NOSPC = 28, NFS4ERR_ROFS = 30, NFS4ERR_MLINK = 31, NFS4ERR_NAMETOOLONG = 63, NFS4ERR_NOTEMPTY = 66, NFS4ERR_DQUOT = 69, NFS4ERR_STALE = 70, NFS4ERR_BADHANDLE = 10001, NFS4ERR_BAD_COOKIE = 10003, NFS4ERR_NOTSUPP = 10004, NFS4ERR_TOOSMALL = 10005, NFS4ERR_SERVERFAULT = 10006, NFS4ERR_BADTYPE = 10007, NFS4ERR_DELAY = 10008, NFS4ERR_SAME = 10009, NFS4ERR_DENIED = 10010, NFS4ERR_EXPIRED = 10011, NFS4ERR_LOCKED = 10012, NFS4ERR_GRACE = 10013, NFS4ERR_FHEXPIRED = 10014, NFS4ERR_SHARE_DENIED = 10015, NFS4ERR_WRONGSEC = 10016, NFS4ERR_CLID_INUSE = 10017, NFS4ERR_RESOURCE = 10018, NFS4ERR_MOVED = 10019, NFS4ERR_NOFILEHANDLE = 10020, NFS4ERR_MINOR_VERS_MISMATCH = 10021, NFS4ERR_STALE_CLIENTID = 10022, NFS4ERR_STALE_STATEID = 10023, NFS4ERR_OLD_STATEID = 10024, NFS4ERR_BAD_STATEID = 10025, NFS4ERR_BAD_SEQID = 10026, NFS4ERR_NOT_SAME = 10027, NFS4ERR_LOCK_RANGE = 10028, NFS4ERR_SYMLINK = 10029, NFS4ERR_RESTOREFH = 10030, NFS4ERR_LEASE_MOVED = 10031, NFS4ERR_ATTRNOTSUPP = 10032, NFS4ERR_NO_GRACE = 10033, NFS4ERR_RECLAIM_BAD = 10034, NFS4ERR_RECLAIM_CONFLICT = 10035, NFS4ERR_BADZDR = 10036, NFS4ERR_LOCKS_HELD = 10037, NFS4ERR_OPENMODE = 10038, NFS4ERR_BADOWNER = 10039, NFS4ERR_BADCHAR = 10040, NFS4ERR_BADNAME = 10041, NFS4ERR_BAD_RANGE = 10042, NFS4ERR_LOCK_NOTSUPP = 10043, NFS4ERR_OP_ILLEGAL = 10044, NFS4ERR_DEADLOCK = 10045, NFS4ERR_FILE_OPEN = 10046, NFS4ERR_ADMIN_REVOKED = 10047, NFS4ERR_CB_PATH_DOWN = 10048, }; typedef enum nfsstat4 nfsstat4; typedef struct { u_int bitmap4_len; uint32_t *bitmap4_val; } bitmap4; typedef uint64_t offset4; typedef uint32_t count4; typedef uint64_t length4; typedef uint64_t clientid4; typedef uint32_t seqid4; typedef struct { u_int utf8string_len; char *utf8string_val; } utf8string; typedef utf8string utf8str_cis; typedef utf8string utf8str_cs; typedef utf8string utf8str_mixed; typedef utf8str_cs component4; typedef struct { u_int pathname4_len; component4 *pathname4_val; } pathname4; typedef uint64_t nfs_lockid4; typedef uint64_t nfs_cookie4; typedef utf8str_cs linktext4; typedef struct { u_int sec_oid4_len; char *sec_oid4_val; } sec_oid4; typedef uint32_t qop4; typedef uint32_t mode4; typedef uint64_t changeid4; typedef char verifier4[NFS4_VERIFIER_SIZE]; struct nfstime4 { int64_t seconds; uint32_t nseconds; }; typedef struct nfstime4 nfstime4; enum time_how4 { SET_TO_SERVER_TIME4 = 0, SET_TO_CLIENT_TIME4 = 1, }; typedef enum time_how4 time_how4; struct settime4 { time_how4 set_it; union { nfstime4 time; } settime4_u; }; typedef struct settime4 settime4; typedef struct { u_int nfs_fh4_len; char *nfs_fh4_val; } nfs_fh4; struct fsid4 { uint64_t major; uint64_t minor; }; typedef struct fsid4 fsid4; struct fs_location4 { struct { u_int server_len; utf8str_cis *server_val; } server; pathname4 rootpath; }; typedef struct fs_location4 fs_location4; struct fs_locations4 { pathname4 fs_root; struct { u_int locations_len; fs_location4 *locations_val; } locations; }; typedef struct fs_locations4 fs_locations4; #define ACL4_SUPPORT_ALLOW_ACL 0x00000001 #define ACL4_SUPPORT_DENY_ACL 0x00000002 #define ACL4_SUPPORT_AUDIT_ACL 0x00000004 #define ACL4_SUPPORT_ALARM_ACL 0x00000008 typedef uint32_t acetype4; #define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000 #define ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001 #define ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002 #define ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003 typedef uint32_t aceflag4; #define ACE4_FILE_INHERIT_ACE 0x00000001 #define ACE4_DIRECTORY_INHERIT_ACE 0x00000002 #define ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004 #define ACE4_INHERIT_ONLY_ACE 0x00000008 #define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010 #define ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020 #define ACE4_IDENTIFIER_GROUP 0x00000040 typedef uint32_t acemask4; #define ACE4_READ_DATA 0x00000001 #define ACE4_LIST_DIRECTORY 0x00000001 #define ACE4_WRITE_DATA 0x00000002 #define ACE4_ADD_FILE 0x00000002 #define ACE4_APPEND_DATA 0x00000004 #define ACE4_ADD_SUBDIRECTORY 0x00000004 #define ACE4_READ_NAMED_ATTRS 0x00000008 #define ACE4_WRITE_NAMED_ATTRS 0x00000010 #define ACE4_EXECUTE 0x00000020 #define ACE4_DELETE_CHILD 0x00000040 #define ACE4_READ_ATTRIBUTES 0x00000080 #define ACE4_WRITE_ATTRIBUTES 0x00000100 #define ACE4_DELETE 0x00010000 #define ACE4_READ_ACL 0x00020000 #define ACE4_WRITE_ACL 0x00040000 #define ACE4_WRITE_OWNER 0x00080000 #define ACE4_SYNCHRONIZE 0x00100000 #define ACE4_GENERIC_READ 0x00120081 #define ACE4_GENERIC_WRITE 0x00160106 #define ACE4_GENERIC_EXECUTE 0x001200A0 struct nfsace4 { acetype4 type; aceflag4 flag; acemask4 access_mask; utf8str_mixed who; }; typedef struct nfsace4 nfsace4; #define MODE4_SUID 0x800 #define MODE4_SGID 0x400 #define MODE4_SVTX 0x200 #define MODE4_RUSR 0x100 #define MODE4_WUSR 0x080 #define MODE4_XUSR 0x040 #define MODE4_RGRP 0x020 #define MODE4_WGRP 0x010 #define MODE4_XGRP 0x008 #define MODE4_ROTH 0x004 #define MODE4_WOTH 0x002 #define MODE4_XOTH 0x001 struct specdata4 { uint32_t specdata1; uint32_t specdata2; }; typedef struct specdata4 specdata4; #define FH4_PERSISTENT 0x00000000 #define FH4_NOEXPIRE_WITH_OPEN 0x00000001 #define FH4_VOLATILE_ANY 0x00000002 #define FH4_VOL_MIGRATION 0x00000004 #define FH4_VOL_RENAME 0x00000008 typedef bitmap4 fattr4_supported_attrs; typedef nfs_ftype4 fattr4_type; typedef uint32_t fattr4_fh_expire_type; typedef changeid4 fattr4_change; typedef uint64_t fattr4_size; typedef uint32_t fattr4_link_support; typedef uint32_t fattr4_symlink_support; typedef uint32_t fattr4_named_attr; typedef fsid4 fattr4_fsid; typedef uint32_t fattr4_unique_handles; typedef uint32_t fattr4_lease_time; typedef nfsstat4 fattr4_rdattr_error; typedef struct { u_int fattr4_acl_len; nfsace4 *fattr4_acl_val; } fattr4_acl; typedef uint32_t fattr4_aclsupport; typedef uint32_t fattr4_archive; typedef uint32_t fattr4_cansettime; typedef uint32_t fattr4_case_insensitive; typedef uint32_t fattr4_case_preserving; typedef uint32_t fattr4_chown_restricted; typedef uint64_t fattr4_fileid; typedef uint64_t fattr4_files_avail; typedef nfs_fh4 fattr4_filehandle; typedef uint64_t fattr4_files_free; typedef uint64_t fattr4_files_total; typedef fs_locations4 fattr4_fs_locations; typedef uint32_t fattr4_hidden; typedef uint32_t fattr4_homogeneous; typedef uint64_t fattr4_maxfilesize; typedef uint32_t fattr4_maxlink; typedef uint32_t fattr4_maxname; typedef uint64_t fattr4_maxread; typedef uint64_t fattr4_maxwrite; typedef utf8str_cs fattr4_mimetype; typedef mode4 fattr4_mode; typedef uint64_t fattr4_mounted_on_fileid; typedef uint32_t fattr4_no_trunc; typedef uint32_t fattr4_numlinks; typedef utf8str_mixed fattr4_owner; typedef utf8str_mixed fattr4_owner_group; typedef uint64_t fattr4_quota_avail_hard; typedef uint64_t fattr4_quota_avail_soft; typedef uint64_t fattr4_quota_used; typedef specdata4 fattr4_rawdev; typedef uint64_t fattr4_space_avail; typedef uint64_t fattr4_space_free; typedef uint64_t fattr4_space_total; typedef uint64_t fattr4_space_used; typedef uint32_t fattr4_system; typedef nfstime4 fattr4_time_access; typedef settime4 fattr4_time_access_set; typedef nfstime4 fattr4_time_backup; typedef nfstime4 fattr4_time_create; typedef nfstime4 fattr4_time_delta; typedef nfstime4 fattr4_time_metadata; typedef nfstime4 fattr4_time_modify; typedef settime4 fattr4_time_modify_set; #define FATTR4_SUPPORTED_ATTRS 0 #define FATTR4_TYPE 1 #define FATTR4_FH_EXPIRE_TYPE 2 #define FATTR4_CHANGE 3 #define FATTR4_SIZE 4 #define FATTR4_LINK_SUPPORT 5 #define FATTR4_SYMLINK_SUPPORT 6 #define FATTR4_NAMED_ATTR 7 #define FATTR4_FSID 8 #define FATTR4_UNIQUE_HANDLES 9 #define FATTR4_LEASE_TIME 10 #define FATTR4_RDATTR_ERROR 11 #define FATTR4_FILEHANDLE 19 #define FATTR4_ACL 12 #define FATTR4_ACLSUPPORT 13 #define FATTR4_ARCHIVE 14 #define FATTR4_CANSETTIME 15 #define FATTR4_CASE_INSENSITIVE 16 #define FATTR4_CASE_PRESERVING 17 #define FATTR4_CHOWN_RESTRICTED 18 #define FATTR4_FILEID 20 #define FATTR4_FILES_AVAIL 21 #define FATTR4_FILES_FREE 22 #define FATTR4_FILES_TOTAL 23 #define FATTR4_FS_LOCATIONS 24 #define FATTR4_HIDDEN 25 #define FATTR4_HOMOGENEOUS 26 #define FATTR4_MAXFILESIZE 27 #define FATTR4_MAXLINK 28 #define FATTR4_MAXNAME 29 #define FATTR4_MAXREAD 30 #define FATTR4_MAXWRITE 31 #define FATTR4_MIMETYPE 32 #define FATTR4_MODE 33 #define FATTR4_NO_TRUNC 34 #define FATTR4_NUMLINKS 35 #define FATTR4_OWNER 36 #define FATTR4_OWNER_GROUP 37 #define FATTR4_QUOTA_AVAIL_HARD 38 #define FATTR4_QUOTA_AVAIL_SOFT 39 #define FATTR4_QUOTA_USED 40 #define FATTR4_RAWDEV 41 #define FATTR4_SPACE_AVAIL 42 #define FATTR4_SPACE_FREE 43 #define FATTR4_SPACE_TOTAL 44 #define FATTR4_SPACE_USED 45 #define FATTR4_SYSTEM 46 #define FATTR4_TIME_ACCESS 47 #define FATTR4_TIME_ACCESS_SET 48 #define FATTR4_TIME_BACKUP 49 #define FATTR4_TIME_CREATE 50 #define FATTR4_TIME_DELTA 51 #define FATTR4_TIME_METADATA 52 #define FATTR4_TIME_MODIFY 53 #define FATTR4_TIME_MODIFY_SET 54 #define FATTR4_MOUNTED_ON_FILEID 55 typedef struct { u_int attrlist4_len; char *attrlist4_val; } attrlist4; struct fattr4 { bitmap4 attrmask; attrlist4 attr_vals; }; typedef struct fattr4 fattr4; struct change_info4 { uint32_t atomic; changeid4 before; changeid4 after; }; typedef struct change_info4 change_info4; struct clientaddr4 { char *r_netid; char *r_addr; }; typedef struct clientaddr4 clientaddr4; struct cb_client4 { uint32_t cb_program; clientaddr4 cb_location; }; typedef struct cb_client4 cb_client4; struct stateid4 { uint32_t seqid; char other[12]; }; typedef struct stateid4 stateid4; struct nfs_client_id4 { verifier4 verifier; struct { u_int id_len; char *id_val; } id; }; typedef struct nfs_client_id4 nfs_client_id4; struct open_owner4 { clientid4 clientid; struct { u_int owner_len; char *owner_val; } owner; }; typedef struct open_owner4 open_owner4; struct lock_owner4 { clientid4 clientid; struct { u_int owner_len; char *owner_val; } owner; }; typedef struct lock_owner4 lock_owner4; enum nfs_lock_type4 { READ_LT = 1, WRITE_LT = 2, READW_LT = 3, WRITEW_LT = 4, }; typedef enum nfs_lock_type4 nfs_lock_type4; #define ACCESS4_READ 0x00000001 #define ACCESS4_LOOKUP 0x00000002 #define ACCESS4_MODIFY 0x00000004 #define ACCESS4_EXTEND 0x00000008 #define ACCESS4_DELETE 0x00000010 #define ACCESS4_EXECUTE 0x00000020 struct ACCESS4args { uint32_t access; }; typedef struct ACCESS4args ACCESS4args; struct ACCESS4resok { uint32_t supported; uint32_t access; }; typedef struct ACCESS4resok ACCESS4resok; struct ACCESS4res { nfsstat4 status; union { ACCESS4resok resok4; } ACCESS4res_u; }; typedef struct ACCESS4res ACCESS4res; struct CLOSE4args { seqid4 seqid; stateid4 open_stateid; }; typedef struct CLOSE4args CLOSE4args; struct CLOSE4res { nfsstat4 status; union { stateid4 open_stateid; } CLOSE4res_u; }; typedef struct CLOSE4res CLOSE4res; struct COMMIT4args { offset4 offset; count4 count; }; typedef struct COMMIT4args COMMIT4args; struct COMMIT4resok { verifier4 writeverf; }; typedef struct COMMIT4resok COMMIT4resok; struct COMMIT4res { nfsstat4 status; union { COMMIT4resok resok4; } COMMIT4res_u; }; typedef struct COMMIT4res COMMIT4res; struct createtype4 { nfs_ftype4 type; union { linktext4 linkdata; specdata4 devdata; } createtype4_u; }; typedef struct createtype4 createtype4; struct CREATE4args { createtype4 objtype; component4 objname; fattr4 createattrs; }; typedef struct CREATE4args CREATE4args; struct CREATE4resok { change_info4 cinfo; bitmap4 attrset; }; typedef struct CREATE4resok CREATE4resok; struct CREATE4res { nfsstat4 status; union { CREATE4resok resok4; } CREATE4res_u; }; typedef struct CREATE4res CREATE4res; struct DELEGPURGE4args { clientid4 clientid; }; typedef struct DELEGPURGE4args DELEGPURGE4args; struct DELEGPURGE4res { nfsstat4 status; }; typedef struct DELEGPURGE4res DELEGPURGE4res; struct DELEGRETURN4args { stateid4 deleg_stateid; }; typedef struct DELEGRETURN4args DELEGRETURN4args; struct DELEGRETURN4res { nfsstat4 status; }; typedef struct DELEGRETURN4res DELEGRETURN4res; struct GETATTR4args { bitmap4 attr_request; }; typedef struct GETATTR4args GETATTR4args; struct GETATTR4resok { fattr4 obj_attributes; }; typedef struct GETATTR4resok GETATTR4resok; struct GETATTR4res { nfsstat4 status; union { GETATTR4resok resok4; } GETATTR4res_u; }; typedef struct GETATTR4res GETATTR4res; struct GETFH4resok { nfs_fh4 object; }; typedef struct GETFH4resok GETFH4resok; struct GETFH4res { nfsstat4 status; union { GETFH4resok resok4; } GETFH4res_u; }; typedef struct GETFH4res GETFH4res; struct LINK4args { component4 newname; }; typedef struct LINK4args LINK4args; struct LINK4resok { change_info4 cinfo; }; typedef struct LINK4resok LINK4resok; struct LINK4res { nfsstat4 status; union { LINK4resok resok4; } LINK4res_u; }; typedef struct LINK4res LINK4res; struct open_to_lock_owner4 { seqid4 open_seqid; stateid4 open_stateid; seqid4 lock_seqid; lock_owner4 lock_owner; }; typedef struct open_to_lock_owner4 open_to_lock_owner4; struct exist_lock_owner4 { stateid4 lock_stateid; seqid4 lock_seqid; }; typedef struct exist_lock_owner4 exist_lock_owner4; struct locker4 { uint32_t new_lock_owner; union { open_to_lock_owner4 open_owner; exist_lock_owner4 lock_owner; } locker4_u; }; typedef struct locker4 locker4; struct LOCK4args { nfs_lock_type4 locktype; uint32_t reclaim; offset4 offset; length4 length; locker4 locker; }; typedef struct LOCK4args LOCK4args; struct LOCK4denied { offset4 offset; length4 length; nfs_lock_type4 locktype; lock_owner4 owner; }; typedef struct LOCK4denied LOCK4denied; struct LOCK4resok { stateid4 lock_stateid; }; typedef struct LOCK4resok LOCK4resok; struct LOCK4res { nfsstat4 status; union { LOCK4resok resok4; LOCK4denied denied; } LOCK4res_u; }; typedef struct LOCK4res LOCK4res; struct LOCKT4args { nfs_lock_type4 locktype; offset4 offset; length4 length; lock_owner4 owner; }; typedef struct LOCKT4args LOCKT4args; struct LOCKT4res { nfsstat4 status; union { LOCK4denied denied; } LOCKT4res_u; }; typedef struct LOCKT4res LOCKT4res; struct LOCKU4args { nfs_lock_type4 locktype; seqid4 seqid; stateid4 lock_stateid; offset4 offset; length4 length; }; typedef struct LOCKU4args LOCKU4args; struct LOCKU4res { nfsstat4 status; union { stateid4 lock_stateid; } LOCKU4res_u; }; typedef struct LOCKU4res LOCKU4res; struct LOOKUP4args { component4 objname; }; typedef struct LOOKUP4args LOOKUP4args; struct LOOKUP4res { nfsstat4 status; }; typedef struct LOOKUP4res LOOKUP4res; struct LOOKUPP4res { nfsstat4 status; }; typedef struct LOOKUPP4res LOOKUPP4res; struct NVERIFY4args { fattr4 obj_attributes; }; typedef struct NVERIFY4args NVERIFY4args; struct NVERIFY4res { nfsstat4 status; }; typedef struct NVERIFY4res NVERIFY4res; enum createmode4 { UNCHECKED4 = 0, GUARDED4 = 1, EXCLUSIVE4 = 2, }; typedef enum createmode4 createmode4; struct createhow4 { createmode4 mode; union { fattr4 createattrs; verifier4 createverf; } createhow4_u; }; typedef struct createhow4 createhow4; enum opentype4 { OPEN4_NOCREATE = 0, OPEN4_CREATE = 1, }; typedef enum opentype4 opentype4; struct openflag4 { opentype4 opentype; union { createhow4 how; } openflag4_u; }; typedef struct openflag4 openflag4; enum limit_by4 { NFS_LIMIT_SIZE = 1, NFS_LIMIT_BLOCKS = 2, }; typedef enum limit_by4 limit_by4; struct nfs_modified_limit4 { uint32_t num_blocks; uint32_t bytes_per_block; }; typedef struct nfs_modified_limit4 nfs_modified_limit4; struct nfs_space_limit4 { limit_by4 limitby; union { uint64_t filesize; nfs_modified_limit4 mod_blocks; } nfs_space_limit4_u; }; typedef struct nfs_space_limit4 nfs_space_limit4; #define OPEN4_SHARE_ACCESS_READ 0x00000001 #define OPEN4_SHARE_ACCESS_WRITE 0x00000002 #define OPEN4_SHARE_ACCESS_BOTH 0x00000003 #define OPEN4_SHARE_DENY_NONE 0x00000000 #define OPEN4_SHARE_DENY_READ 0x00000001 #define OPEN4_SHARE_DENY_WRITE 0x00000002 #define OPEN4_SHARE_DENY_BOTH 0x00000003 enum open_delegation_type4 { OPEN_DELEGATE_NONE = 0, OPEN_DELEGATE_READ = 1, OPEN_DELEGATE_WRITE = 2, }; typedef enum open_delegation_type4 open_delegation_type4; enum open_claim_type4 { CLAIM_NULL = 0, CLAIM_PREVIOUS = 1, CLAIM_DELEGATE_CUR = 2, CLAIM_DELEGATE_PREV = 3, }; typedef enum open_claim_type4 open_claim_type4; struct open_claim_delegate_cur4 { stateid4 delegate_stateid; component4 file; }; typedef struct open_claim_delegate_cur4 open_claim_delegate_cur4; struct open_claim4 { open_claim_type4 claim; union { component4 file; open_delegation_type4 delegate_type; open_claim_delegate_cur4 delegate_cur_info; component4 file_delegate_prev; } open_claim4_u; }; typedef struct open_claim4 open_claim4; struct OPEN4args { seqid4 seqid; uint32_t share_access; uint32_t share_deny; open_owner4 owner; openflag4 openhow; open_claim4 claim; }; typedef struct OPEN4args OPEN4args; struct open_read_delegation4 { stateid4 stateid; uint32_t recall; nfsace4 permissions; }; typedef struct open_read_delegation4 open_read_delegation4; struct open_write_delegation4 { stateid4 stateid; uint32_t recall; nfs_space_limit4 space_limit; nfsace4 permissions; }; typedef struct open_write_delegation4 open_write_delegation4; struct open_delegation4 { open_delegation_type4 delegation_type; union { open_read_delegation4 read; open_write_delegation4 write; } open_delegation4_u; }; typedef struct open_delegation4 open_delegation4; #define OPEN4_RESULT_CONFIRM 0x00000002 #define OPEN4_RESULT_LOCKTYPE_POSIX 0x00000004 struct OPEN4resok { stateid4 stateid; change_info4 cinfo; uint32_t rflags; bitmap4 attrset; open_delegation4 delegation; }; typedef struct OPEN4resok OPEN4resok; struct OPEN4res { nfsstat4 status; union { OPEN4resok resok4; } OPEN4res_u; }; typedef struct OPEN4res OPEN4res; struct OPENATTR4args { uint32_t createdir; }; typedef struct OPENATTR4args OPENATTR4args; struct OPENATTR4res { nfsstat4 status; }; typedef struct OPENATTR4res OPENATTR4res; struct OPEN_CONFIRM4args { stateid4 open_stateid; seqid4 seqid; }; typedef struct OPEN_CONFIRM4args OPEN_CONFIRM4args; struct OPEN_CONFIRM4resok { stateid4 open_stateid; }; typedef struct OPEN_CONFIRM4resok OPEN_CONFIRM4resok; struct OPEN_CONFIRM4res { nfsstat4 status; union { OPEN_CONFIRM4resok resok4; } OPEN_CONFIRM4res_u; }; typedef struct OPEN_CONFIRM4res OPEN_CONFIRM4res; struct OPEN_DOWNGRADE4args { stateid4 open_stateid; seqid4 seqid; uint32_t share_access; uint32_t share_deny; }; typedef struct OPEN_DOWNGRADE4args OPEN_DOWNGRADE4args; struct OPEN_DOWNGRADE4resok { stateid4 open_stateid; }; typedef struct OPEN_DOWNGRADE4resok OPEN_DOWNGRADE4resok; struct OPEN_DOWNGRADE4res { nfsstat4 status; union { OPEN_DOWNGRADE4resok resok4; } OPEN_DOWNGRADE4res_u; }; typedef struct OPEN_DOWNGRADE4res OPEN_DOWNGRADE4res; struct PUTFH4args { nfs_fh4 object; }; typedef struct PUTFH4args PUTFH4args; struct PUTFH4res { nfsstat4 status; }; typedef struct PUTFH4res PUTFH4res; struct PUTPUBFH4res { nfsstat4 status; }; typedef struct PUTPUBFH4res PUTPUBFH4res; struct PUTROOTFH4res { nfsstat4 status; }; typedef struct PUTROOTFH4res PUTROOTFH4res; struct READ4args { stateid4 stateid; offset4 offset; count4 count; }; typedef struct READ4args READ4args; struct READ4resok { uint32_t eof; struct { u_int data_len; char *data_val; } data; }; typedef struct READ4resok READ4resok; struct READ4res { nfsstat4 status; union { READ4resok resok4; } READ4res_u; }; typedef struct READ4res READ4res; struct READDIR4args { nfs_cookie4 cookie; verifier4 cookieverf; count4 dircount; count4 maxcount; bitmap4 attr_request; }; typedef struct READDIR4args READDIR4args; struct entry4 { nfs_cookie4 cookie; component4 name; fattr4 attrs; struct entry4 *nextentry; }; typedef struct entry4 entry4; struct dirlist4 { entry4 *entries; uint32_t eof; }; typedef struct dirlist4 dirlist4; struct READDIR4resok { verifier4 cookieverf; dirlist4 reply; }; typedef struct READDIR4resok READDIR4resok; struct READDIR4res { nfsstat4 status; union { READDIR4resok resok4; } READDIR4res_u; }; typedef struct READDIR4res READDIR4res; struct READLINK4resok { linktext4 link; }; typedef struct READLINK4resok READLINK4resok; struct READLINK4res { nfsstat4 status; union { READLINK4resok resok4; } READLINK4res_u; }; typedef struct READLINK4res READLINK4res; struct REMOVE4args { component4 target; }; typedef struct REMOVE4args REMOVE4args; struct REMOVE4resok { change_info4 cinfo; }; typedef struct REMOVE4resok REMOVE4resok; struct REMOVE4res { nfsstat4 status; union { REMOVE4resok resok4; } REMOVE4res_u; }; typedef struct REMOVE4res REMOVE4res; struct RENAME4args { component4 oldname; component4 newname; }; typedef struct RENAME4args RENAME4args; struct RENAME4resok { change_info4 source_cinfo; change_info4 target_cinfo; }; typedef struct RENAME4resok RENAME4resok; struct RENAME4res { nfsstat4 status; union { RENAME4resok resok4; } RENAME4res_u; }; typedef struct RENAME4res RENAME4res; struct RENEW4args { clientid4 clientid; }; typedef struct RENEW4args RENEW4args; struct RENEW4res { nfsstat4 status; }; typedef struct RENEW4res RENEW4res; struct RESTOREFH4res { nfsstat4 status; }; typedef struct RESTOREFH4res RESTOREFH4res; struct SAVEFH4res { nfsstat4 status; }; typedef struct SAVEFH4res SAVEFH4res; struct SETATTR4args { stateid4 stateid; fattr4 obj_attributes; }; typedef struct SETATTR4args SETATTR4args; struct SETATTR4res { nfsstat4 status; bitmap4 attrsset; }; typedef struct SETATTR4res SETATTR4res; struct SETCLIENTID4args { nfs_client_id4 client; cb_client4 callback; uint32_t callback_ident; }; typedef struct SETCLIENTID4args SETCLIENTID4args; struct SETCLIENTID4resok { clientid4 clientid; verifier4 setclientid_confirm; }; typedef struct SETCLIENTID4resok SETCLIENTID4resok; struct SETCLIENTID4res { nfsstat4 status; union { SETCLIENTID4resok resok4; clientaddr4 client_using; } SETCLIENTID4res_u; }; typedef struct SETCLIENTID4res SETCLIENTID4res; struct SETCLIENTID_CONFIRM4args { clientid4 clientid; verifier4 setclientid_confirm; }; typedef struct SETCLIENTID_CONFIRM4args SETCLIENTID_CONFIRM4args; struct SETCLIENTID_CONFIRM4res { nfsstat4 status; }; typedef struct SETCLIENTID_CONFIRM4res SETCLIENTID_CONFIRM4res; struct VERIFY4args { fattr4 obj_attributes; }; typedef struct VERIFY4args VERIFY4args; struct VERIFY4res { nfsstat4 status; }; typedef struct VERIFY4res VERIFY4res; enum stable_how4 { UNSTABLE4 = 0, DATA_SYNC4 = 1, FILE_SYNC4 = 2, }; typedef enum stable_how4 stable_how4; struct WRITE4args { stateid4 stateid; offset4 offset; stable_how4 stable; struct { u_int data_len; char *data_val; } data; }; typedef struct WRITE4args WRITE4args; struct WRITE4resok { count4 count; stable_how4 committed; verifier4 writeverf; }; typedef struct WRITE4resok WRITE4resok; struct WRITE4res { nfsstat4 status; union { WRITE4resok resok4; } WRITE4res_u; }; typedef struct WRITE4res WRITE4res; struct RELEASE_LOCKOWNER4args { lock_owner4 lock_owner; }; typedef struct RELEASE_LOCKOWNER4args RELEASE_LOCKOWNER4args; struct RELEASE_LOCKOWNER4res { nfsstat4 status; }; typedef struct RELEASE_LOCKOWNER4res RELEASE_LOCKOWNER4res; struct ILLEGAL4res { nfsstat4 status; }; typedef struct ILLEGAL4res ILLEGAL4res; enum nfs_opnum4 { OP_ACCESS = 3, OP_CLOSE = 4, OP_COMMIT = 5, OP_CREATE = 6, OP_DELEGPURGE = 7, OP_DELEGRETURN = 8, OP_GETATTR = 9, OP_GETFH = 10, OP_LINK = 11, OP_LOCK = 12, OP_LOCKT = 13, OP_LOCKU = 14, OP_LOOKUP = 15, OP_LOOKUPP = 16, OP_NVERIFY = 17, OP_OPEN = 18, OP_OPENATTR = 19, OP_OPEN_CONFIRM = 20, OP_OPEN_DOWNGRADE = 21, OP_PUTFH = 22, OP_PUTPUBFH = 23, OP_PUTROOTFH = 24, OP_READ = 25, OP_READDIR = 26, OP_READLINK = 27, OP_REMOVE = 28, OP_RENAME = 29, OP_RENEW = 30, OP_RESTOREFH = 31, OP_SAVEFH = 32, OP_SECINFO = 33, OP_SETATTR = 34, OP_SETCLIENTID = 35, OP_SETCLIENTID_CONFIRM = 36, OP_VERIFY = 37, OP_WRITE = 38, OP_RELEASE_LOCKOWNER = 39, OP_ILLEGAL = 10044, }; typedef enum nfs_opnum4 nfs_opnum4; struct nfs_argop4 { nfs_opnum4 argop; union { ACCESS4args opaccess; CLOSE4args opclose; COMMIT4args opcommit; CREATE4args opcreate; DELEGPURGE4args opdelegpurge; DELEGRETURN4args opdelegreturn; GETATTR4args opgetattr; LINK4args oplink; LOCK4args oplock; LOCKT4args oplockt; LOCKU4args oplocku; LOOKUP4args oplookup; NVERIFY4args opnverify; OPEN4args opopen; OPENATTR4args opopenattr; OPEN_CONFIRM4args opopen_confirm; OPEN_DOWNGRADE4args opopen_downgrade; PUTFH4args opputfh; READ4args opread; READDIR4args opreaddir; REMOVE4args opremove; RENAME4args oprename; RENEW4args oprenew; SETATTR4args opsetattr; SETCLIENTID4args opsetclientid; SETCLIENTID_CONFIRM4args opsetclientid_confirm; VERIFY4args opverify; WRITE4args opwrite; RELEASE_LOCKOWNER4args oprelease_lockowner; } nfs_argop4_u; }; typedef struct nfs_argop4 nfs_argop4; struct nfs_resop4 { nfs_opnum4 resop; union { ACCESS4res opaccess; CLOSE4res opclose; COMMIT4res opcommit; CREATE4res opcreate; DELEGPURGE4res opdelegpurge; DELEGRETURN4res opdelegreturn; GETATTR4res opgetattr; GETFH4res opgetfh; LINK4res oplink; LOCK4res oplock; LOCKT4res oplockt; LOCKU4res oplocku; LOOKUP4res oplookup; LOOKUPP4res oplookupp; NVERIFY4res opnverify; OPEN4res opopen; OPENATTR4res opopenattr; OPEN_CONFIRM4res opopen_confirm; OPEN_DOWNGRADE4res opopen_downgrade; PUTFH4res opputfh; PUTPUBFH4res opputpubfh; PUTROOTFH4res opputrootfh; READ4res opread; READDIR4res opreaddir; READLINK4res opreadlink; REMOVE4res opremove; RENAME4res oprename; RENEW4res oprenew; RESTOREFH4res oprestorefh; SAVEFH4res opsavefh; SETATTR4res opsetattr; SETCLIENTID4res opsetclientid; SETCLIENTID_CONFIRM4res opsetclientid_confirm; VERIFY4res opverify; WRITE4res opwrite; RELEASE_LOCKOWNER4res oprelease_lockowner; ILLEGAL4res opillegal; } nfs_resop4_u; }; typedef struct nfs_resop4 nfs_resop4; struct COMPOUND4args { utf8str_cs tag; uint32_t minorversion; struct { u_int argarray_len; nfs_argop4 *argarray_val; } argarray; }; typedef struct COMPOUND4args COMPOUND4args; struct COMPOUND4res { nfsstat4 status; utf8str_cs tag; struct { u_int resarray_len; nfs_resop4 *resarray_val; } resarray; }; typedef struct COMPOUND4res COMPOUND4res; struct CB_GETATTR4args { nfs_fh4 fh; bitmap4 attr_request; }; typedef struct CB_GETATTR4args CB_GETATTR4args; struct CB_GETATTR4resok { fattr4 obj_attributes; }; typedef struct CB_GETATTR4resok CB_GETATTR4resok; struct CB_GETATTR4res { nfsstat4 status; union { CB_GETATTR4resok resok4; } CB_GETATTR4res_u; }; typedef struct CB_GETATTR4res CB_GETATTR4res; struct CB_RECALL4args { stateid4 stateid; uint32_t truncate; nfs_fh4 fh; }; typedef struct CB_RECALL4args CB_RECALL4args; struct CB_RECALL4res { nfsstat4 status; }; typedef struct CB_RECALL4res CB_RECALL4res; struct CB_ILLEGAL4res { nfsstat4 status; }; typedef struct CB_ILLEGAL4res CB_ILLEGAL4res; enum nfs_cb_opnum4 { OP_CB_GETATTR = 3, OP_CB_RECALL = 4, OP_CB_ILLEGAL = 10044, }; typedef enum nfs_cb_opnum4 nfs_cb_opnum4; struct nfs_cb_argop4 { u_int argop; union { CB_GETATTR4args opcbgetattr; CB_RECALL4args opcbrecall; } nfs_cb_argop4_u; }; typedef struct nfs_cb_argop4 nfs_cb_argop4; struct nfs_cb_resop4 { u_int resop; union { CB_GETATTR4res opcbgetattr; CB_RECALL4res opcbrecall; CB_ILLEGAL4res opcbillegal; } nfs_cb_resop4_u; }; typedef struct nfs_cb_resop4 nfs_cb_resop4; struct CB_COMPOUND4args { utf8str_cs tag; uint32_t minorversion; uint32_t callback_ident; struct { u_int argarray_len; nfs_cb_argop4 *argarray_val; } argarray; }; typedef struct CB_COMPOUND4args CB_COMPOUND4args; struct CB_COMPOUND4res { nfsstat4 status; utf8str_cs tag; struct { u_int resarray_len; nfs_cb_resop4 *resarray_val; } resarray; }; typedef struct CB_COMPOUND4res CB_COMPOUND4res; #define NFS4_PROGRAM 100003 #define NFS_V4 4 #if defined(__STDC__) || defined(__cplusplus) #define NFSPROC4_NULL 0 extern void * nfsproc4_null_4(void *, void *); extern void * nfsproc4_null_4_svc(void *, struct svc_req *); #define NFSPROC4_COMPOUND 1 extern COMPOUND4res * nfsproc4_compound_4(COMPOUND4args *, void *); extern COMPOUND4res * nfsproc4_compound_4_svc(COMPOUND4args *, struct svc_req *); extern int nfs4_program_4_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define NFSPROC4_NULL 0 extern void * nfsproc4_null_4(); extern void * nfsproc4_null_4_svc(); #define NFSPROC4_COMPOUND 1 extern COMPOUND4res * nfsproc4_compound_4(); extern COMPOUND4res * nfsproc4_compound_4_svc(); extern int nfs4_program_4_freeresult (); #endif /* K&R C */ #define NFS4_CALLBACK 0x40000000 #define NFS_CB 1 #if defined(__STDC__) || defined(__cplusplus) #define CB_NULL 0 extern void * cb_null_1(void *, void *); extern void * cb_null_1_svc(void *, struct svc_req *); #define CB_COMPOUND 1 extern CB_COMPOUND4res * cb_compound_1(CB_COMPOUND4args *, void *); extern CB_COMPOUND4res * cb_compound_1_svc(CB_COMPOUND4args *, struct svc_req *); extern int nfs4_callback_1_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define CB_NULL 0 extern void * cb_null_1(); extern void * cb_null_1_svc(); #define CB_COMPOUND 1 extern CB_COMPOUND4res * cb_compound_1(); extern CB_COMPOUND4res * cb_compound_1_svc(); extern int nfs4_callback_1_freeresult (); #endif /* K&R C */ /* the zdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern uint32_t zdr_nfs_ftype4 (ZDR *, nfs_ftype4*); extern uint32_t zdr_nfsstat4 (ZDR *, nfsstat4*); extern uint32_t zdr_bitmap4 (ZDR *, bitmap4*); extern uint32_t zdr_offset4 (ZDR *, offset4*); extern uint32_t zdr_count4 (ZDR *, count4*); extern uint32_t zdr_length4 (ZDR *, length4*); extern uint32_t zdr_clientid4 (ZDR *, clientid4*); extern uint32_t zdr_seqid4 (ZDR *, seqid4*); extern uint32_t zdr_utf8string (ZDR *, utf8string*); extern uint32_t zdr_utf8str_cis (ZDR *, utf8str_cis*); extern uint32_t zdr_utf8str_cs (ZDR *, utf8str_cs*); extern uint32_t zdr_utf8str_mixed (ZDR *, utf8str_mixed*); extern uint32_t zdr_component4 (ZDR *, component4*); extern uint32_t zdr_pathname4 (ZDR *, pathname4*); extern uint32_t zdr_nfs_lockid4 (ZDR *, nfs_lockid4*); extern uint32_t zdr_nfs_cookie4 (ZDR *, nfs_cookie4*); extern uint32_t zdr_linktext4 (ZDR *, linktext4*); extern uint32_t zdr_sec_oid4 (ZDR *, sec_oid4*); extern uint32_t zdr_qop4 (ZDR *, qop4*); extern uint32_t zdr_mode4 (ZDR *, mode4*); extern uint32_t zdr_changeid4 (ZDR *, changeid4*); extern uint32_t zdr_verifier4 (ZDR *, verifier4); extern uint32_t zdr_nfstime4 (ZDR *, nfstime4*); extern uint32_t zdr_time_how4 (ZDR *, time_how4*); extern uint32_t zdr_settime4 (ZDR *, settime4*); extern uint32_t zdr_nfs_fh4 (ZDR *, nfs_fh4*); extern uint32_t zdr_fsid4 (ZDR *, fsid4*); extern uint32_t zdr_fs_location4 (ZDR *, fs_location4*); extern uint32_t zdr_fs_locations4 (ZDR *, fs_locations4*); extern uint32_t zdr_acetype4 (ZDR *, acetype4*); extern uint32_t zdr_aceflag4 (ZDR *, aceflag4*); extern uint32_t zdr_acemask4 (ZDR *, acemask4*); extern uint32_t zdr_nfsace4 (ZDR *, nfsace4*); extern uint32_t zdr_specdata4 (ZDR *, specdata4*); extern uint32_t zdr_fattr4_supported_attrs (ZDR *, fattr4_supported_attrs*); extern uint32_t zdr_fattr4_type (ZDR *, fattr4_type*); extern uint32_t zdr_fattr4_fh_expire_type (ZDR *, fattr4_fh_expire_type*); extern uint32_t zdr_fattr4_change (ZDR *, fattr4_change*); extern uint32_t zdr_fattr4_size (ZDR *, fattr4_size*); extern uint32_t zdr_fattr4_link_support (ZDR *, fattr4_link_support*); extern uint32_t zdr_fattr4_symlink_support (ZDR *, fattr4_symlink_support*); extern uint32_t zdr_fattr4_named_attr (ZDR *, fattr4_named_attr*); extern uint32_t zdr_fattr4_fsid (ZDR *, fattr4_fsid*); extern uint32_t zdr_fattr4_unique_handles (ZDR *, fattr4_unique_handles*); extern uint32_t zdr_fattr4_lease_time (ZDR *, fattr4_lease_time*); extern uint32_t zdr_fattr4_rdattr_error (ZDR *, fattr4_rdattr_error*); extern uint32_t zdr_fattr4_acl (ZDR *, fattr4_acl*); extern uint32_t zdr_fattr4_aclsupport (ZDR *, fattr4_aclsupport*); extern uint32_t zdr_fattr4_archive (ZDR *, fattr4_archive*); extern uint32_t zdr_fattr4_cansettime (ZDR *, fattr4_cansettime*); extern uint32_t zdr_fattr4_case_insensitive (ZDR *, fattr4_case_insensitive*); extern uint32_t zdr_fattr4_case_preserving (ZDR *, fattr4_case_preserving*); extern uint32_t zdr_fattr4_chown_restricted (ZDR *, fattr4_chown_restricted*); extern uint32_t zdr_fattr4_fileid (ZDR *, fattr4_fileid*); extern uint32_t zdr_fattr4_files_avail (ZDR *, fattr4_files_avail*); extern uint32_t zdr_fattr4_filehandle (ZDR *, fattr4_filehandle*); extern uint32_t zdr_fattr4_files_free (ZDR *, fattr4_files_free*); extern uint32_t zdr_fattr4_files_total (ZDR *, fattr4_files_total*); extern uint32_t zdr_fattr4_fs_locations (ZDR *, fattr4_fs_locations*); extern uint32_t zdr_fattr4_hidden (ZDR *, fattr4_hidden*); extern uint32_t zdr_fattr4_homogeneous (ZDR *, fattr4_homogeneous*); extern uint32_t zdr_fattr4_maxfilesize (ZDR *, fattr4_maxfilesize*); extern uint32_t zdr_fattr4_maxlink (ZDR *, fattr4_maxlink*); extern uint32_t zdr_fattr4_maxname (ZDR *, fattr4_maxname*); extern uint32_t zdr_fattr4_maxread (ZDR *, fattr4_maxread*); extern uint32_t zdr_fattr4_maxwrite (ZDR *, fattr4_maxwrite*); extern uint32_t zdr_fattr4_mimetype (ZDR *, fattr4_mimetype*); extern uint32_t zdr_fattr4_mode (ZDR *, fattr4_mode*); extern uint32_t zdr_fattr4_mounted_on_fileid (ZDR *, fattr4_mounted_on_fileid*); extern uint32_t zdr_fattr4_no_trunc (ZDR *, fattr4_no_trunc*); extern uint32_t zdr_fattr4_numlinks (ZDR *, fattr4_numlinks*); extern uint32_t zdr_fattr4_owner (ZDR *, fattr4_owner*); extern uint32_t zdr_fattr4_owner_group (ZDR *, fattr4_owner_group*); extern uint32_t zdr_fattr4_quota_avail_hard (ZDR *, fattr4_quota_avail_hard*); extern uint32_t zdr_fattr4_quota_avail_soft (ZDR *, fattr4_quota_avail_soft*); extern uint32_t zdr_fattr4_quota_used (ZDR *, fattr4_quota_used*); extern uint32_t zdr_fattr4_rawdev (ZDR *, fattr4_rawdev*); extern uint32_t zdr_fattr4_space_avail (ZDR *, fattr4_space_avail*); extern uint32_t zdr_fattr4_space_free (ZDR *, fattr4_space_free*); extern uint32_t zdr_fattr4_space_total (ZDR *, fattr4_space_total*); extern uint32_t zdr_fattr4_space_used (ZDR *, fattr4_space_used*); extern uint32_t zdr_fattr4_system (ZDR *, fattr4_system*); extern uint32_t zdr_fattr4_time_access (ZDR *, fattr4_time_access*); extern uint32_t zdr_fattr4_time_access_set (ZDR *, fattr4_time_access_set*); extern uint32_t zdr_fattr4_time_backup (ZDR *, fattr4_time_backup*); extern uint32_t zdr_fattr4_time_create (ZDR *, fattr4_time_create*); extern uint32_t zdr_fattr4_time_delta (ZDR *, fattr4_time_delta*); extern uint32_t zdr_fattr4_time_metadata (ZDR *, fattr4_time_metadata*); extern uint32_t zdr_fattr4_time_modify (ZDR *, fattr4_time_modify*); extern uint32_t zdr_fattr4_time_modify_set (ZDR *, fattr4_time_modify_set*); extern uint32_t zdr_attrlist4 (ZDR *, attrlist4*); extern uint32_t zdr_fattr4 (ZDR *, fattr4*); extern uint32_t zdr_change_info4 (ZDR *, change_info4*); extern uint32_t zdr_clientaddr4 (ZDR *, clientaddr4*); extern uint32_t zdr_cb_client4 (ZDR *, cb_client4*); extern uint32_t zdr_stateid4 (ZDR *, stateid4*); extern uint32_t zdr_nfs_client_id4 (ZDR *, nfs_client_id4*); extern uint32_t zdr_open_owner4 (ZDR *, open_owner4*); extern uint32_t zdr_lock_owner4 (ZDR *, lock_owner4*); extern uint32_t zdr_nfs_lock_type4 (ZDR *, nfs_lock_type4*); extern uint32_t zdr_ACCESS4args (ZDR *, ACCESS4args*); extern uint32_t zdr_ACCESS4resok (ZDR *, ACCESS4resok*); extern uint32_t zdr_ACCESS4res (ZDR *, ACCESS4res*); extern uint32_t zdr_CLOSE4args (ZDR *, CLOSE4args*); extern uint32_t zdr_CLOSE4res (ZDR *, CLOSE4res*); extern uint32_t zdr_COMMIT4args (ZDR *, COMMIT4args*); extern uint32_t zdr_COMMIT4resok (ZDR *, COMMIT4resok*); extern uint32_t zdr_COMMIT4res (ZDR *, COMMIT4res*); extern uint32_t zdr_createtype4 (ZDR *, createtype4*); extern uint32_t zdr_CREATE4args (ZDR *, CREATE4args*); extern uint32_t zdr_CREATE4resok (ZDR *, CREATE4resok*); extern uint32_t zdr_CREATE4res (ZDR *, CREATE4res*); extern uint32_t zdr_DELEGPURGE4args (ZDR *, DELEGPURGE4args*); extern uint32_t zdr_DELEGPURGE4res (ZDR *, DELEGPURGE4res*); extern uint32_t zdr_DELEGRETURN4args (ZDR *, DELEGRETURN4args*); extern uint32_t zdr_DELEGRETURN4res (ZDR *, DELEGRETURN4res*); extern uint32_t zdr_GETATTR4args (ZDR *, GETATTR4args*); extern uint32_t zdr_GETATTR4resok (ZDR *, GETATTR4resok*); extern uint32_t zdr_GETATTR4res (ZDR *, GETATTR4res*); extern uint32_t zdr_GETFH4resok (ZDR *, GETFH4resok*); extern uint32_t zdr_GETFH4res (ZDR *, GETFH4res*); extern uint32_t zdr_LINK4args (ZDR *, LINK4args*); extern uint32_t zdr_LINK4resok (ZDR *, LINK4resok*); extern uint32_t zdr_LINK4res (ZDR *, LINK4res*); extern uint32_t zdr_open_to_lock_owner4 (ZDR *, open_to_lock_owner4*); extern uint32_t zdr_exist_lock_owner4 (ZDR *, exist_lock_owner4*); extern uint32_t zdr_locker4 (ZDR *, locker4*); extern uint32_t zdr_LOCK4args (ZDR *, LOCK4args*); extern uint32_t zdr_LOCK4denied (ZDR *, LOCK4denied*); extern uint32_t zdr_LOCK4resok (ZDR *, LOCK4resok*); extern uint32_t zdr_LOCK4res (ZDR *, LOCK4res*); extern uint32_t zdr_LOCKT4args (ZDR *, LOCKT4args*); extern uint32_t zdr_LOCKT4res (ZDR *, LOCKT4res*); extern uint32_t zdr_LOCKU4args (ZDR *, LOCKU4args*); extern uint32_t zdr_LOCKU4res (ZDR *, LOCKU4res*); extern uint32_t zdr_LOOKUP4args (ZDR *, LOOKUP4args*); extern uint32_t zdr_LOOKUP4res (ZDR *, LOOKUP4res*); extern uint32_t zdr_LOOKUPP4res (ZDR *, LOOKUPP4res*); extern uint32_t zdr_NVERIFY4args (ZDR *, NVERIFY4args*); extern uint32_t zdr_NVERIFY4res (ZDR *, NVERIFY4res*); extern uint32_t zdr_createmode4 (ZDR *, createmode4*); extern uint32_t zdr_createhow4 (ZDR *, createhow4*); extern uint32_t zdr_opentype4 (ZDR *, opentype4*); extern uint32_t zdr_openflag4 (ZDR *, openflag4*); extern uint32_t zdr_limit_by4 (ZDR *, limit_by4*); extern uint32_t zdr_nfs_modified_limit4 (ZDR *, nfs_modified_limit4*); extern uint32_t zdr_nfs_space_limit4 (ZDR *, nfs_space_limit4*); extern uint32_t zdr_open_delegation_type4 (ZDR *, open_delegation_type4*); extern uint32_t zdr_open_claim_type4 (ZDR *, open_claim_type4*); extern uint32_t zdr_open_claim_delegate_cur4 (ZDR *, open_claim_delegate_cur4*); extern uint32_t zdr_open_claim4 (ZDR *, open_claim4*); extern uint32_t zdr_OPEN4args (ZDR *, OPEN4args*); extern uint32_t zdr_open_read_delegation4 (ZDR *, open_read_delegation4*); extern uint32_t zdr_open_write_delegation4 (ZDR *, open_write_delegation4*); extern uint32_t zdr_open_delegation4 (ZDR *, open_delegation4*); extern uint32_t zdr_OPEN4resok (ZDR *, OPEN4resok*); extern uint32_t zdr_OPEN4res (ZDR *, OPEN4res*); extern uint32_t zdr_OPENATTR4args (ZDR *, OPENATTR4args*); extern uint32_t zdr_OPENATTR4res (ZDR *, OPENATTR4res*); extern uint32_t zdr_OPEN_CONFIRM4args (ZDR *, OPEN_CONFIRM4args*); extern uint32_t zdr_OPEN_CONFIRM4resok (ZDR *, OPEN_CONFIRM4resok*); extern uint32_t zdr_OPEN_CONFIRM4res (ZDR *, OPEN_CONFIRM4res*); extern uint32_t zdr_OPEN_DOWNGRADE4args (ZDR *, OPEN_DOWNGRADE4args*); extern uint32_t zdr_OPEN_DOWNGRADE4resok (ZDR *, OPEN_DOWNGRADE4resok*); extern uint32_t zdr_OPEN_DOWNGRADE4res (ZDR *, OPEN_DOWNGRADE4res*); extern uint32_t zdr_PUTFH4args (ZDR *, PUTFH4args*); extern uint32_t zdr_PUTFH4res (ZDR *, PUTFH4res*); extern uint32_t zdr_PUTPUBFH4res (ZDR *, PUTPUBFH4res*); extern uint32_t zdr_PUTROOTFH4res (ZDR *, PUTROOTFH4res*); extern uint32_t zdr_READ4args (ZDR *, READ4args*); extern uint32_t zdr_READ4resok (ZDR *, READ4resok*); extern uint32_t zdr_READ4res (ZDR *, READ4res*); extern uint32_t zdr_READDIR4args (ZDR *, READDIR4args*); extern uint32_t zdr_entry4 (ZDR *, entry4*); extern uint32_t zdr_dirlist4 (ZDR *, dirlist4*); extern uint32_t zdr_READDIR4resok (ZDR *, READDIR4resok*); extern uint32_t zdr_READDIR4res (ZDR *, READDIR4res*); extern uint32_t zdr_READLINK4resok (ZDR *, READLINK4resok*); extern uint32_t zdr_READLINK4res (ZDR *, READLINK4res*); extern uint32_t zdr_REMOVE4args (ZDR *, REMOVE4args*); extern uint32_t zdr_REMOVE4resok (ZDR *, REMOVE4resok*); extern uint32_t zdr_REMOVE4res (ZDR *, REMOVE4res*); extern uint32_t zdr_RENAME4args (ZDR *, RENAME4args*); extern uint32_t zdr_RENAME4resok (ZDR *, RENAME4resok*); extern uint32_t zdr_RENAME4res (ZDR *, RENAME4res*); extern uint32_t zdr_RENEW4args (ZDR *, RENEW4args*); extern uint32_t zdr_RENEW4res (ZDR *, RENEW4res*); extern uint32_t zdr_RESTOREFH4res (ZDR *, RESTOREFH4res*); extern uint32_t zdr_SAVEFH4res (ZDR *, SAVEFH4res*); extern uint32_t zdr_SETATTR4args (ZDR *, SETATTR4args*); extern uint32_t zdr_SETATTR4res (ZDR *, SETATTR4res*); extern uint32_t zdr_SETCLIENTID4args (ZDR *, SETCLIENTID4args*); extern uint32_t zdr_SETCLIENTID4resok (ZDR *, SETCLIENTID4resok*); extern uint32_t zdr_SETCLIENTID4res (ZDR *, SETCLIENTID4res*); extern uint32_t zdr_SETCLIENTID_CONFIRM4args (ZDR *, SETCLIENTID_CONFIRM4args*); extern uint32_t zdr_SETCLIENTID_CONFIRM4res (ZDR *, SETCLIENTID_CONFIRM4res*); extern uint32_t zdr_VERIFY4args (ZDR *, VERIFY4args*); extern uint32_t zdr_VERIFY4res (ZDR *, VERIFY4res*); extern uint32_t zdr_stable_how4 (ZDR *, stable_how4*); extern uint32_t zdr_WRITE4args (ZDR *, WRITE4args*); extern uint32_t zdr_WRITE4resok (ZDR *, WRITE4resok*); extern uint32_t zdr_WRITE4res (ZDR *, WRITE4res*); extern uint32_t zdr_RELEASE_LOCKOWNER4args (ZDR *, RELEASE_LOCKOWNER4args*); extern uint32_t zdr_RELEASE_LOCKOWNER4res (ZDR *, RELEASE_LOCKOWNER4res*); extern uint32_t zdr_ILLEGAL4res (ZDR *, ILLEGAL4res*); extern uint32_t zdr_nfs_opnum4 (ZDR *, nfs_opnum4*); extern uint32_t zdr_nfs_argop4 (ZDR *, nfs_argop4*); extern uint32_t zdr_nfs_resop4 (ZDR *, nfs_resop4*); extern uint32_t zdr_COMPOUND4args (ZDR *, COMPOUND4args*); extern uint32_t zdr_COMPOUND4res (ZDR *, COMPOUND4res*); extern uint32_t zdr_CB_GETATTR4args (ZDR *, CB_GETATTR4args*); extern uint32_t zdr_CB_GETATTR4resok (ZDR *, CB_GETATTR4resok*); extern uint32_t zdr_CB_GETATTR4res (ZDR *, CB_GETATTR4res*); extern uint32_t zdr_CB_RECALL4args (ZDR *, CB_RECALL4args*); extern uint32_t zdr_CB_RECALL4res (ZDR *, CB_RECALL4res*); extern uint32_t zdr_CB_ILLEGAL4res (ZDR *, CB_ILLEGAL4res*); extern uint32_t zdr_nfs_cb_opnum4 (ZDR *, nfs_cb_opnum4*); extern uint32_t zdr_nfs_cb_argop4 (ZDR *, nfs_cb_argop4*); extern uint32_t zdr_nfs_cb_resop4 (ZDR *, nfs_cb_resop4*); extern uint32_t zdr_CB_COMPOUND4args (ZDR *, CB_COMPOUND4args*); extern uint32_t zdr_CB_COMPOUND4res (ZDR *, CB_COMPOUND4res*); #else /* K&R C */ extern uint32_t zdr_nfs_ftype4 (); extern uint32_t zdr_nfsstat4 (); extern uint32_t zdr_bitmap4 (); extern uint32_t zdr_offset4 (); extern uint32_t zdr_count4 (); extern uint32_t zdr_length4 (); extern uint32_t zdr_clientid4 (); extern uint32_t zdr_seqid4 (); extern uint32_t zdr_utf8string (); extern uint32_t zdr_utf8str_cis (); extern uint32_t zdr_utf8str_cs (); extern uint32_t zdr_utf8str_mixed (); extern uint32_t zdr_component4 (); extern uint32_t zdr_pathname4 (); extern uint32_t zdr_nfs_lockid4 (); extern uint32_t zdr_nfs_cookie4 (); extern uint32_t zdr_linktext4 (); extern uint32_t zdr_sec_oid4 (); extern uint32_t zdr_qop4 (); extern uint32_t zdr_mode4 (); extern uint32_t zdr_changeid4 (); extern uint32_t zdr_verifier4 (); extern uint32_t zdr_nfstime4 (); extern uint32_t zdr_time_how4 (); extern uint32_t zdr_settime4 (); extern uint32_t zdr_nfs_fh4 (); extern uint32_t zdr_fsid4 (); extern uint32_t zdr_fs_location4 (); extern uint32_t zdr_fs_locations4 (); extern uint32_t zdr_acetype4 (); extern uint32_t zdr_aceflag4 (); extern uint32_t zdr_acemask4 (); extern uint32_t zdr_nfsace4 (); extern uint32_t zdr_specdata4 (); extern uint32_t zdr_fattr4_supported_attrs (); extern uint32_t zdr_fattr4_type (); extern uint32_t zdr_fattr4_fh_expire_type (); extern uint32_t zdr_fattr4_change (); extern uint32_t zdr_fattr4_size (); extern uint32_t zdr_fattr4_link_support (); extern uint32_t zdr_fattr4_symlink_support (); extern uint32_t zdr_fattr4_named_attr (); extern uint32_t zdr_fattr4_fsid (); extern uint32_t zdr_fattr4_unique_handles (); extern uint32_t zdr_fattr4_lease_time (); extern uint32_t zdr_fattr4_rdattr_error (); extern uint32_t zdr_fattr4_acl (); extern uint32_t zdr_fattr4_aclsupport (); extern uint32_t zdr_fattr4_archive (); extern uint32_t zdr_fattr4_cansettime (); extern uint32_t zdr_fattr4_case_insensitive (); extern uint32_t zdr_fattr4_case_preserving (); extern uint32_t zdr_fattr4_chown_restricted (); extern uint32_t zdr_fattr4_fileid (); extern uint32_t zdr_fattr4_files_avail (); extern uint32_t zdr_fattr4_filehandle (); extern uint32_t zdr_fattr4_files_free (); extern uint32_t zdr_fattr4_files_total (); extern uint32_t zdr_fattr4_fs_locations (); extern uint32_t zdr_fattr4_hidden (); extern uint32_t zdr_fattr4_homogeneous (); extern uint32_t zdr_fattr4_maxfilesize (); extern uint32_t zdr_fattr4_maxlink (); extern uint32_t zdr_fattr4_maxname (); extern uint32_t zdr_fattr4_maxread (); extern uint32_t zdr_fattr4_maxwrite (); extern uint32_t zdr_fattr4_mimetype (); extern uint32_t zdr_fattr4_mode (); extern uint32_t zdr_fattr4_mounted_on_fileid (); extern uint32_t zdr_fattr4_no_trunc (); extern uint32_t zdr_fattr4_numlinks (); extern uint32_t zdr_fattr4_owner (); extern uint32_t zdr_fattr4_owner_group (); extern uint32_t zdr_fattr4_quota_avail_hard (); extern uint32_t zdr_fattr4_quota_avail_soft (); extern uint32_t zdr_fattr4_quota_used (); extern uint32_t zdr_fattr4_rawdev (); extern uint32_t zdr_fattr4_space_avail (); extern uint32_t zdr_fattr4_space_free (); extern uint32_t zdr_fattr4_space_total (); extern uint32_t zdr_fattr4_space_used (); extern uint32_t zdr_fattr4_system (); extern uint32_t zdr_fattr4_time_access (); extern uint32_t zdr_fattr4_time_access_set (); extern uint32_t zdr_fattr4_time_backup (); extern uint32_t zdr_fattr4_time_create (); extern uint32_t zdr_fattr4_time_delta (); extern uint32_t zdr_fattr4_time_metadata (); extern uint32_t zdr_fattr4_time_modify (); extern uint32_t zdr_fattr4_time_modify_set (); extern uint32_t zdr_attrlist4 (); extern uint32_t zdr_fattr4 (); extern uint32_t zdr_change_info4 (); extern uint32_t zdr_clientaddr4 (); extern uint32_t zdr_cb_client4 (); extern uint32_t zdr_stateid4 (); extern uint32_t zdr_nfs_client_id4 (); extern uint32_t zdr_open_owner4 (); extern uint32_t zdr_lock_owner4 (); extern uint32_t zdr_nfs_lock_type4 (); extern uint32_t zdr_ACCESS4args (); extern uint32_t zdr_ACCESS4resok (); extern uint32_t zdr_ACCESS4res (); extern uint32_t zdr_CLOSE4args (); extern uint32_t zdr_CLOSE4res (); extern uint32_t zdr_COMMIT4args (); extern uint32_t zdr_COMMIT4resok (); extern uint32_t zdr_COMMIT4res (); extern uint32_t zdr_createtype4 (); extern uint32_t zdr_CREATE4args (); extern uint32_t zdr_CREATE4resok (); extern uint32_t zdr_CREATE4res (); extern uint32_t zdr_DELEGPURGE4args (); extern uint32_t zdr_DELEGPURGE4res (); extern uint32_t zdr_DELEGRETURN4args (); extern uint32_t zdr_DELEGRETURN4res (); extern uint32_t zdr_GETATTR4args (); extern uint32_t zdr_GETATTR4resok (); extern uint32_t zdr_GETATTR4res (); extern uint32_t zdr_GETFH4resok (); extern uint32_t zdr_GETFH4res (); extern uint32_t zdr_LINK4args (); extern uint32_t zdr_LINK4resok (); extern uint32_t zdr_LINK4res (); extern uint32_t zdr_open_to_lock_owner4 (); extern uint32_t zdr_exist_lock_owner4 (); extern uint32_t zdr_locker4 (); extern uint32_t zdr_LOCK4args (); extern uint32_t zdr_LOCK4denied (); extern uint32_t zdr_LOCK4resok (); extern uint32_t zdr_LOCK4res (); extern uint32_t zdr_LOCKT4args (); extern uint32_t zdr_LOCKT4res (); extern uint32_t zdr_LOCKU4args (); extern uint32_t zdr_LOCKU4res (); extern uint32_t zdr_LOOKUP4args (); extern uint32_t zdr_LOOKUP4res (); extern uint32_t zdr_LOOKUPP4res (); extern uint32_t zdr_NVERIFY4args (); extern uint32_t zdr_NVERIFY4res (); extern uint32_t zdr_createmode4 (); extern uint32_t zdr_createhow4 (); extern uint32_t zdr_opentype4 (); extern uint32_t zdr_openflag4 (); extern uint32_t zdr_limit_by4 (); extern uint32_t zdr_nfs_modified_limit4 (); extern uint32_t zdr_nfs_space_limit4 (); extern uint32_t zdr_open_delegation_type4 (); extern uint32_t zdr_open_claim_type4 (); extern uint32_t zdr_open_claim_delegate_cur4 (); extern uint32_t zdr_open_claim4 (); extern uint32_t zdr_OPEN4args (); extern uint32_t zdr_open_read_delegation4 (); extern uint32_t zdr_open_write_delegation4 (); extern uint32_t zdr_open_delegation4 (); extern uint32_t zdr_OPEN4resok (); extern uint32_t zdr_OPEN4res (); extern uint32_t zdr_OPENATTR4args (); extern uint32_t zdr_OPENATTR4res (); extern uint32_t zdr_OPEN_CONFIRM4args (); extern uint32_t zdr_OPEN_CONFIRM4resok (); extern uint32_t zdr_OPEN_CONFIRM4res (); extern uint32_t zdr_OPEN_DOWNGRADE4args (); extern uint32_t zdr_OPEN_DOWNGRADE4resok (); extern uint32_t zdr_OPEN_DOWNGRADE4res (); extern uint32_t zdr_PUTFH4args (); extern uint32_t zdr_PUTFH4res (); extern uint32_t zdr_PUTPUBFH4res (); extern uint32_t zdr_PUTROOTFH4res (); extern uint32_t zdr_READ4args (); extern uint32_t zdr_READ4resok (); extern uint32_t zdr_READ4res (); extern uint32_t zdr_READDIR4args (); extern uint32_t zdr_entry4 (); extern uint32_t zdr_dirlist4 (); extern uint32_t zdr_READDIR4resok (); extern uint32_t zdr_READDIR4res (); extern uint32_t zdr_READLINK4resok (); extern uint32_t zdr_READLINK4res (); extern uint32_t zdr_REMOVE4args (); extern uint32_t zdr_REMOVE4resok (); extern uint32_t zdr_REMOVE4res (); extern uint32_t zdr_RENAME4args (); extern uint32_t zdr_RENAME4resok (); extern uint32_t zdr_RENAME4res (); extern uint32_t zdr_RENEW4args (); extern uint32_t zdr_RENEW4res (); extern uint32_t zdr_RESTOREFH4res (); extern uint32_t zdr_SAVEFH4res (); extern uint32_t zdr_SETATTR4args (); extern uint32_t zdr_SETATTR4res (); extern uint32_t zdr_SETCLIENTID4args (); extern uint32_t zdr_SETCLIENTID4resok (); extern uint32_t zdr_SETCLIENTID4res (); extern uint32_t zdr_SETCLIENTID_CONFIRM4args (); extern uint32_t zdr_SETCLIENTID_CONFIRM4res (); extern uint32_t zdr_VERIFY4args (); extern uint32_t zdr_VERIFY4res (); extern uint32_t zdr_stable_how4 (); extern uint32_t zdr_WRITE4args (); extern uint32_t zdr_WRITE4resok (); extern uint32_t zdr_WRITE4res (); extern uint32_t zdr_RELEASE_LOCKOWNER4args (); extern uint32_t zdr_RELEASE_LOCKOWNER4res (); extern uint32_t zdr_ILLEGAL4res (); extern uint32_t zdr_nfs_opnum4 (); extern uint32_t zdr_nfs_argop4 (); extern uint32_t zdr_nfs_resop4 (); extern uint32_t zdr_COMPOUND4args (); extern uint32_t zdr_COMPOUND4res (); extern uint32_t zdr_CB_GETATTR4args (); extern uint32_t zdr_CB_GETATTR4resok (); extern uint32_t zdr_CB_GETATTR4res (); extern uint32_t zdr_CB_RECALL4args (); extern uint32_t zdr_CB_RECALL4res (); extern uint32_t zdr_CB_ILLEGAL4res (); extern uint32_t zdr_nfs_cb_opnum4 (); extern uint32_t zdr_nfs_cb_argop4 (); extern uint32_t zdr_nfs_cb_resop4 (); extern uint32_t zdr_CB_COMPOUND4args (); extern uint32_t zdr_CB_COMPOUND4res (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_NFS4_H_RPCGEN */ libnfs-libnfs-4.0.0/nfs4/nfs4.c000066400000000000000000000233421343063627400161470ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2016 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef WIN32 #include #else #include #endif/*WIN32*/ #include #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-nfs4.h" char * nfsstat4_to_str(int error) { switch (error) { case NFS4_OK: return "NFS4_OK"; break; case NFS4ERR_PERM: return "NFS4ERR_PERM"; break; case NFS4ERR_NOENT: return "NFS4ERR_NOENT"; break; case NFS4ERR_IO: return "NFS4ERR_IO"; break; case NFS4ERR_NXIO: return "NFS4ERR_NXIO"; break; case NFS4ERR_ACCESS: return "NFS4ERR_ACCESS"; break; case NFS4ERR_EXIST: return "NFS4ERR_EXIST"; break; case NFS4ERR_XDEV: return "NFS4ERR_XDEV"; break; case NFS4ERR_NOTDIR: return "NFS4ERR_NOTDIR"; break; case NFS4ERR_ISDIR: return "NFS4ERR_ISDIR"; break; case NFS4ERR_INVAL: return "NFS4ERR_INVAL"; break; case NFS4ERR_FBIG: return "NFS4ERR_FBIG"; break; case NFS4ERR_NOSPC: return "NFS4ERR_NOSPC"; break; case NFS4ERR_ROFS: return"NFS4ERR_ROFS"; break; case NFS4ERR_MLINK: return "NFS4ERR_MLINK"; break; case NFS4ERR_NAMETOOLONG: return "NFS4ERR_NAMETOOLONG"; break; case NFS4ERR_NOTEMPTY: return "NFS4ERR_NOTEMPTY"; break; case NFS4ERR_DQUOT: return "NFS4ERR_DQUOT"; break; case NFS4ERR_STALE: return "NFS4ERR_STALE"; break; case NFS4ERR_BADHANDLE: return "NFS4ERR_BADHANDLE"; break; case NFS4ERR_BAD_COOKIE: return "NFS4ERR_BAD_COOKIE"; break; case NFS4ERR_NOTSUPP: return "NFS4ERR_NOTSUPP"; break; case NFS4ERR_TOOSMALL: return "NFS4ERR_TOOSMALL"; break; case NFS4ERR_SERVERFAULT: return "NFS4ERR_SERVERFAULT"; break; case NFS4ERR_BADTYPE: return "NFS4ERR_BADTYPE"; break; case NFS4ERR_DELAY: return "NFS4ERR_DELAY"; break; case NFS4ERR_SAME: return "NFS4ERR_SAME"; break; case NFS4ERR_DENIED: return "NFS4ERR_DENIED"; break; case NFS4ERR_EXPIRED: return "NFS4ERR_EXPIRED"; break; case NFS4ERR_LOCKED: return "NFS4ERR_LOCKED"; break; case NFS4ERR_GRACE: return "NFS4ERR_GRACE"; break; case NFS4ERR_FHEXPIRED: return "NFS4ERR_FHEXPIRED"; break; case NFS4ERR_SHARE_DENIED: return "NFS4ERR_SHARE_DENIED"; break; case NFS4ERR_WRONGSEC: return "NFS4ERR_WRONGSEC"; break; case NFS4ERR_CLID_INUSE: return "NFS4ERR_CLID_INUSE"; break; case NFS4ERR_RESOURCE: return "NFS4ERR_RESOURCE"; break; case NFS4ERR_MOVED: return "NFS4ERR_MOVED"; break; case NFS4ERR_NOFILEHANDLE: return "NFS4ERR_NOFILEHANDLE"; break; case NFS4ERR_MINOR_VERS_MISMATCH: return "NFS4ERR_MINOR_VERS_MISMATCH"; break; case NFS4ERR_STALE_CLIENTID: return "NFS4ERR_STALE_CLIENTID"; break; case NFS4ERR_STALE_STATEID: return "NFS4ERR_STALE_STATEID"; break; case NFS4ERR_OLD_STATEID: return "NFS4ERR_OLD_STATEID"; break; case NFS4ERR_BAD_STATEID: return "NFS4ERR_BAD_STATEID"; break; case NFS4ERR_BAD_SEQID: return "NFS4ERR_BAD_SEQID"; break; case NFS4ERR_NOT_SAME: return "NFS4ERR_NOT_SAME"; break; case NFS4ERR_LOCK_RANGE: return "NFS4ERR_LOCK_RANGE"; break; case NFS4ERR_SYMLINK: return "NFS4ERR_SYMLINK"; break; case NFS4ERR_RESTOREFH: return "NFS4ERR_RESTOREFH"; break; case NFS4ERR_LEASE_MOVED: return "NFS4ERR_LEASE_MOVED"; break; case NFS4ERR_ATTRNOTSUPP: return "NFS4ERR_ATTRNOTSUPP"; break; case NFS4ERR_NO_GRACE: return "NFS4ERR_NO_GRACE"; break; case NFS4ERR_RECLAIM_BAD: return "NFS4ERR_RECLAIM_BAD"; break; case NFS4ERR_RECLAIM_CONFLICT: return "NFS4ERR_RECLAIM_CONFLICT"; break; case NFS4ERR_BADZDR: return "NFS4ERR_BADZDR"; break; case NFS4ERR_LOCKS_HELD: return "NFS4ERR_LOCKS_HELD"; break; case NFS4ERR_OPENMODE: return "NFS4ERR_OPENMODE"; break; case NFS4ERR_BADOWNER: return "NFS4ERR_BADOWNER"; break; case NFS4ERR_BADCHAR: return "NFS4ERR_BADCHAR"; break; case NFS4ERR_BADNAME: return "NFS4ERR_BADNAME"; break; case NFS4ERR_BAD_RANGE: return "NFS4ERR_BAD_RANGE"; break; case NFS4ERR_LOCK_NOTSUPP: return "NFS4ERR_LOCK_NOTSUPP"; break; case NFS4ERR_OP_ILLEGAL: return "NFS4ERR_OP_ILLEGAL"; break; case NFS4ERR_DEADLOCK: return "NFS4ERR_DEADLOCK"; break; case NFS4ERR_FILE_OPEN: return "NFS4ERR_FILE_OPEN"; break; case NFS4ERR_ADMIN_REVOKED: return "NFS4ERR_ADMIN_REVOKED"; break; case NFS4ERR_CB_PATH_DOWN: return "NFS4ERR_CB_PATH_DOWN"; break; }; return "unknown nfsv4 error"; } int nfsstat4_to_errno(int error) { switch (error) { case NFS4_OK: return 0; case NFS4ERR_PERM: return -EPERM; case NFS4ERR_NOENT: return -ENOENT ; case NFS4ERR_IO: return -EIO; case NFS4ERR_NXIO: return -ENXIO; case NFS4ERR_ACCESS: return -EACCES ; case NFS4ERR_EXIST: return -EEXIST; case NFS4ERR_XDEV: return -EXDEV; case NFS4ERR_NOTDIR: return -ENOTDIR ; case NFS4ERR_ISDIR: return -EISDIR ; case NFS4ERR_INVAL: return -EINVAL; case NFS4ERR_FBIG: return -EFBIG; case NFS4ERR_NOSPC: return -ENOSPC; case NFS4ERR_ROFS: return -EROFS; case NFS4ERR_MLINK: return -EMLINK; case NFS4ERR_NAMETOOLONG: return -ENAMETOOLONG; case NFS4ERR_NOTEMPTY: return -ENOTEMPTY; case NFS4ERR_DQUOT: return -ERANGE; case NFS4ERR_STALE: return -EIO; case NFS4ERR_BADHANDLE: return -EINVAL; case NFS4ERR_BAD_COOKIE: return -EINVAL; case NFS4ERR_NOTSUPP: return -EINVAL; case NFS4ERR_TOOSMALL: return -EIO; case NFS4ERR_SERVERFAULT: return -EIO; case NFS4ERR_BADTYPE: return -EINVAL; case NFS4ERR_DELAY: return -EIO; case NFS4ERR_SAME: return -EIO; case NFS4ERR_DENIED: return -EIO; case NFS4ERR_EXPIRED: return -EIO; case NFS4ERR_LOCKED: return -EIO; case NFS4ERR_GRACE: return -EIO; case NFS4ERR_FHEXPIRED: return -EIO; case NFS4ERR_SHARE_DENIED: return -EIO; case NFS4ERR_WRONGSEC: return -EIO; case NFS4ERR_CLID_INUSE: return -EIO; case NFS4ERR_RESOURCE: return -EIO; case NFS4ERR_MOVED: return -EIO; case NFS4ERR_NOFILEHANDLE: return -EIO; case NFS4ERR_MINOR_VERS_MISMATCH: return -EIO; case NFS4ERR_STALE_CLIENTID: return -EIO; case NFS4ERR_STALE_STATEID: return -EIO; case NFS4ERR_OLD_STATEID: return -EIO; case NFS4ERR_BAD_STATEID: return -EINVAL; case NFS4ERR_BAD_SEQID: return -EINVAL; case NFS4ERR_NOT_SAME: return -EIO; case NFS4ERR_LOCK_RANGE: return -EIO; case NFS4ERR_SYMLINK: return -EIO; case NFS4ERR_RESTOREFH: return -EIO; case NFS4ERR_ATTRNOTSUPP: return -EINVAL; case NFS4ERR_NO_GRACE: return -EIO; case NFS4ERR_RECLAIM_BAD: return -EIO; case NFS4ERR_RECLAIM_CONFLICT: return -EIO; case NFS4ERR_BADZDR: return -EINVAL; case NFS4ERR_LOCKS_HELD: return -EIO; case NFS4ERR_OPENMODE: return -EIO; case NFS4ERR_BADOWNER: return -EINVAL; case NFS4ERR_BADCHAR: return -EINVAL; case NFS4ERR_BADNAME: return -EINVAL; case NFS4ERR_BAD_RANGE: return -EINVAL; case NFS4ERR_LOCK_NOTSUPP: return -EINVAL; case NFS4ERR_OP_ILLEGAL: return -EIO; case NFS4ERR_DEADLOCK: return -EIO; case NFS4ERR_FILE_OPEN: return -EIO; case NFS4ERR_ADMIN_REVOKED: return -EIO; case NFS4ERR_CB_PATH_DOWN: return -EIO; }; return -ERANGE; } int rpc_nfs4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS4_PROGRAM, NFS_V4, NFSPROC4_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu " "for NFS4/NULL call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for " "NFS4/NULL call"); return -1; } return 0; } int rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb, struct COMPOUND4args *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NFS4_PROGRAM, NFS_V4, NFSPROC4_COMPOUND, cb, private_data, (zdrproc_t)zdr_COMPOUND4res, sizeof(COMPOUND4res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for " "NFS4/COMPOUND call"); return -1; } if (zdr_COMPOUND4args(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode COMPOUND4args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for " "NFS4/COMPOUND4 call"); return -3; } return 0; } libnfs-libnfs-4.0.0/nfs4/nfs4.x000066400000000000000000001240711343063627400161750ustar00rootroot00000000000000/* This is based on RFC3530 */ /* * NFS v4 Definitions */ /* * Copyright (C) The Internet Society (1998,1999,2000,2001,2002). * All Rights Reserved. */ /* * nfs4_prot.x * */ /* * Sizes */ const NFS4_FHSIZE = 128; const NFS4_VERIFIER_SIZE = 8; const NFS4_OPAQUE_LIMIT = 1024; /* * File types */ enum nfs_ftype4 { NF4REG = 1, /* Regular File */ NF4DIR = 2, /* Directory */ NF4BLK = 3, /* Special File - block device */ NF4CHR = 4, /* Special File - character device */ NF4LNK = 5, /* Symbolic Link */ NF4SOCK = 6, /* Special File - socket */ NF4FIFO = 7, /* Special File - fifo */ NF4ATTRDIR = 8, /* Attribute Directory */ NF4NAMEDATTR = 9 /* Named Attribute */ }; /* * Error status */ enum nfsstat4 { NFS4_OK = 0, /* everything is okay */ NFS4ERR_PERM = 1, /* caller not privileged */ NFS4ERR_NOENT = 2, /* no such file/directory */ NFS4ERR_IO = 5, /* hard I/O error */ NFS4ERR_NXIO = 6, /* no such device */ NFS4ERR_ACCESS = 13, /* access denied */ NFS4ERR_EXIST = 17, /* file already exists */ NFS4ERR_XDEV = 18, /* different filesystems */ /* Unused/reserved 19 */ NFS4ERR_NOTDIR = 20, /* should be a directory */ NFS4ERR_ISDIR = 21, /* should not be directory */ NFS4ERR_INVAL = 22, /* invalid argument */ NFS4ERR_FBIG = 27, /* file exceeds server max */ NFS4ERR_NOSPC = 28, /* no space on filesystem */ NFS4ERR_ROFS = 30, /* read-only filesystem */ NFS4ERR_MLINK = 31, /* too many hard links */ NFS4ERR_NAMETOOLONG = 63, /* name exceeds server max */ NFS4ERR_NOTEMPTY = 66, /* directory not empty */ NFS4ERR_DQUOT = 69, /* hard quota limit reached*/ NFS4ERR_STALE = 70, /* file no longer exists */ NFS4ERR_BADHANDLE = 10001,/* Illegal filehandle */ NFS4ERR_BAD_COOKIE = 10003,/* READDIR cookie is stale */ NFS4ERR_NOTSUPP = 10004,/* operation not supported */ NFS4ERR_TOOSMALL = 10005,/* response limit exceeded */ NFS4ERR_SERVERFAULT = 10006,/* undefined server error */ NFS4ERR_BADTYPE = 10007,/* type invalid for CREATE */ NFS4ERR_DELAY = 10008,/* file "busy" - retry */ NFS4ERR_SAME = 10009,/* nverify says attrs same */ NFS4ERR_DENIED = 10010,/* lock unavailable */ NFS4ERR_EXPIRED = 10011,/* lock lease expired */ NFS4ERR_LOCKED = 10012,/* I/O failed due to lock */ NFS4ERR_GRACE = 10013,/* in grace period */ NFS4ERR_FHEXPIRED = 10014,/* filehandle expired */ NFS4ERR_SHARE_DENIED = 10015,/* share reserve denied */ NFS4ERR_WRONGSEC = 10016,/* wrong security flavor */ NFS4ERR_CLID_INUSE = 10017,/* clientid in use */ NFS4ERR_RESOURCE = 10018,/* resource exhaustion */ NFS4ERR_MOVED = 10019,/* filesystem relocated */ NFS4ERR_NOFILEHANDLE = 10020,/* current FH is not set */ NFS4ERR_MINOR_VERS_MISMATCH = 10021,/* minor vers not supp */ NFS4ERR_STALE_CLIENTID = 10022,/* server has rebooted */ NFS4ERR_STALE_STATEID = 10023,/* server has rebooted */ NFS4ERR_OLD_STATEID = 10024,/* state is out of sync */ NFS4ERR_BAD_STATEID = 10025,/* incorrect stateid */ NFS4ERR_BAD_SEQID = 10026,/* request is out of seq. */ NFS4ERR_NOT_SAME = 10027,/* verify - attrs not same */ NFS4ERR_LOCK_RANGE = 10028,/* lock range not supported*/ NFS4ERR_SYMLINK = 10029,/* should be file/directory*/ NFS4ERR_RESTOREFH = 10030,/* no saved filehandle */ NFS4ERR_LEASE_MOVED = 10031,/* some filesystem moved */ NFS4ERR_ATTRNOTSUPP = 10032,/* recommended attr not sup*/ NFS4ERR_NO_GRACE = 10033,/* reclaim outside of grace*/ NFS4ERR_RECLAIM_BAD = 10034,/* reclaim error at server */ NFS4ERR_RECLAIM_CONFLICT = 10035,/* conflict on reclaim */ NFS4ERR_BADZDR = 10036,/* ZDR decode failed */ NFS4ERR_LOCKS_HELD = 10037,/* file locks held at CLOSE*/ NFS4ERR_OPENMODE = 10038,/* conflict in OPEN and I/O*/ NFS4ERR_BADOWNER = 10039,/* owner translation bad */ NFS4ERR_BADCHAR = 10040,/* utf-8 char not supported*/ NFS4ERR_BADNAME = 10041,/* name not supported */ NFS4ERR_BAD_RANGE = 10042,/* lock range not supported*/ NFS4ERR_LOCK_NOTSUPP = 10043,/* no atomic up/downgrade */ NFS4ERR_OP_ILLEGAL = 10044,/* undefined operation */ NFS4ERR_DEADLOCK = 10045,/* file locking deadlock */ NFS4ERR_FILE_OPEN = 10046,/* open file blocks op. */ NFS4ERR_ADMIN_REVOKED = 10047,/* lockowner state revoked */ NFS4ERR_CB_PATH_DOWN = 10048 /* callback path down */ }; /* * Basic data types */ typedef uint32_t bitmap4<>; typedef uint64_t offset4; typedef uint32_t count4; typedef uint64_t length4; typedef uint64_t clientid4; typedef uint32_t seqid4; typedef opaque utf8string<>; typedef utf8string utf8str_cis; typedef utf8string utf8str_cs; typedef utf8string utf8str_mixed; typedef utf8str_cs component4; typedef component4 pathname4<>; typedef uint64_t nfs_lockid4; typedef uint64_t nfs_cookie4; typedef utf8str_cs linktext4; typedef opaque sec_oid4<>; typedef uint32_t qop4; typedef uint32_t mode4; typedef uint64_t changeid4; typedef opaque verifier4[NFS4_VERIFIER_SIZE]; /* * Timeval */ struct nfstime4 { int64_t seconds; uint32_t nseconds; }; enum time_how4 { SET_TO_SERVER_TIME4 = 0, SET_TO_CLIENT_TIME4 = 1 }; union settime4 switch (time_how4 set_it) { case SET_TO_CLIENT_TIME4: nfstime4 time; default: void; }; /* * File access handle */ typedef opaque nfs_fh4; /* * File attribute definitions */ /* * FSID structure for major/minor */ struct fsid4 { uint64_t major; uint64_t minor; }; /* * Filesystem locations attribute for relocation/migration */ struct fs_location4 { utf8str_cis server<>; pathname4 rootpath; }; struct fs_locations4 { pathname4 fs_root; fs_location4 locations<>; }; /* * Various Access Control Entry definitions */ /* * Mask that indicates which Access Control Entries are supported. * Values for the fattr4_aclsupport attribute. */ const ACL4_SUPPORT_ALLOW_ACL = 0x00000001; const ACL4_SUPPORT_DENY_ACL = 0x00000002; const ACL4_SUPPORT_AUDIT_ACL = 0x00000004; const ACL4_SUPPORT_ALARM_ACL = 0x00000008; typedef uint32_t acetype4; /* * acetype4 values, others can be added as needed. */ const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000; const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001; const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002; const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003; /* * ACE flag */ typedef uint32_t aceflag4; /* * ACE flag values */ const ACE4_FILE_INHERIT_ACE = 0x00000001; const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002; const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004; const ACE4_INHERIT_ONLY_ACE = 0x00000008; const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010; const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020; const ACE4_IDENTIFIER_GROUP = 0x00000040; /* * ACE mask */ typedef uint32_t acemask4; /* * ACE mask values */ const ACE4_READ_DATA = 0x00000001; const ACE4_LIST_DIRECTORY = 0x00000001; const ACE4_WRITE_DATA = 0x00000002; const ACE4_ADD_FILE = 0x00000002; const ACE4_APPEND_DATA = 0x00000004; const ACE4_ADD_SUBDIRECTORY = 0x00000004; const ACE4_READ_NAMED_ATTRS = 0x00000008; const ACE4_WRITE_NAMED_ATTRS = 0x00000010; const ACE4_EXECUTE = 0x00000020; const ACE4_DELETE_CHILD = 0x00000040; const ACE4_READ_ATTRIBUTES = 0x00000080; const ACE4_WRITE_ATTRIBUTES = 0x00000100; const ACE4_DELETE = 0x00010000; const ACE4_READ_ACL = 0x00020000; const ACE4_WRITE_ACL = 0x00040000; const ACE4_WRITE_OWNER = 0x00080000; const ACE4_SYNCHRONIZE = 0x00100000; /* * ACE4_GENERIC_READ -- defined as combination of * ACE4_READ_ACL | * ACE4_READ_DATA | * ACE4_READ_ATTRIBUTES | * ACE4_SYNCHRONIZE */ const ACE4_GENERIC_READ = 0x00120081; /* * ACE4_GENERIC_WRITE -- defined as combination of * ACE4_READ_ACL | * ACE4_WRITE_DATA | * ACE4_WRITE_ATTRIBUTES | * ACE4_WRITE_ACL | * ACE4_APPEND_DATA | * ACE4_SYNCHRONIZE */ const ACE4_GENERIC_WRITE = 0x00160106; /* * ACE4_GENERIC_EXECUTE -- defined as combination of * ACE4_READ_ACL * ACE4_READ_ATTRIBUTES * ACE4_EXECUTE * ACE4_SYNCHRONIZE */ const ACE4_GENERIC_EXECUTE = 0x001200A0; /* * Access Control Entry definition */ struct nfsace4 { acetype4 type; aceflag4 flag; acemask4 access_mask; utf8str_mixed who; }; /* * Field definitions for the fattr4_mode attribute */ const MODE4_SUID = 0x800; /* set user id on execution */ const MODE4_SGID = 0x400; /* set group id on execution */ const MODE4_SVTX = 0x200; /* save text even after use */ const MODE4_RUSR = 0x100; /* read permission: owner */ const MODE4_WUSR = 0x080; /* write permission: owner */ const MODE4_XUSR = 0x040; /* execute permission: owner */ const MODE4_RGRP = 0x020; /* read permission: group */ const MODE4_WGRP = 0x010; /* write permission: group */ const MODE4_XGRP = 0x008; /* execute permission: group */ const MODE4_ROTH = 0x004; /* read permission: other */ const MODE4_WOTH = 0x002; /* write permission: other */ const MODE4_XOTH = 0x001; /* execute permission: other */ /* * Special data/attribute associated with * file types NF4BLK and NF4CHR. */ struct specdata4 { uint32_t specdata1; /* major device number */ uint32_t specdata2; /* minor device number */ }; /* * Values for fattr4_fh_expire_type */ const FH4_PERSISTENT = 0x00000000; const FH4_NOEXPIRE_WITH_OPEN = 0x00000001; const FH4_VOLATILE_ANY = 0x00000002; const FH4_VOL_MIGRATION = 0x00000004; const FH4_VOL_RENAME = 0x00000008; typedef bitmap4 fattr4_supported_attrs; typedef nfs_ftype4 fattr4_type; typedef uint32_t fattr4_fh_expire_type; typedef changeid4 fattr4_change; typedef uint64_t fattr4_size; typedef bool fattr4_link_support; typedef bool fattr4_symlink_support; typedef bool fattr4_named_attr; typedef fsid4 fattr4_fsid; typedef bool fattr4_unique_handles; typedef uint32_t fattr4_lease_time; typedef nfsstat4 fattr4_rdattr_error; typedef nfsace4 fattr4_acl<>; typedef uint32_t fattr4_aclsupport; typedef bool fattr4_archive; typedef bool fattr4_cansettime; typedef bool fattr4_case_insensitive; typedef bool fattr4_case_preserving; typedef bool fattr4_chown_restricted; typedef uint64_t fattr4_fileid; typedef uint64_t fattr4_files_avail; typedef nfs_fh4 fattr4_filehandle; typedef uint64_t fattr4_files_free; typedef uint64_t fattr4_files_total; typedef fs_locations4 fattr4_fs_locations; typedef bool fattr4_hidden; typedef bool fattr4_homogeneous; typedef uint64_t fattr4_maxfilesize; typedef uint32_t fattr4_maxlink; typedef uint32_t fattr4_maxname; typedef uint64_t fattr4_maxread; typedef uint64_t fattr4_maxwrite; typedef utf8str_cs fattr4_mimetype; typedef mode4 fattr4_mode; typedef uint64_t fattr4_mounted_on_fileid; typedef bool fattr4_no_trunc; typedef uint32_t fattr4_numlinks; typedef utf8str_mixed fattr4_owner; typedef utf8str_mixed fattr4_owner_group; typedef uint64_t fattr4_quota_avail_hard; typedef uint64_t fattr4_quota_avail_soft; typedef uint64_t fattr4_quota_used; typedef specdata4 fattr4_rawdev; typedef uint64_t fattr4_space_avail; typedef uint64_t fattr4_space_free; typedef uint64_t fattr4_space_total; typedef uint64_t fattr4_space_used; typedef bool fattr4_system; typedef nfstime4 fattr4_time_access; typedef settime4 fattr4_time_access_set; typedef nfstime4 fattr4_time_backup; typedef nfstime4 fattr4_time_create; typedef nfstime4 fattr4_time_delta; typedef nfstime4 fattr4_time_metadata; typedef nfstime4 fattr4_time_modify; typedef settime4 fattr4_time_modify_set; /* * Mandatory Attributes */ const FATTR4_SUPPORTED_ATTRS = 0; const FATTR4_TYPE = 1; const FATTR4_FH_EXPIRE_TYPE = 2; const FATTR4_CHANGE = 3; const FATTR4_SIZE = 4; const FATTR4_LINK_SUPPORT = 5; const FATTR4_SYMLINK_SUPPORT = 6; const FATTR4_NAMED_ATTR = 7; const FATTR4_FSID = 8; const FATTR4_UNIQUE_HANDLES = 9; const FATTR4_LEASE_TIME = 10; const FATTR4_RDATTR_ERROR = 11; const FATTR4_FILEHANDLE = 19; /* * Recommended Attributes */ const FATTR4_ACL = 12; const FATTR4_ACLSUPPORT = 13; const FATTR4_ARCHIVE = 14; const FATTR4_CANSETTIME = 15; const FATTR4_CASE_INSENSITIVE = 16; const FATTR4_CASE_PRESERVING = 17; const FATTR4_CHOWN_RESTRICTED = 18; const FATTR4_FILEID = 20; const FATTR4_FILES_AVAIL = 21; const FATTR4_FILES_FREE = 22; const FATTR4_FILES_TOTAL = 23; const FATTR4_FS_LOCATIONS = 24; const FATTR4_HIDDEN = 25; const FATTR4_HOMOGENEOUS = 26; const FATTR4_MAXFILESIZE = 27; const FATTR4_MAXLINK = 28; const FATTR4_MAXNAME = 29; const FATTR4_MAXREAD = 30; const FATTR4_MAXWRITE = 31; const FATTR4_MIMETYPE = 32; const FATTR4_MODE = 33; const FATTR4_NO_TRUNC = 34; const FATTR4_NUMLINKS = 35; const FATTR4_OWNER = 36; const FATTR4_OWNER_GROUP = 37; const FATTR4_QUOTA_AVAIL_HARD = 38; const FATTR4_QUOTA_AVAIL_SOFT = 39; const FATTR4_QUOTA_USED = 40; const FATTR4_RAWDEV = 41; const FATTR4_SPACE_AVAIL = 42; const FATTR4_SPACE_FREE = 43; const FATTR4_SPACE_TOTAL = 44; const FATTR4_SPACE_USED = 45; const FATTR4_SYSTEM = 46; const FATTR4_TIME_ACCESS = 47; const FATTR4_TIME_ACCESS_SET = 48; const FATTR4_TIME_BACKUP = 49; const FATTR4_TIME_CREATE = 50; const FATTR4_TIME_DELTA = 51; const FATTR4_TIME_METADATA = 52; const FATTR4_TIME_MODIFY = 53; const FATTR4_TIME_MODIFY_SET = 54; const FATTR4_MOUNTED_ON_FILEID = 55; typedef opaque attrlist4<>; /* * File attribute container */ struct fattr4 { bitmap4 attrmask; attrlist4 attr_vals; }; /* * Change info for the client */ struct change_info4 { bool atomic; changeid4 before; changeid4 after; }; struct clientaddr4 { /* see struct rpcb in RFC 1833 */ string r_netid<>; /* network id */ string r_addr<>; /* universal address */ }; /* * Callback program info as provided by the client */ struct cb_client4 { uint32_t cb_program; clientaddr4 cb_location; }; /* * Stateid */ struct stateid4 { uint32_t seqid; opaque other[12]; }; /* * Client ID */ struct nfs_client_id4 { verifier4 verifier; opaque id; }; struct open_owner4 { clientid4 clientid; opaque owner; }; struct lock_owner4 { clientid4 clientid; opaque owner; }; enum nfs_lock_type4 { READ_LT = 1, WRITE_LT = 2, READW_LT = 3, /* blocking read */ WRITEW_LT = 4 /* blocking write */ }; /* * ACCESS: Check access permission */ const ACCESS4_READ = 0x00000001; const ACCESS4_LOOKUP = 0x00000002; const ACCESS4_MODIFY = 0x00000004; const ACCESS4_EXTEND = 0x00000008; const ACCESS4_DELETE = 0x00000010; const ACCESS4_EXECUTE = 0x00000020; struct ACCESS4args { /* CURRENT_FH: object */ uint32_t access; }; struct ACCESS4resok { uint32_t supported; uint32_t access; }; union ACCESS4res switch (nfsstat4 status) { case NFS4_OK: ACCESS4resok resok4; default: void; }; /* * CLOSE: Close a file and release share reservations */ struct CLOSE4args { /* CURRENT_FH: object */ seqid4 seqid; stateid4 open_stateid; }; union CLOSE4res switch (nfsstat4 status) { case NFS4_OK: stateid4 open_stateid; default: void; }; /* * COMMIT: Commit cached data on server to stable storage */ struct COMMIT4args { /* CURRENT_FH: file */ offset4 offset; count4 count; }; struct COMMIT4resok { verifier4 writeverf; }; union COMMIT4res switch (nfsstat4 status) { case NFS4_OK: COMMIT4resok resok4; default: void; }; /* * CREATE: Create a non-regular file */ union createtype4 switch (nfs_ftype4 type) { case NF4LNK: linktext4 linkdata; case NF4BLK: case NF4CHR: specdata4 devdata; case NF4SOCK: case NF4FIFO: case NF4DIR: void; default: void; /* server should return NFS4ERR_BADTYPE */ }; struct CREATE4args { /* CURRENT_FH: directory for creation */ createtype4 objtype; component4 objname; fattr4 createattrs; }; struct CREATE4resok { change_info4 cinfo; bitmap4 attrset; /* attributes set */ }; union CREATE4res switch (nfsstat4 status) { case NFS4_OK: CREATE4resok resok4; default: void; }; /* * DELEGPURGE: Purge Delegations Awaiting Recovery */ struct DELEGPURGE4args { clientid4 clientid; }; struct DELEGPURGE4res { nfsstat4 status; }; /* * DELEGRETURN: Return a delegation */ struct DELEGRETURN4args { /* CURRENT_FH: delegated file */ stateid4 deleg_stateid; }; struct DELEGRETURN4res { nfsstat4 status; }; /* * GETATTR: Get file attributes */ struct GETATTR4args { /* CURRENT_FH: directory or file */ bitmap4 attr_request; }; struct GETATTR4resok { fattr4 obj_attributes; }; union GETATTR4res switch (nfsstat4 status) { case NFS4_OK: GETATTR4resok resok4; default: void; }; /* * GETFH: Get current filehandle */ struct GETFH4resok { nfs_fh4 object; }; union GETFH4res switch (nfsstat4 status) { case NFS4_OK: GETFH4resok resok4; default: void; }; /* * LINK: Create link to an object */ struct LINK4args { /* SAVED_FH: source object */ /* CURRENT_FH: target directory */ component4 newname; }; struct LINK4resok { change_info4 cinfo; }; union LINK4res switch (nfsstat4 status) { case NFS4_OK: LINK4resok resok4; default: void; }; /* * For LOCK, transition from open_owner to new lock_owner */ struct open_to_lock_owner4 { seqid4 open_seqid; stateid4 open_stateid; seqid4 lock_seqid; lock_owner4 lock_owner; }; /* * For LOCK, existing lock_owner continues to request file locks */ struct exist_lock_owner4 { stateid4 lock_stateid; seqid4 lock_seqid; }; union locker4 switch (bool new_lock_owner) { case TRUE: open_to_lock_owner4 open_owner; case FALSE: exist_lock_owner4 lock_owner; }; /* * LOCK/LOCKT/LOCKU: Record lock management */ struct LOCK4args { /* CURRENT_FH: file */ nfs_lock_type4 locktype; bool reclaim; offset4 offset; length4 length; locker4 locker; }; struct LOCK4denied { offset4 offset; length4 length; nfs_lock_type4 locktype; lock_owner4 owner; }; struct LOCK4resok { stateid4 lock_stateid; }; union LOCK4res switch (nfsstat4 status) { case NFS4_OK: LOCK4resok resok4; case NFS4ERR_DENIED: LOCK4denied denied; default: void; }; struct LOCKT4args { /* CURRENT_FH: file */ nfs_lock_type4 locktype; offset4 offset; length4 length; lock_owner4 owner; }; union LOCKT4res switch (nfsstat4 status) { case NFS4ERR_DENIED: LOCK4denied denied; case NFS4_OK: void; default: void; }; struct LOCKU4args { /* CURRENT_FH: file */ nfs_lock_type4 locktype; seqid4 seqid; stateid4 lock_stateid; offset4 offset; length4 length; }; union LOCKU4res switch (nfsstat4 status) { case NFS4_OK: stateid4 lock_stateid; default: void; }; /* * LOOKUP: Lookup filename */ struct LOOKUP4args { /* CURRENT_FH: directory */ component4 objname; }; struct LOOKUP4res { /* CURRENT_FH: object */ nfsstat4 status; }; /* * LOOKUPP: Lookup parent directory */ struct LOOKUPP4res { /* CURRENT_FH: directory */ nfsstat4 status; }; /* * NVERIFY: Verify attributes different */ struct NVERIFY4args { /* CURRENT_FH: object */ fattr4 obj_attributes; }; struct NVERIFY4res { nfsstat4 status; }; /* * Various definitions for OPEN */ enum createmode4 { UNCHECKED4 = 0, GUARDED4 = 1, EXCLUSIVE4 = 2 }; union createhow4 switch (createmode4 mode) { case UNCHECKED4: case GUARDED4: fattr4 createattrs; case EXCLUSIVE4: verifier4 createverf; }; enum opentype4 { OPEN4_NOCREATE = 0, OPEN4_CREATE = 1 }; union openflag4 switch (opentype4 opentype) { case OPEN4_CREATE: createhow4 how; default: void; }; /* Next definitions used for OPEN delegation */ enum limit_by4 { NFS_LIMIT_SIZE = 1, NFS_LIMIT_BLOCKS = 2 /* others as needed */ }; struct nfs_modified_limit4 { uint32_t num_blocks; uint32_t bytes_per_block; }; union nfs_space_limit4 switch (limit_by4 limitby) { /* limit specified as file size */ case NFS_LIMIT_SIZE: uint64_t filesize; /* limit specified by number of blocks */ case NFS_LIMIT_BLOCKS: nfs_modified_limit4 mod_blocks; } ; /* * Share Access and Deny constants for open argument */ const OPEN4_SHARE_ACCESS_READ = 0x00000001; const OPEN4_SHARE_ACCESS_WRITE = 0x00000002; const OPEN4_SHARE_ACCESS_BOTH = 0x00000003; const OPEN4_SHARE_DENY_NONE = 0x00000000; const OPEN4_SHARE_DENY_READ = 0x00000001; const OPEN4_SHARE_DENY_WRITE = 0x00000002; const OPEN4_SHARE_DENY_BOTH = 0x00000003; enum open_delegation_type4 { OPEN_DELEGATE_NONE = 0, OPEN_DELEGATE_READ = 1, OPEN_DELEGATE_WRITE = 2 }; enum open_claim_type4 { CLAIM_NULL = 0, CLAIM_PREVIOUS = 1, CLAIM_DELEGATE_CUR = 2, CLAIM_DELEGATE_PREV = 3 }; struct open_claim_delegate_cur4 { stateid4 delegate_stateid; component4 file; }; union open_claim4 switch (open_claim_type4 claim) { /* * No special rights to file. Ordinary OPEN of the specified file. */ case CLAIM_NULL: /* CURRENT_FH: directory */ component4 file; /* * Right to the file established by an open previous to server * reboot. File identified by filehandle obtained at that time * rather than by name. */ case CLAIM_PREVIOUS: /* CURRENT_FH: file being reclaimed */ open_delegation_type4 delegate_type; /* * Right to file based on a delegation granted by the server. * File is specified by name. */ case CLAIM_DELEGATE_CUR: /* CURRENT_FH: directory */ open_claim_delegate_cur4 delegate_cur_info; /* Right to file based on a delegation granted to a previous boot * instance of the client. File is specified by name. */ case CLAIM_DELEGATE_PREV: /* CURRENT_FH: directory */ component4 file_delegate_prev; }; /* * OPEN: Open a file, potentially receiving an open delegation */ struct OPEN4args { seqid4 seqid; uint32_t share_access; uint32_t share_deny; open_owner4 owner; openflag4 openhow; open_claim4 claim; }; struct open_read_delegation4 { stateid4 stateid; /* Stateid for delegation*/ bool recall; /* Pre-recalled flag for delegations obtained by reclaim (CLAIM_PREVIOUS) */ nfsace4 permissions; /* Defines users who don't need an ACCESS call to open for read */ }; struct open_write_delegation4 { stateid4 stateid; /* Stateid for delegation */ bool recall; /* Pre-recalled flag for delegations obtained by reclaim (CLAIM_PREVIOUS) */ nfs_space_limit4 space_limit; /* Defines condition that the client must check to determine whether the file needs to be flushed to the server on close. */ nfsace4 permissions; /* Defines users who don't need an ACCESS call as part of a delegated open. */ }; union open_delegation4 switch (open_delegation_type4 delegation_type) { case OPEN_DELEGATE_NONE: void; case OPEN_DELEGATE_READ: open_read_delegation4 read; case OPEN_DELEGATE_WRITE: open_write_delegation4 write; }; /* * Result flags */ /* Client must confirm open */ const OPEN4_RESULT_CONFIRM = 0x00000002; /* Type of file locking behavior at the server */ const OPEN4_RESULT_LOCKTYPE_POSIX = 0x00000004; struct OPEN4resok { stateid4 stateid; /* Stateid for open */ change_info4 cinfo; /* Directory Change Info */ uint32_t rflags; /* Result flags */ bitmap4 attrset; /* attribute set for create*/ open_delegation4 delegation; /* Info on any open delegation */ }; union OPEN4res switch (nfsstat4 status) { case NFS4_OK: /* CURRENT_FH: opened file */ OPEN4resok resok4; default: void; }; /* * OPENATTR: open named attributes directory */ struct OPENATTR4args { /* CURRENT_FH: object */ bool createdir; }; struct OPENATTR4res { /* CURRENT_FH: named attr directory */ nfsstat4 status; }; /* * OPEN_CONFIRM: confirm the open */ struct OPEN_CONFIRM4args { /* CURRENT_FH: opened file */ stateid4 open_stateid; seqid4 seqid; }; struct OPEN_CONFIRM4resok { stateid4 open_stateid; }; union OPEN_CONFIRM4res switch (nfsstat4 status) { case NFS4_OK: OPEN_CONFIRM4resok resok4; default: void; }; /* * OPEN_DOWNGRADE: downgrade the access/deny for a file */ struct OPEN_DOWNGRADE4args { /* CURRENT_FH: opened file */ stateid4 open_stateid; seqid4 seqid; uint32_t share_access; uint32_t share_deny; }; struct OPEN_DOWNGRADE4resok { stateid4 open_stateid; }; union OPEN_DOWNGRADE4res switch(nfsstat4 status) { case NFS4_OK: OPEN_DOWNGRADE4resok resok4; default: void; }; /* * PUTFH: Set current filehandle */ struct PUTFH4args { nfs_fh4 object; }; struct PUTFH4res { /* CURRENT_FH: */ nfsstat4 status; }; /* * PUTPUBFH: Set public filehandle */ struct PUTPUBFH4res { /* CURRENT_FH: public fh */ nfsstat4 status; }; /* * PUTROOTFH: Set root filehandle */ struct PUTROOTFH4res { /* CURRENT_FH: root fh */ nfsstat4 status; }; /* * READ: Read from file */ struct READ4args { /* CURRENT_FH: file */ stateid4 stateid; offset4 offset; count4 count; }; struct READ4resok { bool eof; opaque data<>; }; union READ4res switch (nfsstat4 status) { case NFS4_OK: READ4resok resok4; default: void; }; /* * READDIR: Read directory */ struct READDIR4args { /* CURRENT_FH: directory */ nfs_cookie4 cookie; verifier4 cookieverf; count4 dircount; count4 maxcount; bitmap4 attr_request; }; struct entry4 { nfs_cookie4 cookie; component4 name; fattr4 attrs; entry4 *nextentry; }; struct dirlist4 { entry4 *entries; bool eof; }; struct READDIR4resok { verifier4 cookieverf; dirlist4 reply; }; union READDIR4res switch (nfsstat4 status) { case NFS4_OK: READDIR4resok resok4; default: void; }; /* * READLINK: Read symbolic link */ struct READLINK4resok { linktext4 link; }; union READLINK4res switch (nfsstat4 status) { case NFS4_OK: READLINK4resok resok4; default: void; }; /* * REMOVE: Remove filesystem object */ struct REMOVE4args { /* CURRENT_FH: directory */ component4 target; }; struct REMOVE4resok { change_info4 cinfo; }; union REMOVE4res switch (nfsstat4 status) { case NFS4_OK: REMOVE4resok resok4; default: void; }; /* * RENAME: Rename directory entry */ struct RENAME4args { /* SAVED_FH: source directory */ component4 oldname; /* CURRENT_FH: target directory */ component4 newname; }; struct RENAME4resok { change_info4 source_cinfo; change_info4 target_cinfo; }; union RENAME4res switch (nfsstat4 status) { case NFS4_OK: RENAME4resok resok4; default: void; }; /* * RENEW: Renew a Lease */ struct RENEW4args { clientid4 clientid; }; struct RENEW4res { nfsstat4 status; }; /* * RESTOREFH: Restore saved filehandle */ struct RESTOREFH4res { /* CURRENT_FH: value of saved fh */ nfsstat4 status; }; /* * SAVEFH: Save current filehandle */ struct SAVEFH4res { /* SAVED_FH: value of current fh */ nfsstat4 status; }; #if 0 /* * SECINFO: Obtain Available Security Mechanisms */ struct SECINFO4args { /* CURRENT_FH: directory */ component4 name; }; /* * From RFC 2203 */ enum rpc_gss_svc_t { RPC_GSS_SVC_NONE = 1, RPC_GSS_SVC_INTEGRITY = 2, RPC_GSS_SVC_PRIVACY = 3 }; struct rpcsec_gss_info { sec_oid4 oid; qop4 qop; rpc_gss_svc_t service; }; /* RPCSEC_GSS has a value of '6' - See RFC 2203 */ union secinfo4 switch (uint32_t flavor) { case RPCSEC_GSS: rpcsec_gss_info flavor_info; default: void; }; typedef secinfo4 SECINFO4resok<>; union SECINFO4res switch (nfsstat4 status) { case NFS4_OK: SECINFO4resok resok4; default: void; }; #endif /* * SETATTR: Set attributes */ struct SETATTR4args { /* CURRENT_FH: target object */ stateid4 stateid; fattr4 obj_attributes; }; struct SETATTR4res { nfsstat4 status; bitmap4 attrsset; }; /* * SETCLIENTID */ struct SETCLIENTID4args { nfs_client_id4 client; cb_client4 callback; uint32_t callback_ident; }; struct SETCLIENTID4resok { clientid4 clientid; verifier4 setclientid_confirm; }; union SETCLIENTID4res switch (nfsstat4 status) { case NFS4_OK: SETCLIENTID4resok resok4; case NFS4ERR_CLID_INUSE: clientaddr4 client_using; default: void; }; struct SETCLIENTID_CONFIRM4args { clientid4 clientid; verifier4 setclientid_confirm; }; struct SETCLIENTID_CONFIRM4res { nfsstat4 status; }; /* * VERIFY: Verify attributes same */ struct VERIFY4args { /* CURRENT_FH: object */ fattr4 obj_attributes; }; struct VERIFY4res { nfsstat4 status; }; /* * WRITE: Write to file */ enum stable_how4 { UNSTABLE4 = 0, DATA_SYNC4 = 1, FILE_SYNC4 = 2 }; struct WRITE4args { /* CURRENT_FH: file */ stateid4 stateid; offset4 offset; stable_how4 stable; opaque data<>; }; struct WRITE4resok { count4 count; stable_how4 committed; verifier4 writeverf; }; union WRITE4res switch (nfsstat4 status) { case NFS4_OK: WRITE4resok resok4; default: void; }; /* * RELEASE_LOCKOWNER: Notify server to release lockowner */ struct RELEASE_LOCKOWNER4args { lock_owner4 lock_owner; }; struct RELEASE_LOCKOWNER4res { nfsstat4 status; }; /* * ILLEGAL: Response for illegal operation numbers */ struct ILLEGAL4res { nfsstat4 status; }; /* * Operation arrays */ enum nfs_opnum4 { OP_ACCESS = 3, OP_CLOSE = 4, OP_COMMIT = 5, OP_CREATE = 6, OP_DELEGPURGE = 7, OP_DELEGRETURN = 8, OP_GETATTR = 9, OP_GETFH = 10, OP_LINK = 11, OP_LOCK = 12, OP_LOCKT = 13, OP_LOCKU = 14, OP_LOOKUP = 15, OP_LOOKUPP = 16, OP_NVERIFY = 17, OP_OPEN = 18, OP_OPENATTR = 19, OP_OPEN_CONFIRM = 20, OP_OPEN_DOWNGRADE = 21, OP_PUTFH = 22, OP_PUTPUBFH = 23, OP_PUTROOTFH = 24, OP_READ = 25, OP_READDIR = 26, OP_READLINK = 27, OP_REMOVE = 28, OP_RENAME = 29, OP_RENEW = 30, OP_RESTOREFH = 31, OP_SAVEFH = 32, OP_SECINFO = 33, OP_SETATTR = 34, OP_SETCLIENTID = 35, OP_SETCLIENTID_CONFIRM = 36, OP_VERIFY = 37, OP_WRITE = 38, OP_RELEASE_LOCKOWNER = 39, OP_ILLEGAL = 10044 }; union nfs_argop4 switch (nfs_opnum4 argop) { case OP_ACCESS: ACCESS4args opaccess; case OP_CLOSE: CLOSE4args opclose; case OP_COMMIT: COMMIT4args opcommit; case OP_CREATE: CREATE4args opcreate; case OP_DELEGPURGE: DELEGPURGE4args opdelegpurge; case OP_DELEGRETURN: DELEGRETURN4args opdelegreturn; case OP_GETATTR: GETATTR4args opgetattr; case OP_GETFH: void; case OP_LINK: LINK4args oplink; case OP_LOCK: LOCK4args oplock; case OP_LOCKT: LOCKT4args oplockt; case OP_LOCKU: LOCKU4args oplocku; case OP_LOOKUP: LOOKUP4args oplookup; case OP_LOOKUPP: void; case OP_NVERIFY: NVERIFY4args opnverify; case OP_OPEN: OPEN4args opopen; case OP_OPENATTR: OPENATTR4args opopenattr; case OP_OPEN_CONFIRM: OPEN_CONFIRM4args opopen_confirm; case OP_OPEN_DOWNGRADE: OPEN_DOWNGRADE4args opopen_downgrade; case OP_PUTFH: PUTFH4args opputfh; case OP_PUTPUBFH: void; case OP_PUTROOTFH: void; case OP_READ: READ4args opread; case OP_READDIR: READDIR4args opreaddir; case OP_READLINK: void; case OP_REMOVE: REMOVE4args opremove; case OP_RENAME: RENAME4args oprename; case OP_RENEW: RENEW4args oprenew; case OP_RESTOREFH: void; case OP_SAVEFH: void; #if 0 case OP_SECINFO: SECINFO4args opsecinfo; #endif case OP_SETATTR: SETATTR4args opsetattr; case OP_SETCLIENTID: SETCLIENTID4args opsetclientid; case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4args opsetclientid_confirm; case OP_VERIFY: VERIFY4args opverify; case OP_WRITE: WRITE4args opwrite; case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4args oprelease_lockowner; case OP_ILLEGAL: void; }; union nfs_resop4 switch (nfs_opnum4 resop){ case OP_ACCESS: ACCESS4res opaccess; case OP_CLOSE: CLOSE4res opclose; case OP_COMMIT: COMMIT4res opcommit; case OP_CREATE: CREATE4res opcreate; case OP_DELEGPURGE: DELEGPURGE4res opdelegpurge; case OP_DELEGRETURN: DELEGRETURN4res opdelegreturn; case OP_GETATTR: GETATTR4res opgetattr; case OP_GETFH: GETFH4res opgetfh; case OP_LINK: LINK4res oplink; case OP_LOCK: LOCK4res oplock; case OP_LOCKT: LOCKT4res oplockt; case OP_LOCKU: LOCKU4res oplocku; case OP_LOOKUP: LOOKUP4res oplookup; case OP_LOOKUPP: LOOKUPP4res oplookupp; case OP_NVERIFY: NVERIFY4res opnverify; case OP_OPEN: OPEN4res opopen; case OP_OPENATTR: OPENATTR4res opopenattr; case OP_OPEN_CONFIRM: OPEN_CONFIRM4res opopen_confirm; case OP_OPEN_DOWNGRADE: OPEN_DOWNGRADE4res opopen_downgrade; case OP_PUTFH: PUTFH4res opputfh; case OP_PUTPUBFH: PUTPUBFH4res opputpubfh; case OP_PUTROOTFH: PUTROOTFH4res opputrootfh; case OP_READ: READ4res opread; case OP_READDIR: READDIR4res opreaddir; case OP_READLINK: READLINK4res opreadlink; case OP_REMOVE: REMOVE4res opremove; case OP_RENAME: RENAME4res oprename; case OP_RENEW: RENEW4res oprenew; case OP_RESTOREFH: RESTOREFH4res oprestorefh; case OP_SAVEFH: SAVEFH4res opsavefh; #if 0 case OP_SECINFO: SECINFO4res opsecinfo; #endif case OP_SETATTR: SETATTR4res opsetattr; case OP_SETCLIENTID: SETCLIENTID4res opsetclientid; case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4res opsetclientid_confirm; case OP_VERIFY: VERIFY4res opverify; case OP_WRITE: WRITE4res opwrite; case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4res oprelease_lockowner; case OP_ILLEGAL: ILLEGAL4res opillegal; }; struct COMPOUND4args { utf8str_cs tag; uint32_t minorversion; nfs_argop4 argarray<>; }; struct COMPOUND4res { nfsstat4 status; utf8str_cs tag; nfs_resop4 resarray<>; }; /* * Remote file service routines */ program NFS4_PROGRAM { version NFS_V4 { void NFSPROC4_NULL(void) = 0; COMPOUND4res NFSPROC4_COMPOUND(COMPOUND4args) = 1; } = 4; } = 100003; /* * NFS4 Callback Procedure Definitions and Program */ /* * CB_GETATTR: Get Current Attributes */ struct CB_GETATTR4args { nfs_fh4 fh; bitmap4 attr_request; }; struct CB_GETATTR4resok { fattr4 obj_attributes; }; union CB_GETATTR4res switch (nfsstat4 status) { case NFS4_OK: CB_GETATTR4resok resok4; default: void; }; /* * CB_RECALL: Recall an Open Delegation */ struct CB_RECALL4args { stateid4 stateid; bool truncate; nfs_fh4 fh; }; struct CB_RECALL4res { nfsstat4 status; }; /* * CB_ILLEGAL: Response for illegal operation numbers */ struct CB_ILLEGAL4res { nfsstat4 status; }; /* * Various definitions for CB_COMPOUND */ enum nfs_cb_opnum4 { OP_CB_GETATTR = 3, OP_CB_RECALL = 4, OP_CB_ILLEGAL = 10044 }; union nfs_cb_argop4 switch (unsigned argop) { case OP_CB_GETATTR: CB_GETATTR4args opcbgetattr; case OP_CB_RECALL: CB_RECALL4args opcbrecall; case OP_CB_ILLEGAL: void; }; union nfs_cb_resop4 switch (unsigned resop){ case OP_CB_GETATTR: CB_GETATTR4res opcbgetattr; case OP_CB_RECALL: CB_RECALL4res opcbrecall; case OP_CB_ILLEGAL: CB_ILLEGAL4res opcbillegal; }; struct CB_COMPOUND4args { utf8str_cs tag; uint32_t minorversion; uint32_t callback_ident; nfs_cb_argop4 argarray<>; }; struct CB_COMPOUND4res { nfsstat4 status; utf8str_cs tag; nfs_cb_resop4 resarray<>; }; /* * Program number is in the transient range since the client * will assign the exact transient program number and provide * that to the server via the SETCLIENTID operation. */ program NFS4_CALLBACK { version NFS_CB { void CB_NULL(void) = 0; CB_COMPOUND4res CB_COMPOUND(CB_COMPOUND4args) = 1; } = 1; } = 0x40000000; libnfs-libnfs-4.0.0/nlm/000077500000000000000000000000001343063627400150415ustar00rootroot00000000000000libnfs-libnfs-4.0.0/nlm/CMakeLists.txt000066400000000000000000000001451343063627400176010ustar00rootroot00000000000000set(SOURCES libnfs-raw-nlm.c nlm.c) set(HEADERS libnfs-raw-nlm.h) core_add_library(nlm) libnfs-libnfs-4.0.0/nlm/Makefile.am000066400000000000000000000020471343063627400171000ustar00rootroot00000000000000noinst_LTLIBRARIES = libnlm.la nlm_SOURCES_GENERATED = nlm_HEADERS_GENERATED = nlm_GENERATED = $(nlm_SOURCES_GENERATED) $(nlm_HEADERS_GENERATED) CLEANFILES = $(nlm_GENERATED) nlm-stamp libnlm_la_CPPFLAGS = -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/win32 libnlm_la_SOURCES = \ $(nlm_SOURCES_GENERATED) \ nlm.c libnfs-raw-nlm.c libnfs-raw-nlm.h $(nlm_GENERATED) : nlm-stamp nlm-stamp : nlm.x rm -f $(nlm_GENERATED) touch nlm-stamp compile_rpc: cat nlm.x | head -29 >libnfs-raw-nlm.h rpcgen -h nlm.x | sed -e "s/#include /#include /" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/ CLIENT / void /g" -e "s/SVCXPRT /void /g" -e "s/bool_t/uint32_t/g" >> libnfs-raw-nlm.h cat nlm.x | head -29 >libnfs-raw-nlm.c rpcgen -c nlm.x | sed -e "s/#include \".*nlm.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nlm.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" -e "s/bool_t/uint32_t/g" >> libnfs-raw-nlm.c libnfs-libnfs-4.0.0/nlm/libnfs-raw-nlm.c000066400000000000000000000143261343063627400200430ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #include "libnfs-zdr.h" #include "libnfs-raw-nlm.h" uint32_t zdr_nlm_fh4 (ZDR *zdrs, nlm_fh4 *objp) { if (!zdr_bytes (zdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_nlm4_oh (ZDR *zdrs, nlm4_oh *objp) { if (!zdr_string (zdrs, objp, ~0)) return FALSE; return TRUE; } uint32_t zdr_nlm_cookie (ZDR *zdrs, nlm_cookie *objp) { if (!zdr_bytes (zdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_nlmstat4 (ZDR *zdrs, nlmstat4 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_nlm4_holder (ZDR *zdrs, nlm4_holder *objp) { if (!zdr_bool (zdrs, &objp->exclusive)) return FALSE; if (!zdr_u_int (zdrs, &objp->svid)) return FALSE; if (!zdr_nlm4_oh (zdrs, &objp->oh)) return FALSE; if (!zdr_uint64_t (zdrs, &objp->l_offset)) return FALSE; if (!zdr_uint64_t (zdrs, &objp->l_len)) return FALSE; return TRUE; } uint32_t zdr_nlm4_lock (ZDR *zdrs, nlm4_lock *objp) { if (!zdr_string (zdrs, &objp->caller_name, NLM_MAXNAME)) return FALSE; if (!zdr_nlm_fh4 (zdrs, &objp->fh)) return FALSE; if (!zdr_nlm4_oh (zdrs, &objp->oh)) return FALSE; if (!zdr_u_int (zdrs, &objp->svid)) return FALSE; if (!zdr_uint64_t (zdrs, &objp->l_offset)) return FALSE; if (!zdr_uint64_t (zdrs, &objp->l_len)) return FALSE; return TRUE; } uint32_t zdr_nlm4_share (ZDR *zdrs, nlm4_share *objp) { if (!zdr_string (zdrs, &objp->caller_name, NLM_MAXNAME)) return FALSE; if (!zdr_nlm_fh4 (zdrs, &objp->fh)) return FALSE; if (!zdr_nlm4_oh (zdrs, &objp->oh)) return FALSE; if (!zdr_u_int (zdrs, &objp->mode)) return FALSE; if (!zdr_u_int (zdrs, &objp->access)) return FALSE; return TRUE; } uint32_t zdr_nlm4_testres_denied (ZDR *zdrs, nlm4_testres_denied *objp) { if (!zdr_nlm4_holder (zdrs, &objp->holder)) return FALSE; return TRUE; } uint32_t zdr_nlm4_testreply (ZDR *zdrs, nlm4_testreply *objp) { if (!zdr_nlmstat4 (zdrs, &objp->status)) return FALSE; switch (objp->status) { case NLM4_DENIED: if (!zdr_nlm4_testres_denied (zdrs, &objp->nlm4_testreply_u.lock)) return FALSE; break; default: break; } return TRUE; } uint32_t zdr_NLM4_TESTres (ZDR *zdrs, NLM4_TESTres *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_nlm4_testreply (zdrs, &objp->reply)) return FALSE; return TRUE; } uint32_t zdr_NLM4_TESTargs (ZDR *zdrs, NLM4_TESTargs *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_bool (zdrs, &objp->exclusive)) return FALSE; if (!zdr_nlm4_lock (zdrs, &objp->lock)) return FALSE; return TRUE; } uint32_t zdr_NLM4_CANCres (ZDR *zdrs, NLM4_CANCres *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_nlmstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_NLM4_CANCargs (ZDR *zdrs, NLM4_CANCargs *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_bool (zdrs, &objp->block)) return FALSE; if (!zdr_bool (zdrs, &objp->exclusive)) return FALSE; if (!zdr_nlm4_lock (zdrs, &objp->lock)) return FALSE; return TRUE; } uint32_t zdr_NLM4_UNLOCKres (ZDR *zdrs, NLM4_UNLOCKres *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_nlmstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_NLM4_UNLOCKargs (ZDR *zdrs, NLM4_UNLOCKargs *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_nlm4_lock (zdrs, &objp->lock)) return FALSE; return TRUE; } uint32_t zdr_NLM4_LOCKres (ZDR *zdrs, NLM4_LOCKres *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_nlmstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } uint32_t zdr_NLM4_LOCKargs (ZDR *zdrs, NLM4_LOCKargs *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_bool (zdrs, &objp->block)) return FALSE; if (!zdr_bool (zdrs, &objp->exclusive)) return FALSE; if (!zdr_nlm4_lock (zdrs, &objp->lock)) return FALSE; if (!zdr_bool (zdrs, &objp->reclaim)) return FALSE; if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; } uint32_t zdr_NLM4_GRANTEDargs (ZDR *zdrs, NLM4_GRANTEDargs *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_bool (zdrs, &objp->exclusive)) return FALSE; if (!zdr_nlm4_lock (zdrs, &objp->lock)) return FALSE; return TRUE; } uint32_t zdr_NLM4_GRANTEDres (ZDR *zdrs, NLM4_GRANTEDres *objp) { if (!zdr_nlm_cookie (zdrs, &objp->cookie)) return FALSE; if (!zdr_nlmstat4 (zdrs, &objp->status)) return FALSE; return TRUE; } libnfs-libnfs-4.0.0/nlm/libnfs-raw-nlm.h000066400000000000000000000244461343063627400200540ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _NLM_H_RPCGEN #define _NLM_H_RPCGEN #include #ifdef __cplusplus extern "C" { #endif struct nlm_fh4 { struct { u_int data_len; char *data_val; } data; }; typedef struct nlm_fh4 nlm_fh4; typedef char *nlm4_oh; struct nlm_cookie { struct { u_int data_len; char *data_val; } data; }; typedef struct nlm_cookie nlm_cookie; enum nlmstat4 { NLM4_GRANTED = 0, NLM4_DENIED = 1, NLM4_DENIED_NOLOCKS = 2, NLM4_BLOCKED = 3, NLM4_DENIED_GRACE_PERIOD = 4, NLM4_DEADLCK = 5, NLM4_ROFS = 6, NLM4_STALE_FH = 7, NLM4_FBIG = 8, NLM4_FAILED = 9, }; typedef enum nlmstat4 nlmstat4; struct nlm4_holder { uint32_t exclusive; u_int svid; nlm4_oh oh; uint64_t l_offset; uint64_t l_len; }; typedef struct nlm4_holder nlm4_holder; #define NLM_MAXNAME 256 struct nlm4_lock { char *caller_name; struct nlm_fh4 fh; nlm4_oh oh; u_int svid; uint64_t l_offset; uint64_t l_len; }; typedef struct nlm4_lock nlm4_lock; struct nlm4_share { char *caller_name; struct nlm_fh4 fh; nlm4_oh oh; u_int mode; u_int access; }; typedef struct nlm4_share nlm4_share; struct nlm4_testres_denied { nlm4_holder holder; }; typedef struct nlm4_testres_denied nlm4_testres_denied; struct nlm4_testreply { nlmstat4 status; union { nlm4_testres_denied lock; } nlm4_testreply_u; }; typedef struct nlm4_testreply nlm4_testreply; struct NLM4_TESTres { nlm_cookie cookie; nlm4_testreply reply; }; typedef struct NLM4_TESTres NLM4_TESTres; struct NLM4_TESTargs { nlm_cookie cookie; uint32_t exclusive; nlm4_lock lock; }; typedef struct NLM4_TESTargs NLM4_TESTargs; struct NLM4_CANCres { nlm_cookie cookie; nlmstat4 status; }; typedef struct NLM4_CANCres NLM4_CANCres; struct NLM4_CANCargs { nlm_cookie cookie; uint32_t block; uint32_t exclusive; nlm4_lock lock; }; typedef struct NLM4_CANCargs NLM4_CANCargs; struct NLM4_UNLOCKres { nlm_cookie cookie; nlmstat4 status; }; typedef struct NLM4_UNLOCKres NLM4_UNLOCKres; struct NLM4_UNLOCKargs { nlm_cookie cookie; nlm4_lock lock; }; typedef struct NLM4_UNLOCKargs NLM4_UNLOCKargs; struct NLM4_LOCKres { nlm_cookie cookie; nlmstat4 status; }; typedef struct NLM4_LOCKres NLM4_LOCKres; struct NLM4_LOCKargs { nlm_cookie cookie; uint32_t block; uint32_t exclusive; nlm4_lock lock; uint32_t reclaim; int state; }; typedef struct NLM4_LOCKargs NLM4_LOCKargs; struct NLM4_GRANTEDargs { nlm_cookie cookie; uint32_t exclusive; nlm4_lock lock; }; typedef struct NLM4_GRANTEDargs NLM4_GRANTEDargs; struct NLM4_GRANTEDres { nlm_cookie cookie; nlmstat4 status; }; typedef struct NLM4_GRANTEDres NLM4_GRANTEDres; #define NLM_PROGRAM 100021 #define NLM_V4 4 #if defined(__STDC__) || defined(__cplusplus) #define NLM4_NULL 0 extern void * nlm4_null_4(void *, void *); extern void * nlm4_null_4_svc(void *, struct svc_req *); #define NLM4_TEST 1 extern NLM4_TESTres * nlm4_test_4(NLM4_TESTargs *, void *); extern NLM4_TESTres * nlm4_test_4_svc(NLM4_TESTargs *, struct svc_req *); #define NLM4_LOCK 2 extern NLM4_LOCKres * nlm4_lock_4(NLM4_LOCKargs *, void *); extern NLM4_LOCKres * nlm4_lock_4_svc(NLM4_LOCKargs *, struct svc_req *); #define NLM4_CANCEL 3 extern NLM4_CANCres * nlm4_cancel_4(NLM4_CANCargs *, void *); extern NLM4_CANCres * nlm4_cancel_4_svc(NLM4_CANCargs *, struct svc_req *); #define NLM4_UNLOCK 4 extern NLM4_UNLOCKres * nlm4_unlock_4(NLM4_UNLOCKargs *, void *); extern NLM4_UNLOCKres * nlm4_unlock_4_svc(NLM4_UNLOCKargs *, struct svc_req *); #define NLM4_GRANT 5 extern NLM4_GRANTEDres * nlm4_grant_4(NLM4_GRANTEDargs *, void *); extern NLM4_GRANTEDres * nlm4_grant_4_svc(NLM4_GRANTEDargs *, struct svc_req *); #define NLM4_TEST_MSG 6 extern void * nlm4_test_msg_4(NLM4_TESTargs *, void *); extern void * nlm4_test_msg_4_svc(NLM4_TESTargs *, struct svc_req *); #define NLM4_LOCK_MSG 7 extern void * nlm4_lock_msg_4(NLM4_LOCKargs *, void *); extern void * nlm4_lock_msg_4_svc(NLM4_LOCKargs *, struct svc_req *); #define NLM4_CANCEL_MSG 8 extern void * nlm4_cancel_msg_4(NLM4_CANCargs *, void *); extern void * nlm4_cancel_msg_4_svc(NLM4_CANCargs *, struct svc_req *); #define NLM4_UNLOCK_MSG 9 extern void * nlm4_unlock_msg_4(NLM4_UNLOCKargs *, void *); extern void * nlm4_unlock_msg_4_svc(NLM4_UNLOCKargs *, struct svc_req *); #define NLM4_GRANT_MSG 10 extern void * nlm4_grant_msg_4(NLM4_GRANTEDargs *, void *); extern void * nlm4_grant_msg_4_svc(NLM4_GRANTEDargs *, struct svc_req *); #define NLM4_TEST_RES 11 extern void * nlm4_test_res_4(NLM4_TESTres *, void *); extern void * nlm4_test_res_4_svc(NLM4_TESTres *, struct svc_req *); #define NLM4_LOCK_RES 12 extern void * nlm4_lock_res_4(NLM4_LOCKres *, void *); extern void * nlm4_lock_res_4_svc(NLM4_LOCKres *, struct svc_req *); #define NLM4_CANCEL_RES 13 extern void * nlm4_cancel_res_4(NLM4_CANCres *, void *); extern void * nlm4_cancel_res_4_svc(NLM4_CANCres *, struct svc_req *); #define NLM4_UNLOCK_RES 14 extern void * nlm4_unlock_res_4(NLM4_UNLOCKres *, void *); extern void * nlm4_unlock_res_4_svc(NLM4_UNLOCKres *, struct svc_req *); #define NLM4_GRANT_RES 15 extern void * nlm4_grant_res_4(NLM4_GRANTEDres *, void *); extern void * nlm4_grant_res_4_svc(NLM4_GRANTEDres *, struct svc_req *); extern int nlm_program_4_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define NLM4_NULL 0 extern void * nlm4_null_4(); extern void * nlm4_null_4_svc(); #define NLM4_TEST 1 extern NLM4_TESTres * nlm4_test_4(); extern NLM4_TESTres * nlm4_test_4_svc(); #define NLM4_LOCK 2 extern NLM4_LOCKres * nlm4_lock_4(); extern NLM4_LOCKres * nlm4_lock_4_svc(); #define NLM4_CANCEL 3 extern NLM4_CANCres * nlm4_cancel_4(); extern NLM4_CANCres * nlm4_cancel_4_svc(); #define NLM4_UNLOCK 4 extern NLM4_UNLOCKres * nlm4_unlock_4(); extern NLM4_UNLOCKres * nlm4_unlock_4_svc(); #define NLM4_GRANT 5 extern NLM4_GRANTEDres * nlm4_grant_4(); extern NLM4_GRANTEDres * nlm4_grant_4_svc(); #define NLM4_TEST_MSG 6 extern void * nlm4_test_msg_4(); extern void * nlm4_test_msg_4_svc(); #define NLM4_LOCK_MSG 7 extern void * nlm4_lock_msg_4(); extern void * nlm4_lock_msg_4_svc(); #define NLM4_CANCEL_MSG 8 extern void * nlm4_cancel_msg_4(); extern void * nlm4_cancel_msg_4_svc(); #define NLM4_UNLOCK_MSG 9 extern void * nlm4_unlock_msg_4(); extern void * nlm4_unlock_msg_4_svc(); #define NLM4_GRANT_MSG 10 extern void * nlm4_grant_msg_4(); extern void * nlm4_grant_msg_4_svc(); #define NLM4_TEST_RES 11 extern void * nlm4_test_res_4(); extern void * nlm4_test_res_4_svc(); #define NLM4_LOCK_RES 12 extern void * nlm4_lock_res_4(); extern void * nlm4_lock_res_4_svc(); #define NLM4_CANCEL_RES 13 extern void * nlm4_cancel_res_4(); extern void * nlm4_cancel_res_4_svc(); #define NLM4_UNLOCK_RES 14 extern void * nlm4_unlock_res_4(); extern void * nlm4_unlock_res_4_svc(); #define NLM4_GRANT_RES 15 extern void * nlm4_grant_res_4(); extern void * nlm4_grant_res_4_svc(); extern int nlm_program_4_freeresult (); #endif /* K&R C */ /* the zdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern uint32_t zdr_nlm_fh4 (ZDR *, nlm_fh4*); extern uint32_t zdr_nlm4_oh (ZDR *, nlm4_oh*); extern uint32_t zdr_nlm_cookie (ZDR *, nlm_cookie*); extern uint32_t zdr_nlmstat4 (ZDR *, nlmstat4*); extern uint32_t zdr_nlm4_holder (ZDR *, nlm4_holder*); extern uint32_t zdr_nlm4_lock (ZDR *, nlm4_lock*); extern uint32_t zdr_nlm4_share (ZDR *, nlm4_share*); extern uint32_t zdr_nlm4_testres_denied (ZDR *, nlm4_testres_denied*); extern uint32_t zdr_nlm4_testreply (ZDR *, nlm4_testreply*); extern uint32_t zdr_NLM4_TESTres (ZDR *, NLM4_TESTres*); extern uint32_t zdr_NLM4_TESTargs (ZDR *, NLM4_TESTargs*); extern uint32_t zdr_NLM4_CANCres (ZDR *, NLM4_CANCres*); extern uint32_t zdr_NLM4_CANCargs (ZDR *, NLM4_CANCargs*); extern uint32_t zdr_NLM4_UNLOCKres (ZDR *, NLM4_UNLOCKres*); extern uint32_t zdr_NLM4_UNLOCKargs (ZDR *, NLM4_UNLOCKargs*); extern uint32_t zdr_NLM4_LOCKres (ZDR *, NLM4_LOCKres*); extern uint32_t zdr_NLM4_LOCKargs (ZDR *, NLM4_LOCKargs*); extern uint32_t zdr_NLM4_GRANTEDargs (ZDR *, NLM4_GRANTEDargs*); extern uint32_t zdr_NLM4_GRANTEDres (ZDR *, NLM4_GRANTEDres*); #else /* K&R C */ extern uint32_t zdr_nlm_fh4 (); extern uint32_t zdr_nlm4_oh (); extern uint32_t zdr_nlm_cookie (); extern uint32_t zdr_nlmstat4 (); extern uint32_t zdr_nlm4_holder (); extern uint32_t zdr_nlm4_lock (); extern uint32_t zdr_nlm4_share (); extern uint32_t zdr_nlm4_testres_denied (); extern uint32_t zdr_nlm4_testreply (); extern uint32_t zdr_NLM4_TESTres (); extern uint32_t zdr_NLM4_TESTargs (); extern uint32_t zdr_NLM4_CANCres (); extern uint32_t zdr_NLM4_CANCargs (); extern uint32_t zdr_NLM4_UNLOCKres (); extern uint32_t zdr_NLM4_UNLOCKargs (); extern uint32_t zdr_NLM4_LOCKres (); extern uint32_t zdr_NLM4_LOCKargs (); extern uint32_t zdr_NLM4_GRANTEDargs (); extern uint32_t zdr_NLM4_GRANTEDres (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_NLM_H_RPCGEN */ libnfs-libnfs-4.0.0/nlm/nlm.c000066400000000000000000000113271343063627400157770ustar00rootroot00000000000000/* Copyright (C) 2012 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef WIN32 #include #endif/*WIN32*/ #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-nlm.h" int rpc_nlm4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NLM_PROGRAM, NLM_V4, NLM4_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nlm/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nlm/null call"); return -1; } return 0; } int rpc_nlm4_test_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_TESTargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NLM_PROGRAM, NLM_V4, NLM4_TEST, cb, private_data, (zdrproc_t)zdr_NLM4_TESTres, sizeof(NLM4_TESTres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nlm/test call"); return -1; } if (zdr_NLM4_TESTargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NLM4_TESTargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nlm/test call"); return -1; } return 0; } int rpc_nlm4_lock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_LOCKargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NLM_PROGRAM, NLM_V4, NLM4_LOCK, cb, private_data, (zdrproc_t)zdr_NLM4_LOCKres, sizeof(NLM4_LOCKres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nlm/lock call"); return -1; } if (zdr_NLM4_LOCKargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NLM4_LOCKargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nlm/lock call"); return -1; } return 0; } int rpc_nlm4_cancel_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_CANCargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NLM_PROGRAM, NLM_V4, NLM4_CANCEL, cb, private_data, (zdrproc_t)zdr_NLM4_CANCres, sizeof(NLM4_CANCres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nlm/cancel call"); return -1; } if (zdr_NLM4_CANCargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NLM4_CANCargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nlm/cancel call"); return -1; } return 0; } int rpc_nlm4_unlock_async(struct rpc_context *rpc, rpc_cb cb, struct NLM4_UNLOCKargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NLM_PROGRAM, NLM_V4, NLM4_UNLOCK, cb, private_data, (zdrproc_t)zdr_NLM4_UNLOCKres, sizeof(NLM4_UNLOCKres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nlm/unlock call"); return -1; } if (zdr_NLM4_UNLOCKargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NLM4_UNLOCKargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nlm/unlock call"); return -1; } return 0; } char *nlmstat4_to_str(int st) { enum nlmstat4 stat = st; char *str = "unknown nlm stat"; switch (stat) { case NLM4_GRANTED: str="NLM4_GRANTED";break; case NLM4_DENIED: str="NLM4_DENIED";break; case NLM4_DENIED_NOLOCKS: str="NLM4_DENIED_NOLOCKS";break; case NLM4_BLOCKED: str="NLM4_BLOCKED";break; case NLM4_DENIED_GRACE_PERIOD: str="NLM4_DENIED_GRACE_PERIOD";break; case NLM4_DEADLCK: str="NLM4_DEADLCK";break; case NLM4_ROFS: str="NLM4_ROFS";break; case NLM4_STALE_FH: str="NLM4_STALE_FH";break; case NLM4_FBIG: str="NLM4_FBIG";break; case NLM4_FAILED: str="NLM4_FAILED";break; } return str; } libnfs-libnfs-4.0.0/nlm/nlm.x000066400000000000000000000105761343063627400160310ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ struct nlm_fh4 { opaque data<>; }; typedef string nlm4_oh<>; struct nlm_cookie { opaque data<>; }; enum nlmstat4 { NLM4_GRANTED = 0, NLM4_DENIED = 1, NLM4_DENIED_NOLOCKS = 2, NLM4_BLOCKED = 3, NLM4_DENIED_GRACE_PERIOD = 4, NLM4_DEADLCK = 5, NLM4_ROFS = 6, NLM4_STALE_FH = 7, NLM4_FBIG = 8, NLM4_FAILED = 9 }; struct nlm4_holder { bool exclusive; unsigned int svid; nlm4_oh oh; uint64_t l_offset; uint64_t l_len; }; const NLM_MAXNAME = 256; struct nlm4_lock { string caller_name; struct nlm_fh4 fh; nlm4_oh oh; unsigned int svid; uint64_t l_offset; uint64_t l_len; }; struct nlm4_share { string caller_name; struct nlm_fh4 fh; nlm4_oh oh; unsigned int mode; unsigned int access; }; struct nlm4_testres_denied { nlm4_holder holder; }; union nlm4_testreply switch (nlmstat4 status) { case NLM4_DENIED: nlm4_testres_denied lock; default: void; }; struct NLM4_TESTres { nlm_cookie cookie; nlm4_testreply reply; }; struct NLM4_TESTargs { nlm_cookie cookie; bool exclusive; nlm4_lock lock; }; struct NLM4_CANCres { nlm_cookie cookie; nlmstat4 status; }; struct NLM4_CANCargs { nlm_cookie cookie; bool block; bool exclusive; nlm4_lock lock; }; struct NLM4_UNLOCKres { nlm_cookie cookie; nlmstat4 status; }; struct NLM4_UNLOCKargs { nlm_cookie cookie; nlm4_lock lock; }; struct NLM4_LOCKres { nlm_cookie cookie; nlmstat4 status; }; struct NLM4_LOCKargs { nlm_cookie cookie; bool block; bool exclusive; nlm4_lock lock; bool reclaim; int state; }; struct NLM4_GRANTEDargs { nlm_cookie cookie; bool exclusive; nlm4_lock lock; }; struct NLM4_GRANTEDres { nlm_cookie cookie; nlmstat4 status; }; program NLM_PROGRAM { version NLM_V4 { void NLM4_NULL(void) = 0; NLM4_TESTres NLM4_TEST(NLM4_TESTargs) = 1; NLM4_LOCKres NLM4_LOCK(NLM4_LOCKargs) = 2; NLM4_CANCres NLM4_CANCEL(NLM4_CANCargs) = 3; NLM4_UNLOCKres NLM4_UNLOCK(NLM4_UNLOCKargs) = 4; NLM4_GRANTEDres NLM4_GRANT(NLM4_GRANTEDargs) = 5; void NLM4_TEST_MSG(NLM4_TESTargs) = 6; void NLM4_LOCK_MSG(NLM4_LOCKargs) = 7; void NLM4_CANCEL_MSG(NLM4_CANCargs) = 8; void NLM4_UNLOCK_MSG(NLM4_UNLOCKargs) = 9; void NLM4_GRANT_MSG(NLM4_GRANTEDargs) = 10; void NLM4_TEST_RES(NLM4_TESTres) = 11; void NLM4_LOCK_RES(NLM4_LOCKres) = 12; void NLM4_CANCEL_RES(NLM4_CANCres) = 13; void NLM4_UNLOCK_RES(NLM4_UNLOCKres) = 14; void NLM4_GRANT_RES(NLM4_GRANTEDres) = 15; /* nlm4_shareres */ /* NLM4_SHARE(nlm4_shareargs) = 20; */ /* nlm4_shareres */ /* NLM4_UNSHARE(nlm4_shareargs) = 21; */ /* nlm4_res */ /* NLM4_NM_LOCK(nlm4_lockargs) = 22; */ /* void */ /* NLM4_FREE_ALL(nlm4_notify) = 23; */ } = 4; } = 100021; libnfs-libnfs-4.0.0/nsm/000077500000000000000000000000001343063627400150505ustar00rootroot00000000000000libnfs-libnfs-4.0.0/nsm/CMakeLists.txt000066400000000000000000000001451343063627400176100ustar00rootroot00000000000000set(SOURCES libnfs-raw-nsm.c nsm.c) set(HEADERS libnfs-raw-nsm.h) core_add_library(nsm) libnfs-libnfs-4.0.0/nsm/Makefile.am000066400000000000000000000020471343063627400171070ustar00rootroot00000000000000noinst_LTLIBRARIES = libnsm.la nsm_SOURCES_GENERATED = nsm_HEADERS_GENERATED = nsm_GENERATED = $(nsm_SOURCES_GENERATED) $(nsm_HEADERS_GENERATED) CLEANFILES = $(nsm_GENERATED) nsm-stamp libnsm_la_CPPFLAGS = -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/win32 libnsm_la_SOURCES = \ $(nsm_SOURCES_GENERATED) \ nsm.c libnfs-raw-nsm.c libnfs-raw-nsm.h $(nsm_GENERATED) : nsm-stamp nsm-stamp : nsm.x rm -f $(nsm_GENERATED) touch nsm-stamp compile_rpc: cat nsm.x | head -29 >libnfs-raw-nsm.h rpcgen -h nsm.x | sed -e "s/#include /#include /" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/ CLIENT / void /g" -e "s/SVCXPRT /void /g" -e "s/bool_t/uint32_t/g" >> libnfs-raw-nsm.h cat nsm.x | head -29 >libnfs-raw-nsm.c rpcgen -c nsm.x | sed -e "s/#include \".*nsm.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nsm.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" -e "s/bool_t/uint32_t/g" >> libnfs-raw-nsm.c libnfs-libnfs-4.0.0/nsm/libnfs-raw-nsm.c000066400000000000000000000073251343063627400200620ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #include "libnfs-zdr.h" #include "libnfs-raw-nsm.h" uint32_t zdr_nsmstat1 (ZDR *zdrs, nsmstat1 *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_nsm_my_id (ZDR *zdrs, nsm_my_id *objp) { if (!zdr_string (zdrs, &objp->my_name, NSM_MAXSTRLEN)) return FALSE; if (!zdr_int (zdrs, &objp->my_prog)) return FALSE; if (!zdr_int (zdrs, &objp->my_vers)) return FALSE; if (!zdr_int (zdrs, &objp->my_proc)) return FALSE; return TRUE; } uint32_t zdr_nsm_mon_id (ZDR *zdrs, nsm_mon_id *objp) { if (!zdr_string (zdrs, &objp->mon_name, NSM_MAXSTRLEN)) return FALSE; if (!zdr_nsm_my_id (zdrs, &objp->my_id)) return FALSE; return TRUE; } uint32_t zdr_NSM1_STATres (ZDR *zdrs, NSM1_STATres *objp) { if (!zdr_nsmstat1 (zdrs, &objp->res)) return FALSE; if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; } uint32_t zdr_NSM1_STATargs (ZDR *zdrs, NSM1_STATargs *objp) { if (!zdr_string (zdrs, &objp->mon_name, NSM_MAXSTRLEN)) return FALSE; return TRUE; } uint32_t zdr_NSM1_MONres (ZDR *zdrs, NSM1_MONres *objp) { if (!zdr_nsmstat1 (zdrs, &objp->res)) return FALSE; if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; } uint32_t zdr_NSM1_MONargs (ZDR *zdrs, NSM1_MONargs *objp) { if (!zdr_nsm_mon_id (zdrs, &objp->mon_id)) return FALSE; if (!zdr_opaque (zdrs, objp->priv, 16)) return FALSE; return TRUE; } uint32_t zdr_NSM1_UNMONres (ZDR *zdrs, NSM1_UNMONres *objp) { if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; } uint32_t zdr_NSM1_UNMONargs (ZDR *zdrs, NSM1_UNMONargs *objp) { if (!zdr_nsm_mon_id (zdrs, &objp->mon_id)) return FALSE; return TRUE; } uint32_t zdr_NSM1_UNMONALLres (ZDR *zdrs, NSM1_UNMONALLres *objp) { if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; } uint32_t zdr_NSM1_UNMONALLargs (ZDR *zdrs, NSM1_UNMONALLargs *objp) { if (!zdr_nsm_my_id (zdrs, &objp->my_id)) return FALSE; return TRUE; } uint32_t zdr_NSM1_NOTIFYargs (ZDR *zdrs, NSM1_NOTIFYargs *objp) { if (!zdr_string (zdrs, &objp->mon_name, NSM_MAXSTRLEN)) return FALSE; if (!zdr_int (zdrs, &objp->state)) return FALSE; return TRUE; } libnfs-libnfs-4.0.0/nsm/libnfs-raw-nsm.h000066400000000000000000000144521343063627400200660ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _NSM_H_RPCGEN #define _NSM_H_RPCGEN #include #ifdef __cplusplus extern "C" { #endif #define NSM_MAXSTRLEN 1024 enum nsmstat1 { NSM_STAT_SUCC = 0, NSM_STAT_FAIL = 1, }; typedef enum nsmstat1 nsmstat1; struct nsm_my_id { char *my_name; int my_prog; int my_vers; int my_proc; }; typedef struct nsm_my_id nsm_my_id; struct nsm_mon_id { char *mon_name; struct nsm_my_id my_id; }; typedef struct nsm_mon_id nsm_mon_id; struct NSM1_STATres { nsmstat1 res; int state; }; typedef struct NSM1_STATres NSM1_STATres; struct NSM1_STATargs { char *mon_name; }; typedef struct NSM1_STATargs NSM1_STATargs; struct NSM1_MONres { nsmstat1 res; int state; }; typedef struct NSM1_MONres NSM1_MONres; struct NSM1_MONargs { struct nsm_mon_id mon_id; char priv[16]; }; typedef struct NSM1_MONargs NSM1_MONargs; struct NSM1_UNMONres { int state; }; typedef struct NSM1_UNMONres NSM1_UNMONres; struct NSM1_UNMONargs { struct nsm_mon_id mon_id; }; typedef struct NSM1_UNMONargs NSM1_UNMONargs; struct NSM1_UNMONALLres { int state; }; typedef struct NSM1_UNMONALLres NSM1_UNMONALLres; struct NSM1_UNMONALLargs { struct nsm_my_id my_id; }; typedef struct NSM1_UNMONALLargs NSM1_UNMONALLargs; struct NSM1_NOTIFYargs { char *mon_name; int state; }; typedef struct NSM1_NOTIFYargs NSM1_NOTIFYargs; #define NSM_PROGRAM 100024 #define NSM_V1 1 #if defined(__STDC__) || defined(__cplusplus) #define NSM1_NULL 0 extern void * nsm1_null_1(void *, void *); extern void * nsm1_null_1_svc(void *, struct svc_req *); #define NSM1_STAT 1 extern struct NSM1_STATres * nsm1_stat_1(struct NSM1_STATargs *, void *); extern struct NSM1_STATres * nsm1_stat_1_svc(struct NSM1_STATargs *, struct svc_req *); #define NSM1_MON 2 extern struct NSM1_MONres * nsm1_mon_1(struct NSM1_MONargs *, void *); extern struct NSM1_MONres * nsm1_mon_1_svc(struct NSM1_MONargs *, struct svc_req *); #define NSM1_UNMON 3 extern struct NSM1_UNMONres * nsm1_unmon_1(struct NSM1_UNMONargs *, void *); extern struct NSM1_UNMONres * nsm1_unmon_1_svc(struct NSM1_UNMONargs *, struct svc_req *); #define NSM1_UNMON_ALL 4 extern struct NSM1_UNMONALLres * nsm1_unmon_all_1(struct NSM1_UNMONALLargs *, void *); extern struct NSM1_UNMONALLres * nsm1_unmon_all_1_svc(struct NSM1_UNMONALLargs *, struct svc_req *); #define NSM1_SIMU_CRASH 5 extern void * nsm1_simu_crash_1(void *, void *); extern void * nsm1_simu_crash_1_svc(void *, struct svc_req *); #define NSM1_NOTIFY 6 extern void * nsm1_notify_1(struct NSM1_NOTIFYargs *, void *); extern void * nsm1_notify_1_svc(struct NSM1_NOTIFYargs *, struct svc_req *); extern int nsm_program_1_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define NSM1_NULL 0 extern void * nsm1_null_1(); extern void * nsm1_null_1_svc(); #define NSM1_STAT 1 extern struct NSM1_STATres * nsm1_stat_1(); extern struct NSM1_STATres * nsm1_stat_1_svc(); #define NSM1_MON 2 extern struct NSM1_MONres * nsm1_mon_1(); extern struct NSM1_MONres * nsm1_mon_1_svc(); #define NSM1_UNMON 3 extern struct NSM1_UNMONres * nsm1_unmon_1(); extern struct NSM1_UNMONres * nsm1_unmon_1_svc(); #define NSM1_UNMON_ALL 4 extern struct NSM1_UNMONALLres * nsm1_unmon_all_1(); extern struct NSM1_UNMONALLres * nsm1_unmon_all_1_svc(); #define NSM1_SIMU_CRASH 5 extern void * nsm1_simu_crash_1(); extern void * nsm1_simu_crash_1_svc(); #define NSM1_NOTIFY 6 extern void * nsm1_notify_1(); extern void * nsm1_notify_1_svc(); extern int nsm_program_1_freeresult (); #endif /* K&R C */ /* the zdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern uint32_t zdr_nsmstat1 (ZDR *, nsmstat1*); extern uint32_t zdr_nsm_my_id (ZDR *, nsm_my_id*); extern uint32_t zdr_nsm_mon_id (ZDR *, nsm_mon_id*); extern uint32_t zdr_NSM1_STATres (ZDR *, NSM1_STATres*); extern uint32_t zdr_NSM1_STATargs (ZDR *, NSM1_STATargs*); extern uint32_t zdr_NSM1_MONres (ZDR *, NSM1_MONres*); extern uint32_t zdr_NSM1_MONargs (ZDR *, NSM1_MONargs*); extern uint32_t zdr_NSM1_UNMONres (ZDR *, NSM1_UNMONres*); extern uint32_t zdr_NSM1_UNMONargs (ZDR *, NSM1_UNMONargs*); extern uint32_t zdr_NSM1_UNMONALLres (ZDR *, NSM1_UNMONALLres*); extern uint32_t zdr_NSM1_UNMONALLargs (ZDR *, NSM1_UNMONALLargs*); extern uint32_t zdr_NSM1_NOTIFYargs (ZDR *, NSM1_NOTIFYargs*); #else /* K&R C */ extern uint32_t zdr_nsmstat1 (); extern uint32_t zdr_nsm_my_id (); extern uint32_t zdr_nsm_mon_id (); extern uint32_t zdr_NSM1_STATres (); extern uint32_t zdr_NSM1_STATargs (); extern uint32_t zdr_NSM1_MONres (); extern uint32_t zdr_NSM1_MONargs (); extern uint32_t zdr_NSM1_UNMONres (); extern uint32_t zdr_NSM1_UNMONargs (); extern uint32_t zdr_NSM1_UNMONALLres (); extern uint32_t zdr_NSM1_UNMONALLargs (); extern uint32_t zdr_NSM1_NOTIFYargs (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_NSM_H_RPCGEN */ libnfs-libnfs-4.0.0/nsm/nsm.c000066400000000000000000000127511343063627400160170ustar00rootroot00000000000000/* Copyright (C) 2013 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef WIN32 #include #endif/*WIN32*/ #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-nsm.h" int rpc_nsm1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/null call"); return -1; } return 0; } int rpc_nsm1_stat_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_STATargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_STAT, cb, private_data, (zdrproc_t)zdr_NSM1_STATres, sizeof(NSM1_STATres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/stat call"); return -1; } if (zdr_NSM1_STATargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_STATargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/stat call"); return -1; } return 0; } int rpc_nsm1_mon_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_MONargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_MON, cb, private_data, (zdrproc_t)zdr_NSM1_MONres, sizeof(NSM1_MONres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/mon call"); return -1; } if (zdr_NSM1_MONargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_MONargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/mon call"); return -1; } return 0; } int rpc_nsm1_unmon_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_UNMONargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_UNMON, cb, private_data, (zdrproc_t)zdr_NSM1_UNMONres, sizeof(NSM1_UNMONres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/unmon call"); return -1; } if (zdr_NSM1_UNMONargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_UNMONargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/unmon call"); return -1; } return 0; } int rpc_nsm1_unmonall_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_UNMONALLargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_UNMON_ALL, cb, private_data, (zdrproc_t)zdr_NSM1_UNMONALLres, sizeof(NSM1_UNMONALLres)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/unmonall call"); return -1; } if (zdr_NSM1_UNMONALLargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_UNMONALLargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/unmonall call"); return -1; } return 0; } int rpc_nsm1_simucrash_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_SIMU_CRASH, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/simucrash call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/simucrash call"); return -1; } return 0; } int rpc_nsm1_notify_async(struct rpc_context *rpc, rpc_cb cb, struct NSM1_NOTIFYargs *args, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, NSM_PROGRAM, NSM_V1, NSM1_NOTIFY, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nsm/notify call"); return -1; } if (zdr_NSM1_NOTIFYargs(&pdu->zdr, args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode NSM1_NOTIFYargs"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nsm/notify call"); return -1; } return 0; } char *nsmstat1_to_str(int st) { enum nsmstat1 stat = st; char *str = "unknown n1m stat"; switch (stat) { case NSM_STAT_SUCC: str="NSM_STAT_SUCC";break; case NSM_STAT_FAIL: str="NSM_STAT_FAIL";break; } return str; } libnfs-libnfs-4.0.0/nsm/nsm.x000066400000000000000000000064011343063627400160370ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * This defines the maximum length of the string * identifying the caller. */ const NSM_MAXSTRLEN = 1024; enum nsmstat1 { NSM_STAT_SUCC = 0, /* NSM agrees to monitor. */ NSM_STAT_FAIL = 1 /* NSM cannot monitor. */ }; struct nsm_my_id { string my_name; /* hostname */ int my_prog; /* RPC program number */ int my_vers; /* program version number */ int my_proc; /* procedure number */ }; struct nsm_mon_id { string mon_name; /* name of the host to be monitored */ struct nsm_my_id my_id; }; struct NSM1_STATres { nsmstat1 res; int state; }; struct NSM1_STATargs { string mon_name; }; struct NSM1_MONres { nsmstat1 res; int state; }; struct NSM1_MONargs { struct nsm_mon_id mon_id; opaque priv[16]; /* private information */ }; struct NSM1_UNMONres { int state; /* state number of NSM */ }; struct NSM1_UNMONargs { struct nsm_mon_id mon_id; }; struct NSM1_UNMONALLres { int state; /* state number of NSM */ }; struct NSM1_UNMONALLargs { struct nsm_my_id my_id; }; struct NSM1_NOTIFYargs { string mon_name; int state; }; /* * Protocol description for the NSM program. */ program NSM_PROGRAM { version NSM_V1 { void NSM1_NULL(void) = 0; struct NSM1_STATres NSM1_STAT(struct NSM1_STATargs) = 1; struct NSM1_MONres NSM1_MON(struct NSM1_MONargs) = 2; struct NSM1_UNMONres NSM1_UNMON(struct NSM1_UNMONargs) = 3; struct NSM1_UNMONALLres NSM1_UNMON_ALL(struct NSM1_UNMONALLargs) = 4; void NSM1_SIMU_CRASH(void) = 5; void NSM1_NOTIFY(struct NSM1_NOTIFYargs) = 6; } = 1; } = 100024; libnfs-libnfs-4.0.0/packaging/000077500000000000000000000000001343063627400161775ustar00rootroot00000000000000libnfs-libnfs-4.0.0/packaging/RPM/000077500000000000000000000000001343063627400166355ustar00rootroot00000000000000libnfs-libnfs-4.0.0/packaging/RPM/libnfs.spec.in000066400000000000000000000241221343063627400213740ustar00rootroot00000000000000Name: libnfs Summary: NFS client library Vendor: Ronnie Sahlberg Packager: ronniesahlberg@gmail.com Version: @VERSION@ Release: 1 Epoch: 0 License: GNU LGPL version 2.1 Group: System Environment/Libraries URL: http://www.github.com/sahlberg/libnfs Source: libnfs-%{version}.tar.gz Provides: lib = %{version} Prefix: /usr BuildRoot: %{_tmppath}/%{name}-%{version}-root %description LibNFS is a NFS client library ####################################################################### %prep %setup -q # setup the init script and sysconfig file %setup -T -D -n libnfs-%{version} -q %build ## check for ccache if ccache -h >/dev/null 2>&1 ; then CC="ccache gcc" else CC="gcc" fi export CC ## always run autogen.sh aclocal autoheader autoconf libtoolize -c -f -i automake --add-missing CFLAGS="$RPM_OPT_FLAGS $EXTRA -O2 -g -D_GNU_SOURCE" %configure %install # Clean up in case there is trash left from a previous build rm -rf $RPM_BUILD_ROOT # Create the target build directory hierarchy make DESTDIR=$RPM_BUILD_ROOT install # Remove "*.old" files find $RPM_BUILD_ROOT -name "*.old" -exec rm -f {} \; %clean rm -rf $RPM_BUILD_ROOT ####################################################################### ## Files section ## ####################################################################### %files %defattr(-,root,root) %{_libdir}/libnfs.so* %package devel Summary: Development libraries for LibNFS Group: Development %description devel development libraries for LibNFS %files devel %defattr(-,root,root) %{_includedir}/nfsc/libnfs.h %{_includedir}/nfsc/libnfs-zdr.h %{_includedir}/nfsc/libnfs-raw.h %{_includedir}/nfsc/libnfs-raw-mount.h %{_includedir}/nfsc/libnfs-raw-nfs.h %{_includedir}/nfsc/libnfs-raw-nfs4.h %{_includedir}/nfsc/libnfs-raw-portmap.h %{_includedir}/nfsc/libnfs-raw-rquota.h %{_includedir}/nfsc/libnfs-raw-nlm.h %{_includedir}/nfsc/libnfs-raw-nsm.h %{_libdir}/libnfs.a %{_libdir}/libnfs.la %{_libdir}/pkgconfig/libnfs.pc %package utils Summary: Utility programs for LibNFS Group: Applications/System %description utils Utility programs for LibNFS %files utils %defattr(-,root,root) %{_bindir}/nfs-cat %{_bindir}/nfs-cp %{_bindir}/nfs-ls %{_mandir}/man1/nfs-cat.1.gz %{_mandir}/man1/nfs-cp.1.gz %{_mandir}/man1/nfs-ls.1.gz %changelog * Wed Feb 13 2019 : Version 4.0.0 - Fix the versioning in makerpms.sh - Fix some compile issues in the test programs. - NFSv3: skip commit on close if the file has not been written to. - Add nfs_umount() to NFSv3 - Add nfs_statvfs64() - Fix invalid shift of pid_t when generating rpc->xid - Compile fixes for Mac OSX - Fix for dup2() on Windows - NFSv4 fix for directory handling - Improvements to configure/bulding * Sun Jun 24 2018 : Version 3.0.0 - NFSv4 support. - lockf() support (NFSv4 only). - fcntl() support for locking (NFSv4 only). - Add CMake support. - URL arguments to select NFS version. - URL argument to set nfsport. This allows NFSv4 to work for servers without portmapper support. - URL argument to set he mount port. - NFSv4: use getpwnam to map NFSv4 (Ganesha) when passing uid/gid as a user/group name insead of as a uid/gid. - Added nfs-fh: a simle utility to print the filehandle for a nfs file. - Win32 build fixes. - Add a new open2() function that takes a mode argument. - Add a testsuite for libnfs. * Fri Jun 16 2017 : Version 2.0.0 - Add RPC/RAW layer support for NFSv4 - Add support for building RPC servers using libnfs - Add support for setting RPC timeouts for all interfaces. - Add O_NOFOLLOW to nfs_open() - Add a new mkdir2 command that also takes a mode argument. - Add a new readlink2 command that avoids having to preallocate the output buffer. - Build fixes for Mingw and Cygwin. - Use SOCK_CLOEXEC for the sockets - Make rpc_set{g|u}id() public - Performance optimization: socket: Batch pdu read in rpc_read_from_socket - Fix NULL pointer crash in nfs_link(). - Clamp read/write size for servers (Ganesha) that offer very large io sizes instead of failing to connect to the export. - Tell the server to commit all data to stable storage when we close files. - Double free fix: don't call rpc_free_pdu() after rpc_queue_pdu() failure. - Fix for memory leak in rpc_allocate_*(). - Fixes to build nfs-ls and nfs-cp on win32. - Abort the mount process correctly if MOUNT/MNT returns error or is cancelled. - Fix memory leak in error path in nfs_create_2_cb(). - Fix leak of rpc->inbuf if we destroy the context while we still have PDUs in flight. * Sun Oct 9 2016 : Version 1.11.0 - Reduce the number of memory allocations in the ZDR layer. - Check both seconds and nanoseconds field when validating dir cache. - Invalidate the dir cache immediately if we do something that would cause it to become stale, such as adding/removing objects from the cache. - Add options to enable/disable dir caching. - Discard readahead cache on [p]write and truncate. - Android fixes - Windows fixes - Support timeouts for sync functions - Add an internal pagecache - Add nfs_rewinddir(), nfs_seekdir() and nfs_telldir() - Fix crash in nfs_truncate() - Fix segfault that can trigger if we rpc_disconnect() during the mount. - Add support to bind to a specific interface (linux only) * Sun Jan 31 2016 : Version 1.10.0 - Fix a leak where we leaked one rdpe_cb_data structure on each open_dir() - Make building the utils optional - Android: the correct define is __ANDROID__ not ANDROID - Win32: Use _U_ instead of ATTRIBURE((unused)) - Win32: Fix nfs_stat declaration for Win32 - Various fixes for mingw builds - Make rpc->connect_cb a one shot callback and improve documentation - Remove the FUSE module. It now lives in its own repo - Fix POLLERR/POLLHUP handling to properly handle session failures and to try to auto-reconnect * Sun Aug 2 2015 : Version 1.9.8 - Disable multithreading in fuse_nfs - Add -Wall and -Werror compiler flags (and fix issues found by it) - Add nfs-cat utility - Switch to using nfs_[f]stat64 instead of the deprecated nfs_[f]stat call in all examples - If the server does not return any atttributes for entries in READDIRPLUS then try to fetch them using lookup instead. - Reconnection fixes - Enforce the max pdu size and add sanity checks when reading PDUs from the socket. - Stop using ioctl(FIONREAD) to find out how many bytes to read, and treat 0 as an indication of a problem. Some applications call their POLLIN handlers spuriosly even when there is no data to read, which breaks this check in libnfs. - Add basic support to do logging. * Mon Feb 9 2015 : Version 1.9.7 - Auto-traverse mounts. With this option (default to on) libnfs will autodiscover and handle any nested submounts. - Remove nfs_get_current_offset. Applications should use seek instead of this function. - Add umask() support. - Change set_tcp_sockopt() to be static. - Android fix for nfs-ls - Make S_IFLNK available on windows. - Fix a use after free. - Fix a bug where truncate() treated offset as 32bit. * Tue Nov 25 2014 : Version 1.9.6 - Add O_TRUNC support for nfs_create - Handle OOM during create - Return more stats fields as part of readdir since we get these for "free" when we use READDIRPLUS - Follow symlinks during path resolution - Add lchown, lstat and lutimes - Replace all [u_]quad types with [u]int types in our RPC layer - Solaris build fixes * Sat Jul 19 2014 : Version 1.9.5 - Remove old ONC-RPC symbols * Wed Mar 19 2014 : Version 1.9.3 - Add O_TRUNC support to nfs_open() - Add a simple but incomplete LD_PRELOAD tool - Fixes for some memory leaks and C++ compile support - Make ANDROID default uid/gid to 65534 - Allow the READDIRPLUS emulation to still work if some objects in the direcotry can not be lookedup (NFSv4 ACL denying READ-ATTRIBUTES) - Have libnfs retry any read/write operations where the server responds with a short read/write. Some servers do this when they are overloaded? * Thu Jan 30 2014 : Version 1.9.2 - Remove chdir change. This needs more testing. * Tue Jan 28 2014 : Version 1.9.1 - Restore libnfs-raw-*.h to make install * Mon Jan 27 2014 : Version 1.9 - Use _stat64 on windows so file sizes become 64bit always. - Increase default marshalling buffer so we can marshall large PDUs. - RPC layer support for NFSv2 - Win32 updates and fixes - Add URL parsing functions and URL argument support. - New utility: nfs-io - nfs-ls enhancements - RPC layer support for NSM - Add example FUSE filesystem. - Minor fixes. * Wed Oct 30 2013 : Version 1.8 - Fix nasty memory leak in read_from_socket - minor updates * Sun Oct 20 2013 : Version 1.7 - Allow nested eventloops so that a sync function can be called from a callback. - Fix a bug in unmarshalling a uint64. - Add PATHCONF support. - WIN32/64 updates - AROS updates * Mon May 27 2013 : Version 1.6 - AROS/Amiga support - Chose better initial xid value to reduce the probability for collissions. - Set default group to getgid() instead of -1. This fixes an interoperability problem with 3.9 linux knfsd. * Mon Dec 3 2012 : Version 1.5 - Switch to using our own RPC/XDR replacement ZDR instead of relying on the system RPC/TIRPC libraries. This allows using libnfs on platforms that lack RPC libraries completely. - Add support for Android. * Sun Nov 25 2012 : Version 1.4 - Add trackig of freed context and assert on using a context after it has been freed. - Windows x64 support and fixes. - Switch to using our own version of xdr_int64() since the one in libtirpc crashes on some platforms. - Fix memory leak in an error path for addrinfo. - Fix bug dereferencing a null pointer in the mount callback on error. * Sat Mar 3 2012 : Version 1.3 - add set/unset to portmapper - add mount v1 - try to rotate to find a free port better - minor fixes * Tue Dec 6 2011 : Version 1.2 - Add support for MKNOD - Add support for HaneWin NFS server - Change all [s]size_t offset_t to be 64bit clean scalars * Sun Nov 27 2011 : Version 1.1 - Fix definition and use of AUTH - Only call the "connect" callback if non-NULL - make sure the callback for connect is only invoked once for the sync api - make file offset bits 64 bits always * Sun Jul 31 2011 : Version 1.0 - Initial version libnfs-libnfs-4.0.0/packaging/RPM/makerpms.sh000077500000000000000000000056521343063627400210230ustar00rootroot00000000000000#!/bin/sh # # makerpms.sh - build RPM packages from the git sources # # Copyright (C) John H Terpstra 1998-2002 # Copyright (C) Gerald (Jerry) Carter 2003 # Copyright (C) Jim McDonough 2007 # Copyright (C) Andrew Tridgell 2007 # Copyright (C) Michael Adam 2008-2009 # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation; either version 3 of the License, or (at your option) # any later version. # # This program 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 General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # this program; if not, see . # # # The following allows environment variables to override the target directories # the alternative is to have a file in your home directory calles .rpmmacros # containing the following: # %_topdir /home/mylogin/redhat # # Note: Under this directory rpm expects to find the same directories that are under the # /usr/src/redhat directory # EXTRA_OPTIONS="$1" DIRNAME=$(dirname $0) TOPDIR=${DIRNAME}/../.. SPECDIR=`rpm --eval %_specdir` SRCDIR=`rpm --eval %_sourcedir` SPECFILE="libnfs.spec" SPECFILE_IN="libnfs.spec.in" RPMBUILD="rpmbuild" # We use tags and determine the version, as follows: # libnfs-0.9.1 (First release of 0.9). # libnfs-0.9.23 (23rd minor release of the 112 version) # # If we're not directly on a tag, this is a devel release; we append # .0...devel to the release. TAG=`git describe --tags` case "$TAG" in libnfs-*) TAG=${TAG##libnfs-} case "$TAG" in *-*-g*) # 0.9-168-ge6cf0e8 # Not exactly on tag: devel version. VERSION=`echo "$TAG" | sed 's/\([^-]\+\)-\([0-9]\+\)-\(g[0-9a-f]\+\)/\1.0.\2.\3.devel/'` ;; *) # An actual release version VERSION=$TAG ;; esac ;; *) echo Invalid tag "$TAG" >&2 exit 1 ;; esac sed -e s/@VERSION@/$VERSION/g \ < ${DIRNAME}/${SPECFILE_IN} \ > ${DIRNAME}/${SPECFILE} VERSION=$(grep ^Version ${DIRNAME}/${SPECFILE} | sed -e 's/^Version:\ \+//') if echo | gzip -c --rsyncable - > /dev/null 2>&1 ; then GZIP="gzip -9 --rsyncable" else GZIP="gzip -9" fi pushd ${TOPDIR} echo -n "Creating libnfs-${VERSION}.tar.gz ... " git archive --prefix=libnfs-${VERSION}/ HEAD | ${GZIP} > ${SRCDIR}/libnfs-${VERSION}.tar.gz RC=$? popd echo "Done." if [ $RC -ne 0 ]; then echo "Build failed!" exit 1 fi # At this point the SPECDIR and SRCDIR vaiables must have a value! ## ## copy additional source files ## cp -p ${DIRNAME}/${SPECFILE} ${SPECDIR} ## ## Build ## echo "$(basename $0): Getting Ready to build release package" ${RPMBUILD} -ba --clean --rmsource ${EXTRA_OPTIONS} ${SPECDIR}/${SPECFILE} || exit 1 echo "$(basename $0): Done." exit 0 libnfs-libnfs-4.0.0/portmap/000077500000000000000000000000001343063627400157355ustar00rootroot00000000000000libnfs-libnfs-4.0.0/portmap/CMakeLists.txt000066400000000000000000000001651343063627400204770ustar00rootroot00000000000000set(SOURCES libnfs-raw-portmap.c portmap.c) set(HEADERS libnfs-raw-portmap.h) core_add_library(portmap) libnfs-libnfs-4.0.0/portmap/Makefile.am000066400000000000000000000022441343063627400177730ustar00rootroot00000000000000noinst_LTLIBRARIES = libportmap.la portmap_SOURCES_GENERATED = portmap_HEADERS_GENERATED = portmap_GENERATED = $(portmap_SOURCES_GENERATED) $(portmap_HEADERS_GENERATED) CLEANFILES = $(portmap_GENERATED) portmap-stamp libportmap_la_CPPFLAGS = -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/win32 libportmap_la_SOURCES = \ $(portmap_SOURCES_GENERATED) \ portmap.c libnfs-raw-portmap.c libnfs-raw-portmap.h $(portmap_GENERATED) : portmap-stamp portmap-stamp : portmap.x rm -f $(portmap_GENERATED) touch portmap-stamp compile_rpc: cat portmap.x | head -29 >libnfs-raw-portmap.h rpcgen -h portmap.x | sed -e "s/#include /#include /" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/ CLIENT / void /g" -e "s/SVCXPRT /void /g" -e "s/bool_t/uint32_t/g" >> libnfs-raw-portmap.h cat portmap.x | head -29 >libnfs-raw-portmap.c rpcgen -c portmap.x | sed -e "s/#include \".*portmap.h\"/#include \"libnfs-zdr.h\"\n#include \"libnfs-raw-portmap.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;//" -e "s/bool_t/uint32_t/g" -e "s/[ \t]*buf = / int32_t *buf;\n buf = /" >> libnfs-raw-portmap.c libnfs-libnfs-4.0.0/portmap/libnfs-raw-portmap.c000066400000000000000000000246251343063627400216360ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #include "libnfs-zdr.h" #include "libnfs-raw-portmap.h" uint32_t zdr_pmap2_mapping (ZDR *zdrs, pmap2_mapping *objp) { if (zdrs->x_op == ZDR_ENCODE) { int32_t *buf; buf = ZDR_INLINE (zdrs, 4 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->prot)) return FALSE; if (!zdr_u_int (zdrs, &objp->port)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->prog); IZDR_PUT_U_LONG(buf, objp->vers); IZDR_PUT_U_LONG(buf, objp->prot); IZDR_PUT_U_LONG(buf, objp->port); } return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { int32_t *buf; buf = ZDR_INLINE (zdrs, 4 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->prot)) return FALSE; if (!zdr_u_int (zdrs, &objp->port)) return FALSE; } else { objp->prog = IZDR_GET_U_LONG(buf); objp->vers = IZDR_GET_U_LONG(buf); objp->prot = IZDR_GET_U_LONG(buf); objp->port = IZDR_GET_U_LONG(buf); } return TRUE; } if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->prot)) return FALSE; if (!zdr_u_int (zdrs, &objp->port)) return FALSE; return TRUE; } uint32_t zdr_pmap2_call_args (ZDR *zdrs, pmap2_call_args *objp) { if (zdrs->x_op == ZDR_ENCODE) { int32_t *buf; buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->proc)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->prog); IZDR_PUT_U_LONG(buf, objp->vers); IZDR_PUT_U_LONG(buf, objp->proc); } if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) return FALSE; return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { int32_t *buf; buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->proc)) return FALSE; } else { objp->prog = IZDR_GET_U_LONG(buf); objp->vers = IZDR_GET_U_LONG(buf); objp->proc = IZDR_GET_U_LONG(buf); } if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) return FALSE; return TRUE; } if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->proc)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_pmap2_call_result (ZDR *zdrs, pmap2_call_result *objp) { if (!zdr_u_int (zdrs, &objp->port)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->res.res_val, (u_int *) &objp->res.res_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_pmap2_mapping_list (ZDR *zdrs, pmap2_mapping_list *objp) { if (!zdr_pmap2_mapping (zdrs, &objp->map)) return FALSE; if (!zdr_pointer (zdrs, (char **)&objp->next, sizeof (pmap2_mapping_list), (zdrproc_t) zdr_pmap2_mapping_list)) return FALSE; return TRUE; } uint32_t zdr_pmap2_dump_result (ZDR *zdrs, pmap2_dump_result *objp) { if (!zdr_pointer (zdrs, (char **)&objp->list, sizeof (pmap2_mapping_list), (zdrproc_t) zdr_pmap2_mapping_list)) return FALSE; return TRUE; } uint32_t zdr_pmap3_string_result (ZDR *zdrs, pmap3_string_result *objp) { if (!zdr_string (zdrs, &objp->addr, ~0)) return FALSE; return TRUE; } uint32_t zdr_pmap3_mapping (ZDR *zdrs, pmap3_mapping *objp) { if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_string (zdrs, &objp->netid, ~0)) return FALSE; if (!zdr_string (zdrs, &objp->addr, ~0)) return FALSE; if (!zdr_string (zdrs, &objp->owner, ~0)) return FALSE; return TRUE; } uint32_t zdr_pmap3_mapping_list (ZDR *zdrs, pmap3_mapping_list *objp) { if (!zdr_pmap3_mapping (zdrs, &objp->map)) return FALSE; if (!zdr_pointer (zdrs, (char **)&objp->next, sizeof (pmap3_mapping_list), (zdrproc_t) zdr_pmap3_mapping_list)) return FALSE; return TRUE; } uint32_t zdr_pmap3_dump_result (ZDR *zdrs, pmap3_dump_result *objp) { if (!zdr_pointer (zdrs, (char **)&objp->list, sizeof (pmap3_mapping_list), (zdrproc_t) zdr_pmap3_mapping_list)) return FALSE; return TRUE; } uint32_t zdr_pmap3_call_args (ZDR *zdrs, pmap3_call_args *objp) { if (zdrs->x_op == ZDR_ENCODE) { int32_t *buf; buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->proc)) return FALSE; } else { IZDR_PUT_U_LONG(buf, objp->prog); IZDR_PUT_U_LONG(buf, objp->vers); IZDR_PUT_U_LONG(buf, objp->proc); } if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) return FALSE; return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { int32_t *buf; buf = ZDR_INLINE (zdrs, 3 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->proc)) return FALSE; } else { objp->prog = IZDR_GET_U_LONG(buf); objp->vers = IZDR_GET_U_LONG(buf); objp->proc = IZDR_GET_U_LONG(buf); } if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) return FALSE; return TRUE; } if (!zdr_u_int (zdrs, &objp->prog)) return FALSE; if (!zdr_u_int (zdrs, &objp->vers)) return FALSE; if (!zdr_u_int (zdrs, &objp->proc)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->args.args_val, (u_int *) &objp->args.args_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_pmap3_call_result (ZDR *zdrs, pmap3_call_result *objp) { if (!zdr_u_int (zdrs, &objp->port)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->res.res_val, (u_int *) &objp->res.res_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_pmap3_netbuf (ZDR *zdrs, pmap3_netbuf *objp) { if (!zdr_u_int (zdrs, &objp->maxlen)) return FALSE; if (!zdr_bytes (zdrs, (char **)&objp->buf.buf_val, (u_int *) &objp->buf.buf_len, ~0)) return FALSE; return TRUE; } uint32_t zdr_PMAP2SETargs (ZDR *zdrs, PMAP2SETargs *objp) { if (!zdr_pmap2_mapping (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP2UNSETargs (ZDR *zdrs, PMAP2UNSETargs *objp) { if (!zdr_pmap2_mapping (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP2GETPORTargs (ZDR *zdrs, PMAP2GETPORTargs *objp) { if (!zdr_pmap2_mapping (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP2CALLITargs (ZDR *zdrs, PMAP2CALLITargs *objp) { if (!zdr_pmap2_call_args (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP2CALLITres (ZDR *zdrs, PMAP2CALLITres *objp) { if (!zdr_pmap2_call_result (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP2DUMPres (ZDR *zdrs, PMAP2DUMPres *objp) { if (!zdr_pmap2_dump_result (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3SETargs (ZDR *zdrs, PMAP3SETargs *objp) { if (!zdr_pmap3_mapping (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3UNSETargs (ZDR *zdrs, PMAP3UNSETargs *objp) { if (!zdr_pmap3_mapping (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3GETADDRargs (ZDR *zdrs, PMAP3GETADDRargs *objp) { if (!zdr_pmap3_mapping (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3GETADDRres (ZDR *zdrs, PMAP3GETADDRres *objp) { if (!zdr_pmap3_string_result (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3DUMPres (ZDR *zdrs, PMAP3DUMPres *objp) { if (!zdr_pmap3_dump_result (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3CALLITargs (ZDR *zdrs, PMAP3CALLITargs *objp) { if (!zdr_pmap3_call_result (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3CALLITres (ZDR *zdrs, PMAP3CALLITres *objp) { if (!zdr_pmap3_call_result (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3UADDR2TADDRres (ZDR *zdrs, PMAP3UADDR2TADDRres *objp) { if (!zdr_pmap3_netbuf (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3TADDR2UADDRargs (ZDR *zdrs, PMAP3TADDR2UADDRargs *objp) { if (!zdr_pmap3_netbuf (zdrs, objp)) return FALSE; return TRUE; } uint32_t zdr_PMAP3TADDR2UADDRres (ZDR *zdrs, PMAP3TADDR2UADDRres *objp) { if (!zdr_pmap3_string_result (zdrs, objp)) return FALSE; return TRUE; } libnfs-libnfs-4.0.0/portmap/libnfs-raw-portmap.h000066400000000000000000000266041343063627400216420ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _PORTMAP_H_RPCGEN #define _PORTMAP_H_RPCGEN #include #ifdef __cplusplus extern "C" { #endif #define PMAP_PORT 111 struct pmap2_mapping { u_int prog; u_int vers; u_int prot; u_int port; }; typedef struct pmap2_mapping pmap2_mapping; struct pmap2_call_args { u_int prog; u_int vers; u_int proc; struct { u_int args_len; char *args_val; } args; }; typedef struct pmap2_call_args pmap2_call_args; struct pmap2_call_result { u_int port; struct { u_int res_len; char *res_val; } res; }; typedef struct pmap2_call_result pmap2_call_result; struct pmap2_mapping_list { pmap2_mapping map; struct pmap2_mapping_list *next; }; typedef struct pmap2_mapping_list pmap2_mapping_list; struct pmap2_dump_result { struct pmap2_mapping_list *list; }; typedef struct pmap2_dump_result pmap2_dump_result; struct pmap3_string_result { char *addr; }; typedef struct pmap3_string_result pmap3_string_result; struct pmap3_mapping { u_int prog; u_int vers; char *netid; char *addr; char *owner; }; typedef struct pmap3_mapping pmap3_mapping; struct pmap3_mapping_list { pmap3_mapping map; struct pmap3_mapping_list *next; }; typedef struct pmap3_mapping_list pmap3_mapping_list; struct pmap3_dump_result { struct pmap3_mapping_list *list; }; typedef struct pmap3_dump_result pmap3_dump_result; struct pmap3_call_args { u_int prog; u_int vers; u_int proc; struct { u_int args_len; char *args_val; } args; }; typedef struct pmap3_call_args pmap3_call_args; struct pmap3_call_result { u_int port; struct { u_int res_len; char *res_val; } res; }; typedef struct pmap3_call_result pmap3_call_result; struct pmap3_netbuf { u_int maxlen; struct { u_int buf_len; char *buf_val; } buf; }; typedef struct pmap3_netbuf pmap3_netbuf; typedef pmap2_mapping PMAP2SETargs; typedef pmap2_mapping PMAP2UNSETargs; typedef pmap2_mapping PMAP2GETPORTargs; typedef pmap2_call_args PMAP2CALLITargs; typedef pmap2_call_result PMAP2CALLITres; typedef pmap2_dump_result PMAP2DUMPres; typedef pmap3_mapping PMAP3SETargs; typedef pmap3_mapping PMAP3UNSETargs; typedef pmap3_mapping PMAP3GETADDRargs; typedef pmap3_string_result PMAP3GETADDRres; typedef pmap3_dump_result PMAP3DUMPres; typedef pmap3_call_result PMAP3CALLITargs; typedef pmap3_call_result PMAP3CALLITres; typedef pmap3_netbuf PMAP3UADDR2TADDRres; typedef pmap3_netbuf PMAP3TADDR2UADDRargs; typedef pmap3_string_result PMAP3TADDR2UADDRres; #define PMAP_PROGRAM 100000 #define PMAP_V2 2 #if defined(__STDC__) || defined(__cplusplus) #define PMAP2_NULL 0 extern void * pmap2_null_2(void *, void *); extern void * pmap2_null_2_svc(void *, struct svc_req *); #define PMAP2_SET 1 extern uint32_t * pmap2_set_2(PMAP2SETargs *, void *); extern uint32_t * pmap2_set_2_svc(PMAP2SETargs *, struct svc_req *); #define PMAP2_UNSET 2 extern uint32_t * pmap2_unset_2(PMAP2UNSETargs *, void *); extern uint32_t * pmap2_unset_2_svc(PMAP2UNSETargs *, struct svc_req *); #define PMAP2_GETPORT 3 extern uint32_t * pmap2_getport_2(PMAP2GETPORTargs *, void *); extern uint32_t * pmap2_getport_2_svc(PMAP2GETPORTargs *, struct svc_req *); #define PMAP2_DUMP 4 extern PMAP2DUMPres * pmap2_dump_2(void *, void *); extern PMAP2DUMPres * pmap2_dump_2_svc(void *, struct svc_req *); #define PMAP2_CALLIT 5 extern PMAP2CALLITres * pmap2_callit_2(PMAP2CALLITargs *, void *); extern PMAP2CALLITres * pmap2_callit_2_svc(PMAP2CALLITargs *, struct svc_req *); extern int pmap_program_2_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define PMAP2_NULL 0 extern void * pmap2_null_2(); extern void * pmap2_null_2_svc(); #define PMAP2_SET 1 extern uint32_t * pmap2_set_2(); extern uint32_t * pmap2_set_2_svc(); #define PMAP2_UNSET 2 extern uint32_t * pmap2_unset_2(); extern uint32_t * pmap2_unset_2_svc(); #define PMAP2_GETPORT 3 extern uint32_t * pmap2_getport_2(); extern uint32_t * pmap2_getport_2_svc(); #define PMAP2_DUMP 4 extern PMAP2DUMPres * pmap2_dump_2(); extern PMAP2DUMPres * pmap2_dump_2_svc(); #define PMAP2_CALLIT 5 extern PMAP2CALLITres * pmap2_callit_2(); extern PMAP2CALLITres * pmap2_callit_2_svc(); extern int pmap_program_2_freeresult (); #endif /* K&R C */ #define PMAP_V3 3 #if defined(__STDC__) || defined(__cplusplus) #define PMAP3_NULL 0 extern void * pmap3_null_3(void *, void *); extern void * pmap3_null_3_svc(void *, struct svc_req *); #define PMAP3_SET 1 extern uint32_t * pmap3_set_3(PMAP3SETargs *, void *); extern uint32_t * pmap3_set_3_svc(PMAP3SETargs *, struct svc_req *); #define PMAP3_UNSET 2 extern uint32_t * pmap3_unset_3(PMAP3UNSETargs *, void *); extern uint32_t * pmap3_unset_3_svc(PMAP3UNSETargs *, struct svc_req *); #define PMAP3_GETADDR 3 extern PMAP3GETADDRres * pmap3_getaddr_3(PMAP3GETADDRargs *, void *); extern PMAP3GETADDRres * pmap3_getaddr_3_svc(PMAP3GETADDRargs *, struct svc_req *); #define PMAP3_DUMP 4 extern PMAP3DUMPres * pmap3_dump_3(void *, void *); extern PMAP3DUMPres * pmap3_dump_3_svc(void *, struct svc_req *); #define PMAP3_CALLIT 5 extern PMAP3CALLITres * pmap3_callit_3(PMAP3CALLITargs *, void *); extern PMAP3CALLITres * pmap3_callit_3_svc(PMAP3CALLITargs *, struct svc_req *); #define PMAP3_GETTIME 6 extern uint32_t * pmap3_gettime_3(void *, void *); extern uint32_t * pmap3_gettime_3_svc(void *, struct svc_req *); #define PMAP3_UADDR2TADDR 7 extern PMAP3UADDR2TADDRres * pmap3_uaddr2taddr_3(char **, void *); extern PMAP3UADDR2TADDRres * pmap3_uaddr2taddr_3_svc(char **, struct svc_req *); #define PMAP3_TADDR2UADDR 8 extern PMAP3TADDR2UADDRres * pmap3_taddr2uaddr_3(PMAP3TADDR2UADDRargs *, void *); extern PMAP3TADDR2UADDRres * pmap3_taddr2uaddr_3_svc(PMAP3TADDR2UADDRargs *, struct svc_req *); extern int pmap_program_3_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define PMAP3_NULL 0 extern void * pmap3_null_3(); extern void * pmap3_null_3_svc(); #define PMAP3_SET 1 extern uint32_t * pmap3_set_3(); extern uint32_t * pmap3_set_3_svc(); #define PMAP3_UNSET 2 extern uint32_t * pmap3_unset_3(); extern uint32_t * pmap3_unset_3_svc(); #define PMAP3_GETADDR 3 extern PMAP3GETADDRres * pmap3_getaddr_3(); extern PMAP3GETADDRres * pmap3_getaddr_3_svc(); #define PMAP3_DUMP 4 extern PMAP3DUMPres * pmap3_dump_3(); extern PMAP3DUMPres * pmap3_dump_3_svc(); #define PMAP3_CALLIT 5 extern PMAP3CALLITres * pmap3_callit_3(); extern PMAP3CALLITres * pmap3_callit_3_svc(); #define PMAP3_GETTIME 6 extern uint32_t * pmap3_gettime_3(); extern uint32_t * pmap3_gettime_3_svc(); #define PMAP3_UADDR2TADDR 7 extern PMAP3UADDR2TADDRres * pmap3_uaddr2taddr_3(); extern PMAP3UADDR2TADDRres * pmap3_uaddr2taddr_3_svc(); #define PMAP3_TADDR2UADDR 8 extern PMAP3TADDR2UADDRres * pmap3_taddr2uaddr_3(); extern PMAP3TADDR2UADDRres * pmap3_taddr2uaddr_3_svc(); extern int pmap_program_3_freeresult (); #endif /* K&R C */ /* the zdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern uint32_t zdr_pmap2_mapping (ZDR *, pmap2_mapping*); extern uint32_t zdr_pmap2_call_args (ZDR *, pmap2_call_args*); extern uint32_t zdr_pmap2_call_result (ZDR *, pmap2_call_result*); extern uint32_t zdr_pmap2_mapping_list (ZDR *, pmap2_mapping_list*); extern uint32_t zdr_pmap2_dump_result (ZDR *, pmap2_dump_result*); extern uint32_t zdr_pmap3_string_result (ZDR *, pmap3_string_result*); extern uint32_t zdr_pmap3_mapping (ZDR *, pmap3_mapping*); extern uint32_t zdr_pmap3_mapping_list (ZDR *, pmap3_mapping_list*); extern uint32_t zdr_pmap3_dump_result (ZDR *, pmap3_dump_result*); extern uint32_t zdr_pmap3_call_args (ZDR *, pmap3_call_args*); extern uint32_t zdr_pmap3_call_result (ZDR *, pmap3_call_result*); extern uint32_t zdr_pmap3_netbuf (ZDR *, pmap3_netbuf*); extern uint32_t zdr_PMAP2SETargs (ZDR *, PMAP2SETargs*); extern uint32_t zdr_PMAP2UNSETargs (ZDR *, PMAP2UNSETargs*); extern uint32_t zdr_PMAP2GETPORTargs (ZDR *, PMAP2GETPORTargs*); extern uint32_t zdr_PMAP2CALLITargs (ZDR *, PMAP2CALLITargs*); extern uint32_t zdr_PMAP2CALLITres (ZDR *, PMAP2CALLITres*); extern uint32_t zdr_PMAP2DUMPres (ZDR *, PMAP2DUMPres*); extern uint32_t zdr_PMAP3SETargs (ZDR *, PMAP3SETargs*); extern uint32_t zdr_PMAP3UNSETargs (ZDR *, PMAP3UNSETargs*); extern uint32_t zdr_PMAP3GETADDRargs (ZDR *, PMAP3GETADDRargs*); extern uint32_t zdr_PMAP3GETADDRres (ZDR *, PMAP3GETADDRres*); extern uint32_t zdr_PMAP3DUMPres (ZDR *, PMAP3DUMPres*); extern uint32_t zdr_PMAP3CALLITargs (ZDR *, PMAP3CALLITargs*); extern uint32_t zdr_PMAP3CALLITres (ZDR *, PMAP3CALLITres*); extern uint32_t zdr_PMAP3UADDR2TADDRres (ZDR *, PMAP3UADDR2TADDRres*); extern uint32_t zdr_PMAP3TADDR2UADDRargs (ZDR *, PMAP3TADDR2UADDRargs*); extern uint32_t zdr_PMAP3TADDR2UADDRres (ZDR *, PMAP3TADDR2UADDRres*); #else /* K&R C */ extern uint32_t zdr_pmap2_mapping (); extern uint32_t zdr_pmap2_call_args (); extern uint32_t zdr_pmap2_call_result (); extern uint32_t zdr_pmap2_mapping_list (); extern uint32_t zdr_pmap2_dump_result (); extern uint32_t zdr_pmap3_string_result (); extern uint32_t zdr_pmap3_mapping (); extern uint32_t zdr_pmap3_mapping_list (); extern uint32_t zdr_pmap3_dump_result (); extern uint32_t zdr_pmap3_call_args (); extern uint32_t zdr_pmap3_call_result (); extern uint32_t zdr_pmap3_netbuf (); extern uint32_t zdr_PMAP2SETargs (); extern uint32_t zdr_PMAP2UNSETargs (); extern uint32_t zdr_PMAP2GETPORTargs (); extern uint32_t zdr_PMAP2CALLITargs (); extern uint32_t zdr_PMAP2CALLITres (); extern uint32_t zdr_PMAP2DUMPres (); extern uint32_t zdr_PMAP3SETargs (); extern uint32_t zdr_PMAP3UNSETargs (); extern uint32_t zdr_PMAP3GETADDRargs (); extern uint32_t zdr_PMAP3GETADDRres (); extern uint32_t zdr_PMAP3DUMPres (); extern uint32_t zdr_PMAP3CALLITargs (); extern uint32_t zdr_PMAP3CALLITres (); extern uint32_t zdr_PMAP3UADDR2TADDRres (); extern uint32_t zdr_PMAP3TADDR2UADDRargs (); extern uint32_t zdr_PMAP3TADDR2UADDRres (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_PORTMAP_H_RPCGEN */ libnfs-libnfs-4.0.0/portmap/portmap.c000066400000000000000000000257471343063627400176020ustar00rootroot00000000000000/* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef WIN32 #include #endif/*WIN32*/ #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-portmap.h" /* * PORTMAP v2 */ int rpc_pmap2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/NULL call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for PORTMAP2/NULL call"); return -1; } return 0; } int rpc_pmap2_getport_async(struct rpc_context *rpc, int program, int version, int protocol, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; struct pmap2_mapping m; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_GETPORT, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/GETPORT call"); return -1; } m.prog = program; m.vers = version; m.prot = protocol; m.port = 0; if (zdr_pmap2_mapping(&pdu->zdr, &m) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP2/GETPORT call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP2/GETPORT pdu"); return -1; } return 0; } int rpc_pmap2_set_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; struct pmap2_mapping m; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_SET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/SET call"); return -1; } m.prog = program; m.vers = version; m.prot = protocol; m.port = port; if (zdr_pmap2_mapping(&pdu->zdr, &m) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP2/SET call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP2/SET pdu"); return -1; } return 0; } int rpc_pmap2_unset_async(struct rpc_context *rpc, int program, int version, int protocol, int port, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; struct pmap2_mapping m; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_UNSET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/UNSET call"); return -1; } m.prog = program; m.vers = version; m.prot = protocol; m.port = port; if (zdr_pmap2_mapping(&pdu->zdr, &m) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP2/UNSET call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP2/UNSET pdu"); return -1; } return 0; } int rpc_pmap2_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_DUMP, cb, private_data, (zdrproc_t)zdr_pmap2_dump_result, sizeof(pmap2_dump_result)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/DUMP call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP2/DUMP pdu"); return -1; } return 0; } int rpc_pmap2_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; struct pmap2_call_args ca; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V2, PMAP2_CALLIT, cb, private_data, (zdrproc_t)zdr_pmap2_call_result, sizeof(pmap2_call_result)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP2/CALLIT call"); return -1; } ca.prog = program; ca.vers = version; ca.proc = procedure; ca.args.args_len = datalen; ca.args.args_val = data; if (zdr_pmap2_call_args(&pdu->zdr, &ca) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP2/CALLIT call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP2/CALLIT pdu: %s", rpc_get_error(rpc)); return -1; } return 0; } /* * PORTMAP v3 */ int rpc_pmap3_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/NULL call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for PORTMAP3/NULL call"); return -1; } return 0; } int rpc_pmap3_set_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_SET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/SET call"); return -1; } if (zdr_pmap3_mapping(&pdu->zdr, map) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/SET call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP3/SET pdu"); return -1; } return 0; } int rpc_pmap3_unset_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_UNSET, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/UNSET call"); return -1; } if (zdr_pmap3_mapping(&pdu->zdr, map) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/UNSET call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP3/UNSET pdu"); return -1; } return 0; } int rpc_pmap3_getaddr_async(struct rpc_context *rpc, struct pmap3_mapping *map, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_GETADDR, cb, private_data, (zdrproc_t)zdr_pmap3_string_result, sizeof(pmap3_string_result)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/GETADDR call"); return -1; } if (zdr_pmap3_mapping(&pdu->zdr, map) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/GETADDR call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP3/GETADDR pdu"); return -1; } return 0; } int rpc_pmap3_dump_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_DUMP, cb, private_data, (zdrproc_t)zdr_pmap3_dump_result, sizeof(pmap3_dump_result)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/DUMP call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP3/DUMP pdu"); return -1; } return 0; } int rpc_pmap3_gettime_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_GETTIME, cb, private_data, (zdrproc_t)zdr_int, sizeof(uint32_t)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/GETTIME call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP3/GETTIME pdu"); return -1; } return 0; } int rpc_pmap3_callit_async(struct rpc_context *rpc, int program, int version, int procedure, char *data, int datalen, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; struct pmap3_call_args ca; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_CALLIT, cb, private_data, (zdrproc_t)zdr_pmap3_call_result, sizeof(pmap3_call_result)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/CALLIT call"); return -1; } ca.prog = program; ca.vers = version; ca.proc = procedure; ca.args.args_len = datalen; ca.args.args_val = data; if (zdr_pmap3_call_args(&pdu->zdr, &ca) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/CALLIT call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP3/CALLIT pdu: %s", rpc_get_error(rpc)); return -1; } return 0; } int rpc_pmap3_uaddr2taddr_async(struct rpc_context *rpc, char *uaddr, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_UADDR2TADDR, cb, private_data, (zdrproc_t)zdr_pmap3_netbuf, sizeof(pmap3_netbuf)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/UADDR2TADDR call"); return -1; } if (zdr_string(&pdu->zdr, &uaddr, 255) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/UADDR2TADDR call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP3/UADDR2TADDR pdu: %s", rpc_get_error(rpc)); return -1; } return 0; } int rpc_pmap3_taddr2uaddr_async(struct rpc_context *rpc, struct pmap3_netbuf *nb, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, PMAP_PROGRAM, PMAP_V3, PMAP3_TADDR2UADDR, cb, private_data, (zdrproc_t)zdr_pmap3_string_result, sizeof(pmap3_string_result)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for PORTMAP3/TADDR2UADDR call"); return -1; } if (zdr_pmap3_netbuf(&pdu->zdr, nb) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode data for PORTMAP3/TADDR2UADDR call"); rpc_free_pdu(rpc, pdu); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Failed to queue PORTMAP3/TADDR2UADDR pdu: %s", rpc_get_error(rpc)); return -1; } return 0; } libnfs-libnfs-4.0.0/portmap/portmap.x000066400000000000000000000106431343063627400176140ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ const PMAP_PORT = 111; /* portmapper port number */ struct pmap2_mapping { unsigned int prog; unsigned int vers; unsigned int prot; unsigned int port; }; struct pmap2_call_args { unsigned int prog; unsigned int vers; unsigned int proc; opaque args<>; }; struct pmap2_call_result { unsigned int port; opaque res<>; }; struct pmap2_mapping_list { pmap2_mapping map; pmap2_mapping_list *next; }; struct pmap2_dump_result { struct pmap2_mapping_list *list; }; struct pmap3_string_result { string addr<>; }; struct pmap3_mapping { unsigned int prog; unsigned int vers; string netid<>; string addr<>; string owner<>; }; struct pmap3_mapping_list { pmap3_mapping map; pmap3_mapping_list *next; }; struct pmap3_dump_result { struct pmap3_mapping_list *list; }; struct pmap3_call_args { unsigned int prog; unsigned int vers; unsigned int proc; opaque args<>; }; struct pmap3_call_result { unsigned int port; opaque res<>; }; struct pmap3_netbuf { unsigned int maxlen; /* This pretty much contains a sockaddr_storage. * Beware differences in endianess for ss_family * and whether or not ss_len exists. */ opaque buf<>; }; typedef pmap2_mapping PMAP2SETargs; typedef pmap2_mapping PMAP2UNSETargs; typedef pmap2_mapping PMAP2GETPORTargs; typedef pmap2_call_args PMAP2CALLITargs; typedef pmap2_call_result PMAP2CALLITres; typedef pmap2_dump_result PMAP2DUMPres; typedef pmap3_mapping PMAP3SETargs; typedef pmap3_mapping PMAP3UNSETargs; typedef pmap3_mapping PMAP3GETADDRargs; typedef pmap3_string_result PMAP3GETADDRres; typedef pmap3_dump_result PMAP3DUMPres; typedef pmap3_call_result PMAP3CALLITargs; typedef pmap3_call_result PMAP3CALLITres; typedef pmap3_netbuf PMAP3UADDR2TADDRres; typedef pmap3_netbuf PMAP3TADDR2UADDRargs; typedef pmap3_string_result PMAP3TADDR2UADDRres; program PMAP_PROGRAM { version PMAP_V2 { void PMAP2_NULL(void) = 0; uint32_t PMAP2_SET(PMAP2SETargs) = 1; uint32_t PMAP2_UNSET(PMAP2UNSETargs) = 2; uint32_t PMAP2_GETPORT(PMAP2GETPORTargs) = 3; PMAP2DUMPres PMAP2_DUMP(void) = 4; PMAP2CALLITres PMAP2_CALLIT(PMAP2CALLITargs) = 5; } = 2; version PMAP_V3 { void PMAP3_NULL(void) = 0; uint32_t PMAP3_SET(PMAP3SETargs) = 1; uint32_t PMAP3_UNSET(PMAP3UNSETargs) = 2; PMAP3GETADDRres PMAP3_GETADDR(PMAP3GETADDRargs) = 3; PMAP3DUMPres PMAP3_DUMP(void) = 4; PMAP3CALLITres PMAP3_CALLIT(PMAP3CALLITargs) = 5; uint32_t PMAP3_GETTIME(void) = 6; PMAP3UADDR2TADDRres PMAP3_UADDR2TADDR(string) = 7; PMAP3TADDR2UADDRres PMAP3_TADDR2UADDR(PMAP3TADDR2UADDRargs) = 8; } = 3; } = 100000; libnfs-libnfs-4.0.0/rquota/000077500000000000000000000000001343063627400155665ustar00rootroot00000000000000libnfs-libnfs-4.0.0/rquota/CMakeLists.txt000066400000000000000000000001611343063627400203240ustar00rootroot00000000000000set(SOURCES libnfs-raw-rquota.c rquota.c) set(HEADERS libnfs-raw-rquota.h) core_add_library(rquota) libnfs-libnfs-4.0.0/rquota/Makefile.am000066400000000000000000000021701343063627400176220ustar00rootroot00000000000000noinst_LTLIBRARIES = librquota.la rquota_SOURCES_GENERATED = rquota_HEADERS_GENERATED = rquota_GENERATED = $(rquota_SOURCES_GENERATED) $(rquota_HEADERS_GENERATED) CLEANFILES = $(rquota_GENERATED) rquota-stamp librquota_la_CPPFLAGS = -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/win32 librquota_la_SOURCES = \ $(rquota_SOURCES_GENERATED) \ rquota.c libnfs-raw-rquota.c libnfs-raw-rquota.h $(rquota_GENERATED) : rquota-stamp rquota-stamp : rquota.x rm -f $(rquota_GENERATED) touch rquota-stamp compile_rpc: cat rquota.x | head -29 >libnfs-raw-rquota.h rpcgen -h rquota.x | sed -e "s/#include /#include /" | sed -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/ CLIENT / void /g" -e "s/SVCXPRT /void /g" -e "s/bool_t/uint32_t/g" >> libnfs-raw-rquota.h cat rquota.x | head -29 >libnfs-raw-rquota.c rpcgen -c rquota.x | sed -e "s/#include \".*rquota.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-rquota.h\"/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/register int32_t \*buf;/register int32_t *buf;\n buf = NULL;/" -e "s/bool_t/uint32_t/g" >> libnfs-raw-rquota.c libnfs-libnfs-4.0.0/rquota/libnfs-raw-rquota.c000066400000000000000000000132531343063627400213130ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #include "libnfs-zdr.h" #include "libnfs-raw-rquota.h" uint32_t zdr_rquotastat (ZDR *zdrs, rquotastat *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_exportpath (ZDR *zdrs, exportpath *objp) { if (!zdr_string (zdrs, objp, RQUOTAPATHLEN)) return FALSE; return TRUE; } uint32_t zdr_GETQUOTA1args (ZDR *zdrs, GETQUOTA1args *objp) { if (!zdr_exportpath (zdrs, &objp->export)) return FALSE; if (!zdr_int (zdrs, &objp->uid)) return FALSE; return TRUE; } uint32_t zdr_quotatype (ZDR *zdrs, quotatype *objp) { if (!zdr_enum (zdrs, (enum_t *) objp)) return FALSE; return TRUE; } uint32_t zdr_GETQUOTA2args (ZDR *zdrs, GETQUOTA2args *objp) { if (!zdr_exportpath (zdrs, &objp->export)) return FALSE; if (!zdr_quotatype (zdrs, &objp->type)) return FALSE; if (!zdr_int (zdrs, &objp->uid)) return FALSE; return TRUE; } uint32_t zdr_GETQUOTA1res_ok (ZDR *zdrs, GETQUOTA1res_ok *objp) { register int32_t *buf; buf = NULL; if (zdrs->x_op == ZDR_ENCODE) { buf = ZDR_INLINE (zdrs, 10 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_int (zdrs, &objp->bsize)) return FALSE; if (!zdr_int (zdrs, &objp->active)) return FALSE; if (!zdr_int (zdrs, &objp->bhardlimit)) return FALSE; if (!zdr_int (zdrs, &objp->bsoftlimit)) return FALSE; if (!zdr_int (zdrs, &objp->curblocks)) return FALSE; if (!zdr_int (zdrs, &objp->fhardlimit)) return FALSE; if (!zdr_int (zdrs, &objp->fsoftlimit)) return FALSE; if (!zdr_int (zdrs, &objp->curfiles)) return FALSE; if (!zdr_int (zdrs, &objp->btimeleft)) return FALSE; if (!zdr_int (zdrs, &objp->ftimeleft)) return FALSE; } else { IZDR_PUT_LONG(buf, objp->bsize); IZDR_PUT_LONG(buf, objp->active); IZDR_PUT_LONG(buf, objp->bhardlimit); IZDR_PUT_LONG(buf, objp->bsoftlimit); IZDR_PUT_LONG(buf, objp->curblocks); IZDR_PUT_LONG(buf, objp->fhardlimit); IZDR_PUT_LONG(buf, objp->fsoftlimit); IZDR_PUT_LONG(buf, objp->curfiles); IZDR_PUT_LONG(buf, objp->btimeleft); IZDR_PUT_LONG(buf, objp->ftimeleft); } return TRUE; } else if (zdrs->x_op == ZDR_DECODE) { buf = ZDR_INLINE (zdrs, 10 * BYTES_PER_ZDR_UNIT); if (buf == NULL) { if (!zdr_int (zdrs, &objp->bsize)) return FALSE; if (!zdr_int (zdrs, &objp->active)) return FALSE; if (!zdr_int (zdrs, &objp->bhardlimit)) return FALSE; if (!zdr_int (zdrs, &objp->bsoftlimit)) return FALSE; if (!zdr_int (zdrs, &objp->curblocks)) return FALSE; if (!zdr_int (zdrs, &objp->fhardlimit)) return FALSE; if (!zdr_int (zdrs, &objp->fsoftlimit)) return FALSE; if (!zdr_int (zdrs, &objp->curfiles)) return FALSE; if (!zdr_int (zdrs, &objp->btimeleft)) return FALSE; if (!zdr_int (zdrs, &objp->ftimeleft)) return FALSE; } else { objp->bsize = IZDR_GET_LONG(buf); objp->active = IZDR_GET_LONG(buf); objp->bhardlimit = IZDR_GET_LONG(buf); objp->bsoftlimit = IZDR_GET_LONG(buf); objp->curblocks = IZDR_GET_LONG(buf); objp->fhardlimit = IZDR_GET_LONG(buf); objp->fsoftlimit = IZDR_GET_LONG(buf); objp->curfiles = IZDR_GET_LONG(buf); objp->btimeleft = IZDR_GET_LONG(buf); objp->ftimeleft = IZDR_GET_LONG(buf); } return TRUE; } if (!zdr_int (zdrs, &objp->bsize)) return FALSE; if (!zdr_int (zdrs, &objp->active)) return FALSE; if (!zdr_int (zdrs, &objp->bhardlimit)) return FALSE; if (!zdr_int (zdrs, &objp->bsoftlimit)) return FALSE; if (!zdr_int (zdrs, &objp->curblocks)) return FALSE; if (!zdr_int (zdrs, &objp->fhardlimit)) return FALSE; if (!zdr_int (zdrs, &objp->fsoftlimit)) return FALSE; if (!zdr_int (zdrs, &objp->curfiles)) return FALSE; if (!zdr_int (zdrs, &objp->btimeleft)) return FALSE; if (!zdr_int (zdrs, &objp->ftimeleft)) return FALSE; return TRUE; } uint32_t zdr_GETQUOTA1res (ZDR *zdrs, GETQUOTA1res *objp) { if (!zdr_rquotastat (zdrs, &objp->status)) return FALSE; switch (objp->status) { case RQUOTA_OK: if (!zdr_GETQUOTA1res_ok (zdrs, &objp->GETQUOTA1res_u.quota)) return FALSE; break; default: break; } return TRUE; } libnfs-libnfs-4.0.0/rquota/libnfs-raw-rquota.h000066400000000000000000000127251343063627400213230ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _RQUOTA_H_RPCGEN #define _RQUOTA_H_RPCGEN #include #ifdef __cplusplus extern "C" { #endif #define RQUOTAPATHLEN 1024 enum rquotastat { RQUOTA_OK = 1, RQUOTA_NOQUOTA = 2, RQUOTA_EPERM = 3, }; typedef enum rquotastat rquotastat; typedef char *exportpath; struct GETQUOTA1args { exportpath export; int uid; }; typedef struct GETQUOTA1args GETQUOTA1args; enum quotatype { RQUOTA_TYPE_UID = 0, RQUOTA_TYPE_GID = 1, }; typedef enum quotatype quotatype; struct GETQUOTA2args { exportpath export; quotatype type; int uid; }; typedef struct GETQUOTA2args GETQUOTA2args; struct GETQUOTA1res_ok { int bsize; int active; int bhardlimit; int bsoftlimit; int curblocks; int fhardlimit; int fsoftlimit; int curfiles; int btimeleft; int ftimeleft; }; typedef struct GETQUOTA1res_ok GETQUOTA1res_ok; struct GETQUOTA1res { rquotastat status; union { GETQUOTA1res_ok quota; } GETQUOTA1res_u; }; typedef struct GETQUOTA1res GETQUOTA1res; #define RQUOTA_PROGRAM 100011 #define RQUOTA_V1 1 #if defined(__STDC__) || defined(__cplusplus) #define RQUOTA1_NULL 0 extern void * rquota1_null_1(void *, void *); extern void * rquota1_null_1_svc(void *, struct svc_req *); #define RQUOTA1_GETQUOTA 1 extern GETQUOTA1res * rquota1_getquota_1(GETQUOTA1args *, void *); extern GETQUOTA1res * rquota1_getquota_1_svc(GETQUOTA1args *, struct svc_req *); #define RQUOTA1_GETACTIVEQUOTA 2 extern GETQUOTA1res * rquota1_getactivequota_1(GETQUOTA1args *, void *); extern GETQUOTA1res * rquota1_getactivequota_1_svc(GETQUOTA1args *, struct svc_req *); extern int rquota_program_1_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define RQUOTA1_NULL 0 extern void * rquota1_null_1(); extern void * rquota1_null_1_svc(); #define RQUOTA1_GETQUOTA 1 extern GETQUOTA1res * rquota1_getquota_1(); extern GETQUOTA1res * rquota1_getquota_1_svc(); #define RQUOTA1_GETACTIVEQUOTA 2 extern GETQUOTA1res * rquota1_getactivequota_1(); extern GETQUOTA1res * rquota1_getactivequota_1_svc(); extern int rquota_program_1_freeresult (); #endif /* K&R C */ #define RQUOTA_V2 2 #if defined(__STDC__) || defined(__cplusplus) #define RQUOTA2_NULL 0 extern void * rquota2_null_2(void *, void *); extern void * rquota2_null_2_svc(void *, struct svc_req *); #define RQUOTA2_GETQUOTA 1 extern GETQUOTA1res * rquota2_getquota_2(GETQUOTA2args *, void *); extern GETQUOTA1res * rquota2_getquota_2_svc(GETQUOTA2args *, struct svc_req *); #define RQUOTA2_GETACTIVEQUOTA 2 extern GETQUOTA1res * rquota2_getactivequota_2(GETQUOTA2args *, void *); extern GETQUOTA1res * rquota2_getactivequota_2_svc(GETQUOTA2args *, struct svc_req *); extern int rquota_program_2_freeresult (void *, zdrproc_t, caddr_t); #else /* K&R C */ #define RQUOTA2_NULL 0 extern void * rquota2_null_2(); extern void * rquota2_null_2_svc(); #define RQUOTA2_GETQUOTA 1 extern GETQUOTA1res * rquota2_getquota_2(); extern GETQUOTA1res * rquota2_getquota_2_svc(); #define RQUOTA2_GETACTIVEQUOTA 2 extern GETQUOTA1res * rquota2_getactivequota_2(); extern GETQUOTA1res * rquota2_getactivequota_2_svc(); extern int rquota_program_2_freeresult (); #endif /* K&R C */ /* the zdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern uint32_t zdr_rquotastat (ZDR *, rquotastat*); extern uint32_t zdr_exportpath (ZDR *, exportpath*); extern uint32_t zdr_GETQUOTA1args (ZDR *, GETQUOTA1args*); extern uint32_t zdr_quotatype (ZDR *, quotatype*); extern uint32_t zdr_GETQUOTA2args (ZDR *, GETQUOTA2args*); extern uint32_t zdr_GETQUOTA1res_ok (ZDR *, GETQUOTA1res_ok*); extern uint32_t zdr_GETQUOTA1res (ZDR *, GETQUOTA1res*); #else /* K&R C */ extern uint32_t zdr_rquotastat (); extern uint32_t zdr_exportpath (); extern uint32_t zdr_GETQUOTA1args (); extern uint32_t zdr_quotatype (); extern uint32_t zdr_GETQUOTA2args (); extern uint32_t zdr_GETQUOTA1res_ok (); extern uint32_t zdr_GETQUOTA1res (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_RQUOTA_H_RPCGEN */ libnfs-libnfs-4.0.0/rquota/rquota.c000066400000000000000000000131011343063627400172410ustar00rootroot00000000000000/* Copyright (C) 2010 by Ronnie Sahlberg This program 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 program 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 program; if not, see . */ #ifdef WIN32 #include #endif/*WIN32*/ #include #include #include #include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-private.h" #include "libnfs-raw-rquota.h" char *rquotastat_to_str(int error) { switch (error) { case RQUOTA_OK: return "RQUOTA_OK"; break; case RQUOTA_NOQUOTA: return "RQUOTA_NOQUOTA"; break; case RQUOTA_EPERM: return "RQUOTA_EPERM"; break; }; return "unknown rquota error"; } int rquotastat_to_errno(int error) { switch (error) { case RQUOTA_OK: return 0; break; case RQUOTA_NOQUOTA: return -ENOENT; break; case RQUOTA_EPERM: return -EPERM; break; }; return -ENOENT; } int rpc_rquota1_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, RQUOTA_PROGRAM, RQUOTA_V1, RQUOTA1_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for rquota1/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for rquota1/null call"); return -2; } return 0; } int rpc_rquota1_getquota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int uid, void *private_data) { struct rpc_pdu *pdu; GETQUOTA1args args; pdu = rpc_allocate_pdu(rpc, RQUOTA_PROGRAM, RQUOTA_V1, RQUOTA1_GETQUOTA, cb, private_data, (zdrproc_t)zdr_GETQUOTA1res, sizeof(GETQUOTA1res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for rquota1/getquota call"); return -1; } args.export = export; args.uid = uid; if (zdr_GETQUOTA1args(&pdu->zdr, &args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode GETQUOTA1args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for rquota1/getquota call"); return -3; } return 0; } int rpc_rquota1_getactivequota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int uid, void *private_data) { struct rpc_pdu *pdu; GETQUOTA1args args; pdu = rpc_allocate_pdu(rpc, RQUOTA_PROGRAM, RQUOTA_V1, RQUOTA1_GETACTIVEQUOTA, cb, private_data, (zdrproc_t)zdr_GETQUOTA1res, sizeof(GETQUOTA1res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for rquota1/getactivequota call"); return -1; } args.export = export; args.uid = uid; if (zdr_GETQUOTA1args(&pdu->zdr, &args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode GETQUOTA1args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for rquota1/getactivequota call"); return -3; } return 0; } int rpc_rquota2_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data) { struct rpc_pdu *pdu; pdu = rpc_allocate_pdu(rpc, RQUOTA_PROGRAM, RQUOTA_V2, RQUOTA2_NULL, cb, private_data, (zdrproc_t)zdr_void, 0); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for rquota2/null call"); return -1; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for rquota2/null call"); return -2; } return 0; } int rpc_rquota2_getquota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int type, int uid, void *private_data) { struct rpc_pdu *pdu; GETQUOTA2args args; pdu = rpc_allocate_pdu(rpc, RQUOTA_PROGRAM, RQUOTA_V2, RQUOTA2_GETQUOTA, cb, private_data, (zdrproc_t)zdr_GETQUOTA1res, sizeof(GETQUOTA1res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for rquota2/getquota call"); return -1; } args.export = export; args.type = type; args.uid = uid; if (zdr_GETQUOTA2args(&pdu->zdr, &args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode GETQUOTA2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for rquota2/getquota call"); return -3; } return 0; } int rpc_rquota2_getactivequota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int type, int uid, void *private_data) { struct rpc_pdu *pdu; GETQUOTA2args args; pdu = rpc_allocate_pdu(rpc, RQUOTA_PROGRAM, RQUOTA_V2, RQUOTA2_GETACTIVEQUOTA, cb, private_data, (zdrproc_t)zdr_GETQUOTA1res, sizeof(GETQUOTA1res)); if (pdu == NULL) { rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for rquota2/getactivequota call"); return -1; } args.export = export; args.type = type; args.uid = uid; if (zdr_GETQUOTA2args(&pdu->zdr, &args) == 0) { rpc_set_error(rpc, "ZDR error: Failed to encode GETQUOTA2args"); rpc_free_pdu(rpc, pdu); return -2; } if (rpc_queue_pdu(rpc, pdu) != 0) { rpc_set_error(rpc, "Out of memory. Failed to queue pdu for rquota2/getactivequota call"); return -3; } return 0; } libnfs-libnfs-4.0.0/rquota/rquota.x000066400000000000000000000053751343063627400173040ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ const RQUOTAPATHLEN = 1024; /* Guess this is max. It is max for mount so probably rquota too */ enum rquotastat { RQUOTA_OK = 1, RQUOTA_NOQUOTA = 2, RQUOTA_EPERM = 3 }; typedef string exportpath; struct GETQUOTA1args { exportpath export; int uid; }; enum quotatype { RQUOTA_TYPE_UID = 0, RQUOTA_TYPE_GID = 1 }; struct GETQUOTA2args { exportpath export; quotatype type; int uid; }; struct GETQUOTA1res_ok { int bsize; int active; int bhardlimit; int bsoftlimit; int curblocks; int fhardlimit; int fsoftlimit; int curfiles; int btimeleft; int ftimeleft; }; union GETQUOTA1res switch (rquotastat status) { case RQUOTA_OK: GETQUOTA1res_ok quota; default: void; }; program RQUOTA_PROGRAM { version RQUOTA_V1 { void RQUOTA1_NULL(void) = 0; GETQUOTA1res RQUOTA1_GETQUOTA(GETQUOTA1args) = 1; GETQUOTA1res RQUOTA1_GETACTIVEQUOTA(GETQUOTA1args) = 2; } = 1; version RQUOTA_V2 { void RQUOTA2_NULL(void) = 0; GETQUOTA1res RQUOTA2_GETQUOTA(GETQUOTA2args) = 1; GETQUOTA1res RQUOTA2_GETACTIVEQUOTA(GETQUOTA2args) = 2; } = 2; } = 100011; libnfs-libnfs-4.0.0/tests/000077500000000000000000000000001343063627400154155ustar00rootroot00000000000000libnfs-libnfs-4.0.0/tests/CMakeLists.txt000066400000000000000000000026471343063627400201660ustar00rootroot00000000000000find_library(DL_LIBRARY dl) set(SOURCES prog_access prog_access2 prog_chmod prog_chown prog_create prog_fchmod prog_fchown prog_fstat prog_ftruncate prog_lchmod prog_lchown prog_link prog_lseek prog_lstat prog_mkdir prog_mknod prog_mount prog_open_read prog_open_write prog_opendir prog_rename prog_rmdir prog_stat prog_statvfs prog_symlink prog_timeout prog_truncate prog_unlink prog_utimes) foreach(TARGET ${SOURCES}) add_executable(${TARGET} ${TARGET}.c) target_link_libraries(${TARGET} ${CORE_LIBRARIES}) add_dependencies(${TARGET} nfs) endforeach() add_library(ld_timeout SHARED ld_timeout.c) set_target_properties(ld_timeout PROPERTIES PREFIX "") target_link_libraries(ld_timeout ${CORE_LIBRARIES} ${DL_LIBRARY}) add_dependencies(ld_timeout nfs) file(GLOB TESTS test_*.sh) file(COPY functions.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) foreach(TEST ${TESTS}) file(COPY ${TEST} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) add_test(NAME ${TEST} COMMAND ${TEST} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endforeach() add_definitions("-D_U_=__attribute__((unused))") libnfs-libnfs-4.0.0/tests/Makefile.am000066400000000000000000000021331343063627400174500ustar00rootroot00000000000000AM_CPPFLAGS = -I${srcdir}/../include -I${srcdir}/../include/nfsc \ "-D_U_=__attribute__((unused))" \ "-D_R_(A,B)=__attribute__((format(printf,A,B)))" AM_CFLAGS = $(WARN_CFLAGS) LDADD = ../lib/libnfs.la noinst_PROGRAMS = prog_access prog_access2 prog_chmod prog_chown prog_create \ prog_fchmod prog_fchown prog_fstat prog_ftruncate prog_lchmod \ prog_lchown prog_link prog_lseek prog_lstat prog_mkdir \ prog_mknod prog_mount prog_opendir prog_open_read prog_open_write \ prog_rename prog_rmdir prog_stat prog_statvfs prog_symlink \ prog_timeout prog_truncate prog_unlink prog_utimes EXTRA_PROGRAMS = ld_timeout CLEANFILES = ld_timeout.o ld_timeout.so ld_timeout_SOURCES = ld_timeout.c ld_timeout_CFLAGS = $(AM_CFLAGS) -fPIC bin_SCRIPTS = ld_timeout.so ld_timeout.o: ld_timeout-ld_timeout.o $(LIBTOOL) --mode=link $(CC) -o $@ $^ ld_timeout.so: ld_timeout.o $(CC) -shared -o ld_timeout.so ld_timeout.o -ldl T = `ls test_*.sh` test: $(noinst_PROGRAMS) for TEST in $(T); do \ echo "Running $$TEST"; \ echo "--------------"; \ sh $$TEST || exit 1; \ echo "--------------"; \ echo; \ done libnfs-libnfs-4.0.0/tests/README000066400000000000000000000003251343063627400162750ustar00rootroot00000000000000Testsuite for libnfs. To run the tests: make VERSION=3 test or make VERSION=4 test The tests will ask for your password as it needs sudo access to run exportfs to create/remove the share we use for testing. libnfs-libnfs-4.0.0/tests/functions.sh000077500000000000000000000007101343063627400177620ustar00rootroot00000000000000TESTDIR=`pwd`/testdata TESTSHARE="127.0.0.1:${TESTDIR}" TESTURL="nfs://127.0.0.1${TESTDIR}" # Which version of NFS to test for VERS=${VERSION:-3} start_share() { rm -rf "${TESTDIR}" 2>/dev/null mkdir "${TESTDIR}" 2>/dev/null sudo exportfs -o rw,insecure,no_root_squash "${TESTSHARE}" } stop_share() { sudo exportfs -u "${TESTSHARE}" rm -rf "${TESTDIR}" } success() { echo "[OK]" } failure() { echo "[FAILED]" exit 1 } libnfs-libnfs-4.0.0/tests/ld_timeout.c000066400000000000000000000043251343063627400177320ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) 2017 by Ronnie Sahlberg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #ifndef discard_const #define discard_const(ptr) ((void *)((intptr_t)(ptr))) #endif #define PRINTF(fmt, args...) \ do { \ fprintf(stderr,"ld_nfs: "); \ fprintf(stderr, (fmt), ##args); \ fprintf(stderr,"\n"); \ } while (0); int timeout_start = 0; int (*real_rpc_service)(struct rpc_context *rpc, int revents); int rpc_service(struct rpc_context *rpc, int revents) { static int call_idx = 0; call_idx++; if (call_idx >= timeout_start) { PRINTF("sleep for 1 seconds causing a timeout"); sleep(1); /* Strip off all the POLLINs so that we will not try * to process them in rpc_service and instead fall-through * to the rpc_timeout_scan() and handle the PDUs there * instead. */ revents &= ~POLLIN; } return real_rpc_service(rpc, revents); } static void __attribute__((constructor)) _init(void) { /* Start timing out calls at this index */ if (getenv("TIMEOUT_START") != NULL) { timeout_start = atoi(getenv("TIMEOUT_START")); } real_rpc_service = dlsym(RTLD_NEXT, "rpc_service"); } libnfs-libnfs-4.0.0/tests/prog_access.c000066400000000000000000000044351343063627400200570ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_access \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int flags = 0; if (argc != 5) { usage(); } if (strstr(argv[4], "R_OK")) { flags |= R_OK; } if (strstr(argv[4], "W_OK")) { flags |= W_OK; } if (strstr(argv[4], "X_OK")) { flags |= X_OK; } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_access(nfs, argv[3], flags)) { fprintf(stderr, "Failed to access(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_access2.c000066400000000000000000000046041343063627400201370ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_access \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int flags = 0; if (argc != 5) { usage(); } if (strstr(argv[4], "R_OK")) { flags |= R_OK; } if (strstr(argv[4], "W_OK")) { flags |= W_OK; } if (strstr(argv[4], "X_OK")) { flags |= X_OK; } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if ((ret = nfs_access2(nfs, argv[3])) != flags) { fprintf(stderr, "access2() failed. Received mode %08x but " "expected %08x: %s\n", ret, flags, nfs_get_error(nfs)); ret = 1; goto finished; } ret = 0; finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_chmod.c000066400000000000000000000041661343063627400177110ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_chmod " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int mode; if (argc != 5) { usage(); } mode = strtol(argv[4], NULL, 8); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chmod(nfs, argv[3], mode)) { fprintf(stderr, "Failed to chmod(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_chown.c000066400000000000000000000042451343063627400177330ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_chown " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int uid, gid; if (argc != 6) { usage(); } uid = strtol(argv[4], NULL, 10); gid = strtol(argv[5], NULL, 10); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chown(nfs, argv[3], uid, gid)) { fprintf(stderr, "Failed to chown(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_create.c000066400000000000000000000044271343063627400200620ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_create " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int mode; struct nfsfh *fh; if (argc != 5) { usage(); } mode = strtol(argv[4], NULL, 8); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_creat(nfs, argv[3], mode, &fh)) { fprintf(stderr, "Failed to creat(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_close(nfs, fh)) { fprintf(stderr, "Failed to close(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_fchmod.c000066400000000000000000000046231343063627400200550ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_fchmod " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int mode; struct nfsfh *fh; if (argc != 5) { usage(); } mode = strtol(argv[4], NULL, 8); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_open(nfs, argv[3], O_RDWR, &fh)) { fprintf(stderr, "Failed to open file : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_fchmod(nfs, fh, mode)) { fprintf(stderr, "Failed to fchmod(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_close(nfs, fh)) { fprintf(stderr, "Failed to close(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_fchown.c000066400000000000000000000047021343063627400200770ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_fchown " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int uid, gid; struct nfsfh *fh; if (argc != 6) { usage(); } uid = strtol(argv[4], NULL, 10); gid = strtol(argv[5], NULL, 10); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_open(nfs, argv[3], O_RDWR, &fh)) { fprintf(stderr, "Failed to open file : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_fchown(nfs, fh, uid, gid)) { fprintf(stderr, "Failed to fchown(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_close(nfs, fh)) { fprintf(stderr, "Failed to close(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_fstat.c000066400000000000000000000050541343063627400177350ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_fstat \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs; struct nfsfh *nfsfh; struct nfs_url *url; struct nfs_stat_64 st; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); exit(1); } if (nfs_open(nfs, argv[3], O_RDONLY, &nfsfh)) { fprintf(stderr, "Failed to open file : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_fstat64(nfs, nfsfh, &st)) { fprintf(stderr, "Failed to stat file : %s\n", nfs_get_error(nfs)); exit(1); } printf("nfs_ino:%" PRIu64 "\n", st.nfs_ino); printf("nfs_mode:%" PRIo64 "\n", st.nfs_mode); printf("nfs_nlink:%" PRIu64 "\n", st.nfs_nlink); printf("nfs_uid:%" PRIu64 "\n", st.nfs_uid); printf("nfs_gid:%" PRIu64 "\n", st.nfs_gid); printf("nfs_size:%" PRIu64 "\n", st.nfs_size); printf("nfs_atime:%" PRIu64 "\n", st.nfs_atime); printf("nfs_mtime:%" PRIu64 "\n", st.nfs_mtime); printf("nfs_ctime:%" PRIu64 "\n", st.nfs_ctime); nfs_destroy_url(url); nfs_close(nfs, nfsfh); nfs_destroy_context(nfs); return 0; } libnfs-libnfs-4.0.0/tests/prog_ftruncate.c000066400000000000000000000042501343063627400206040ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_ftruncate \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs; struct nfsfh *nfsfh; struct nfs_url *url; uint64_t length; if (argc != 5) { usage(); } length = strtol(argv[4], NULL, 10); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); exit(1); } if (nfs_open(nfs, argv[3], O_WRONLY, &nfsfh)) { fprintf(stderr, "Failed to open file : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_ftruncate(nfs, nfsfh, length)) { fprintf(stderr, "Failed to ftruncate file : %s\n", nfs_get_error(nfs)); exit(1); } nfs_destroy_url(url); nfs_close(nfs, nfsfh); nfs_destroy_context(nfs); return 0; } libnfs-libnfs-4.0.0/tests/prog_lchmod.c000066400000000000000000000041711343063627400200610ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_lchmod " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int mode; if (argc != 5) { usage(); } mode = strtol(argv[4], NULL, 8); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_lchmod(nfs, argv[3], mode)) { fprintf(stderr, "Failed to lchmod(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_lchown.c000066400000000000000000000042501343063627400201030ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_lchown " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int uid, gid; if (argc != 6) { usage(); } uid = strtol(argv[4], NULL, 10); gid = strtol(argv[5], NULL, 10); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_lchown(nfs, argv[3], uid, gid)) { fprintf(stderr, "Failed to lchown(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_link.c000066400000000000000000000040441343063627400175470ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_link \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; if (argc != 5) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_link(nfs, argv[3], argv[4])) { fprintf(stderr, "Failed to link: %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_lseek.c000066400000000000000000000113211343063627400177110ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_lseek \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs; struct nfsfh *nfsfh; struct nfs_url *url; struct nfs_stat_64 st; uint64_t current; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); exit(1); } if (nfs_open(nfs, argv[3], O_RDONLY, &nfsfh)) { fprintf(stderr, "Failed to open file : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_fstat64(nfs, nfsfh, &st)) { fprintf(stderr, "Failed to stat file : %s\n", nfs_get_error(nfs)); exit(1); } printf("File size:%" PRIu64 "\n", st.nfs_size); printf("Try lseek(SEEK_SET, 512)\n"); if (nfs_lseek(nfs, nfsfh, 512, SEEK_SET, ¤t)) { fprintf(stderr, "lseek failed: %s\n", nfs_get_error(nfs)); exit(1); } if (current != 512) { fprintf(stderr, "lseek returned wrong current offset." "Expected %d but got %" PRIu64 "\n", 512, current); exit(1); } printf("Try lseek(SEEK_CUR, 0)\n"); if (nfs_lseek(nfs, nfsfh, 0, SEEK_CUR, ¤t)) { fprintf(stderr, "lseek failed: %s\n", nfs_get_error(nfs)); exit(1); } if (current != 512) { fprintf(stderr, "lseek returned wrong current offset." "Expected %d but got %" PRIu64 "\n", 512, current); exit(1); } printf("Try lseek(SEEK_CUR, 4)\n"); if (nfs_lseek(nfs, nfsfh, 4, SEEK_CUR, ¤t)) { fprintf(stderr, "lseek failed: %s\n", nfs_get_error(nfs)); exit(1); } if (current != 516) { fprintf(stderr, "lseek returned wrong current offset." "Expected %d but got %" PRIu64 "\n", 516, current); exit(1); } printf("Try lseek(SEEK_CUR, -16)\n"); if (nfs_lseek(nfs, nfsfh, -16, SEEK_CUR, ¤t)) { fprintf(stderr, "lseek failed: %s\n", nfs_get_error(nfs)); exit(1); } if (current != 500) { fprintf(stderr, "lseek returned wrong current offset." "Expected %d but got %" PRIu64 "\n", 500, current); exit(1); } printf("Try lseek(SEEK_CUR, -500)\n"); if (nfs_lseek(nfs, nfsfh, -500, SEEK_CUR, ¤t)) { fprintf(stderr, "lseek failed: %s\n", nfs_get_error(nfs)); exit(1); } if (current != 0) { fprintf(stderr, "lseek returned wrong current offset." "Expected %d but got %" PRIu64 "\n", 0, current); exit(1); } printf("Try lseek(SEEK_CUR, -1)\n"); if (nfs_lseek(nfs, nfsfh, -1, SEEK_CUR, ¤t) >= 0) { fprintf(stderr, "lseek should have failed.\n"); exit(1); } if (current != 0) { fprintf(stderr, "lseek returned wrong current offset." "Expected %d but got %" PRIu64 "\n", 0, current); exit(1); } printf("Try lseek(SEEK_END, -500)\n"); if (nfs_lseek(nfs, nfsfh, -500, SEEK_END, ¤t)) { fprintf(stderr, "lseek failed: %s\n", nfs_get_error(nfs)); exit(1); } if (current != st.nfs_size - 500) { fprintf(stderr, "lseek returned wrong current offset." "Expected %" PRIu64 " but got %" PRIu64 "\n", st.nfs_size - 500, current); exit(1); } nfs_destroy_url(url); nfs_close(nfs, nfsfh); nfs_destroy_context(nfs); return 0; } libnfs-libnfs-4.0.0/tests/prog_lstat.c000066400000000000000000000047431343063627400177470ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_lstat \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; struct nfs_stat_64 st; int ret = 0; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } nfs_set_timeout(nfs, 1000); url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_lstat64(nfs, argv[3], &st)) { fprintf(stderr, "Failed to lstat file : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } printf("nfs_ino:%" PRIu64 "\n", st.nfs_ino); printf("nfs_mode:%" PRIo64 "\n", st.nfs_mode); printf("nfs_nlink:%" PRIu64 "\n", st.nfs_nlink); printf("nfs_uid:%" PRIu64 "\n", st.nfs_uid); printf("nfs_gid:%" PRIu64 "\n", st.nfs_gid); printf("nfs_size:%" PRIu64 "\n", st.nfs_size); printf("nfs_atime:%" PRIu64 "\n", st.nfs_atime); printf("nfs_mtime:%" PRIu64 "\n", st.nfs_mtime); printf("nfs_ctime:%" PRIu64 "\n", st.nfs_ctime); finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_mkdir.c000066400000000000000000000040211343063627400177130ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_mkdir \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_mkdir(nfs, argv[3])) { fprintf(stderr, "Failed to mkdir: %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_mknod.c000066400000000000000000000042621343063627400177240ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_mknod " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int mode, dev; if (argc != 6) { usage(); } mode = strtol(argv[4], NULL, 8); dev = strtol(argv[5], NULL, 16); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_mknod(nfs, argv[3], mode, dev)) { fprintf(stderr, "Failed to unlink: %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_mount.c000066400000000000000000000032771343063627400177630ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_mount \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; if (argc != 2) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_open_read.c000066400000000000000000000064301343063627400205470ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_open_read " "\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int flags = 0, count, res, pos; struct nfsfh *fh; char buf[1024]; if (argc != 5) { usage(); } if (strstr(argv[4], "O_RDONLY")) { flags |= O_RDONLY; } if (strstr(argv[4], "O_RDWR")) { flags |= O_RDWR; } if (strstr(argv[4], "O_WRONLY")) { flags |= O_WRONLY; } if (strstr(argv[4], "O_NOFOLLOW")) { flags |= O_NOFOLLOW; } if (strstr(argv[4], "O_APPEND")) { flags |= O_APPEND; } if (strstr(argv[4], "O_TRUNC")) { flags |= O_TRUNC; } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_open(nfs, argv[3],flags, &fh)) { fprintf(stderr, "Failed to open(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } count = nfs_read(nfs, fh, sizeof(buf), buf); if (count < 0) { fprintf(stderr, "Failed to read(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } pos = 0; while (count) { res = write(1, &buf[pos], count); if (res < 0) { fprintf(stderr, "write() failed\n"); ret = 1; goto finished; } count -= res; pos += res; } if (nfs_close(nfs, fh)) { fprintf(stderr, "Failed to close(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_open_write.c000066400000000000000000000063011343063627400207630ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_open_write " "\t\n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int flags = 0, count; struct nfsfh *fh; if (argc != 6) { usage(); } if (strstr(argv[4], "O_RDONLY")) { flags |= O_RDONLY; } if (strstr(argv[4], "O_RDWR")) { flags |= O_RDWR; } if (strstr(argv[4], "O_WRONLY")) { flags |= O_WRONLY; } if (strstr(argv[4], "O_NOFOLLOW")) { flags |= O_NOFOLLOW; } if (strstr(argv[4], "O_APPEND")) { flags |= O_APPEND; } if (strstr(argv[4], "O_TRUNC")) { flags |= O_TRUNC; } if (strstr(argv[4], "O_CREAT")) { flags |= O_CREAT; } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_open(nfs, argv[3],flags, &fh)) { fprintf(stderr, "Failed to open(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (strlen(argv[5]) > 0) { count = nfs_write(nfs, fh, strlen(argv[5]), argv[5]); if (count < 0) { fprintf(stderr, "Failed to write(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } } if (nfs_close(nfs, fh)) { fprintf(stderr, "Failed to close(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_opendir.c000066400000000000000000000044571343063627400202620ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_opendir \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; struct nfsdirent *nfsdirent; struct nfsdir *nfsdir; int ret = 0; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } nfs_set_timeout(nfs, 300); url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_opendir(nfs, argv[3], &nfsdir)) { fprintf(stderr, "Failed to opendir() : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } while((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) { if (!strcmp(nfsdirent->name, ".") || !strcmp(nfsdirent->name, "..")) { continue; } printf("%s\n", nfsdirent->name); } nfs_closedir(nfs, nfsdir); finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_rename.c000066400000000000000000000040521343063627400200600ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_rename \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; if (argc != 5) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_rename(nfs, argv[3], argv[4])) { fprintf(stderr, "Failed to rename: %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_rmdir.c000066400000000000000000000040211343063627400177220ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_rmdir \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_rmdir(nfs, argv[3])) { fprintf(stderr, "Failed to rmdir: %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_stat.c000066400000000000000000000047371343063627400175760ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_stat \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; struct nfs_stat_64 st; int ret = 0; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } nfs_set_timeout(nfs, 300); url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_stat64(nfs, argv[3], &st)) { fprintf(stderr, "Failed to stat file : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } printf("nfs_ino:%" PRIu64 "\n", st.nfs_ino); printf("nfs_mode:%" PRIo64 "\n", st.nfs_mode); printf("nfs_nlink:%" PRIu64 "\n", st.nfs_nlink); printf("nfs_uid:%" PRIu64 "\n", st.nfs_uid); printf("nfs_gid:%" PRIu64 "\n", st.nfs_gid); printf("nfs_size:%" PRIu64 "\n", st.nfs_size); printf("nfs_atime:%" PRIu64 "\n", st.nfs_atime); printf("nfs_mtime:%" PRIu64 "\n", st.nfs_mtime); printf("nfs_ctime:%" PRIu64 "\n", st.nfs_ctime); finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_statvfs.c000066400000000000000000000050171343063627400203050ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_statvfs \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; struct nfs_statvfs_64 svfs; int ret = 0; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } nfs_set_timeout(nfs, 300); url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_statvfs64(nfs, argv[3], &svfs)) { fprintf(stderr, "statvfs64 failed : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } printf("bsize:%" PRIu64 "\n", svfs.f_bsize); printf("frsize:%" PRIu64 "\n", svfs.f_frsize); printf("blocks:%" PRIu64 "\n", svfs.f_blocks); printf("bfree:%" PRIu64 "\n", svfs.f_bfree); printf("bavail:%" PRIu64 "\n", svfs.f_bavail); printf("files:%" PRIu64 "\n", svfs.f_files); printf("ffree:%" PRIu64 "\n", svfs.f_ffree); printf("favail:%" PRIu64 "\n", svfs.f_favail); printf("fsid:%" PRIu64 "\n", svfs.f_fsid); printf("namemax:%" PRIu64 "\n", svfs.f_namemax); finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_symlink.c000066400000000000000000000051611343063627400203010ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_symlink \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; char buf[1024]; if (argc != 5) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_symlink(nfs, argv[3], argv[4])) { fprintf(stderr, "Failed to create symlink: %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } memset(buf, 0, sizeof(buf)); if (nfs_readlink(nfs, argv[4], buf, sizeof(buf))) { fprintf(stderr, "Failed to read symlink: %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (strcmp(argv[3], buf)) { fprintf(stderr, "Symlink target did not read back correctly." "Expected \"%s\" Got \"%s\"\n", buf, argv[3]); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_timeout.c000066400000000000000000000046151343063627400203040ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_timeout \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; struct nfs_stat_64 st; if (argc != 2) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } nfs_set_timeout(nfs, 1000); url = nfs_parse_url_full(nfs, argv[argc - 1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); goto finished; } if (nfs_stat64(nfs, url->file, &st)) { fprintf(stderr, "Failed to stat file : %s\n", nfs_get_error(nfs)); goto finished; } printf("nfs_ino:%" PRIu64 "\n", st.nfs_ino); printf("nfs_mode:%" PRIo64 "\n", st.nfs_mode); printf("nfs_nlink:%" PRIu64 "\n", st.nfs_nlink); printf("nfs_uid:%" PRIu64 "\n", st.nfs_uid); printf("nfs_gid:%" PRIu64 "\n", st.nfs_gid); printf("nfs_size:%" PRIu64 "\n", st.nfs_size); printf("nfs_atime:%" PRIu64 "\n", st.nfs_atime); printf("nfs_mtime:%" PRIu64 "\n", st.nfs_mtime); printf("nfs_ctime:%" PRIu64 "\n", st.nfs_ctime); finished: nfs_destroy_url(url); nfs_destroy_context(nfs); /* Always return 0 as we want to catch valgrind * overriding this with return code 1 upon memory leaks. */ return 0; } libnfs-libnfs-4.0.0/tests/prog_truncate.c000066400000000000000000000045361343063627400204450ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_truncate \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs; struct nfs_url *url; uint64_t length; struct nfs_stat_64 st; if (argc != 5) { usage(); } length = strtol(argv[4], NULL, 10); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); exit(1); } if (nfs_truncate(nfs, argv[3], length)) { fprintf(stderr, "Failed to truncate file : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_stat64(nfs, argv[3], &st)) { fprintf(stderr, "Failed to stat file : %s\n", nfs_get_error(nfs)); exit(1); } if (st.nfs_size != length) { fprintf(stderr, "Unexpected file size. Expected %d got %d\n", (int)length, (int)st.nfs_size); exit(1); } nfs_destroy_url(url); nfs_destroy_context(nfs); return 0; } libnfs-libnfs-4.0.0/tests/prog_unlink.c000066400000000000000000000040241343063627400201100ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_unlink \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; if (argc != 4) { usage(); } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_unlink(nfs, argv[3])) { fprintf(stderr, "Failed to unlink: %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/prog_utimes.c000066400000000000000000000044601343063627400201220ustar00rootroot00000000000000/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ /* Copyright (C) by Ronnie Sahlberg 2017 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libnfs.h" void usage(void) { fprintf(stderr, "Usage: prog_utimes \n"); exit(1); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; int atime, mtime; struct timeval times[2]; if (argc != 6) { usage(); } atime = strtol(argv[4], NULL, 10); mtime = strtol(argv[5], NULL, 10); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); ret = 1; goto finished; } memset(×[0], 0, 2 * sizeof(struct timeval)); times[0].tv_sec = atime; times[1].tv_sec = mtime; if (nfs_utimes(nfs, argv[3], ×[0])) { fprintf(stderr, "Failed to access(): %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } finished: nfs_destroy_url(url); nfs_destroy_context(nfs); return ret; } libnfs-libnfs-4.0.0/tests/test_0100_ls_basic.sh000077500000000000000000000006261343063627400212360ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "basic ls test" start_share echo -n "Testing nfs-ls on root of export ... " ../utils/nfs-ls "${TESTURL}" > /dev/null || failure success echo -n "Create a file and verify nfs-ls can see it ... " touch "${TESTDIR}/testfile" ../utils/nfs-ls "${TESTURL}" > "${TESTDIR}/output" || failure grep testfile "${TESTDIR}/output" > /dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0101_ls_discover_server.sh000077500000000000000000000004101343063627400233510ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "discover servers test" start_share echo -n "Testing nfs-ls to discover servers ... " ../utils/nfs-ls -D nfs:// > "${TESTDIR}/output" || failure grep nfs:// "${TESTDIR}/output" > /dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0102_ls_discover_shares.sh000077500000000000000000000004411343063627400233350ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "discover shares test" start_share echo -n "Testing nfs-ls to discover shares on a server ... " ../utils/nfs-ls -D nfs://127.0.0.1 > "${TESTDIR}/output" || failure grep "${TESTURL}" "${TESTDIR}/output" > /dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0200_stat.sh000077500000000000000000000026741343063627400204400ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_stat64() tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null chmod 644 "${TESTDIR}/testfile" ln -s testfile "${TESTDIR}/lstat1" echo -n "test nfs_stat64() ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." /testfile > "${TESTDIR}/output" || failure success echo -n "test nfs_ino ... " INO=`stat --printf="%i" testdata/testfile` grep "nfs_ino:$INO" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mode ... " grep "nfs_mode:100644" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_nlink ... " grep "nfs_nlink:1" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_uid ... " grep "nfs_uid:$UID" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_gid ... " grep "nfs_gid:$GID" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_size ... " grep "nfs_size:32768" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_atime ... " ATIME=`stat --printf="%X" testdata/testfile` grep "nfs_atime:$ATIME" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mtime ... " MTIME=`stat --printf="%Y" testdata/testfile` grep "nfs_mtime:$MTIME" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_ctime ... " CTIME=`stat --printf="%Z" testdata/testfile` grep "nfs_ctime:$CTIME" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0201_stat_paths.sh000077500000000000000000000027041343063627400216320ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} nfs_stat64() path tests." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_stat64() for a root file (abs) (1)... " touch "${TESTDIR}/stat1" ./prog_stat "${TESTURL}/?version=${VERS}" "." /stat1 >/dev/null || failure success echo -n "test nfs_stat64() for a root file (rel) (2)... " ./prog_stat "${TESTURL}/?version=${VERS}" "." stat1 >/dev/null || failure success echo -n "test nfs_stat64() for a subdir file (abs) (3)... " touch "${TESTDIR}/subdir/stat3" ./prog_stat "${TESTURL}/?version=${VERS}" "." /subdir/stat3 >/dev/null || failure success echo -n "test nfs_stat64() for a subdir file (rel) (4)... " ./prog_stat "${TESTURL}/?version=${VERS}" "." subdir/stat3 >/dev/null || failure success echo -n "test nfs_stat64() from a different cwd (rel) (5)... " ./prog_stat "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/stat3 >/dev/null || failure success echo -n "test nfs_stat64() outside the share (rel) (6)... " ./prog_stat "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/stat3 >/dev/null 2>&1 && failure success echo -n "test nfs_lstat64() when target is a symlink (7)... " touch "${TESTDIR}/stat7" ln -s stat7 "${TESTDIR}/symlink7" ./prog_stat "${TESTURL}/?version=${VERS}" "." symlink7 >"${TESTDIR}/output" || failure success echo -n "test nfs_lstat() on the underlying file ... " grep "nfs_mode:100664" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0202_stat_valgrind_leak_check.sh000077500000000000000000000027121343063627400244520ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_stat64()" start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_stat64() (1) ... " touch "${TESTDIR}/stat1" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_stat "${TESTURL}/?version=${VERS}" "." /stat1 >/dev/null 2>&1 || failure success echo -n "test nfs_stat64() (2) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_stat "${TESTURL}/?version=${VERS}" "." stat1 >/dev/null 2>&1 || failure success echo -n "test nfs_stat64() (3) ... " touch "${TESTDIR}/subdir/stat3" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_stat "${TESTURL}/?version=${VERS}" "." /subdir/stat3 >/dev/null 2>&1 || failure success echo -n "test nfs_stat64() (4) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_stat "${TESTURL}/?version=${VERS}" "." subdir/stat3 >/dev/null 2>&1 || failure success echo -n "test nfs_stat64() (5) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_stat "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/stat3 >/dev/null 2>&1 || failure success echo -n "test nfs_stat64() (6) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_stat "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/stat3 2>/dev/null || expr $? != 99 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0203_stat_symlink.sh000077500000000000000000000026761343063627400222130ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} nfs_stat64() test on symlink." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null chmod 644 "${TESTDIR}/testfile" ln -s testfile "${TESTDIR}/lstat1" echo -n "test nfs_stat64() ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." /lstat1 > "${TESTDIR}/output" || failure success echo -n "test nfs_ino ... " INO=`stat --printf="%i" testdata/testfile` grep "nfs_ino:$INO" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mode ... " grep "nfs_mode:100644" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_nlink ... " grep "nfs_nlink:1" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_uid ... " grep "nfs_uid:$UID" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_gid ... " grep "nfs_gid:$GID" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_size ... " grep "nfs_size:32768" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_atime ... " ATIME=`stat --printf="%X" testdata/testfile` grep "nfs_atime:$ATIME" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mtime ... " MTIME=`stat --printf="%Y" testdata/testfile` grep "nfs_mtime:$MTIME" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_ctime ... " CTIME=`stat --printf="%Z" testdata/testfile` grep "nfs_ctime:$CTIME" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0210_fstat.sh000077500000000000000000000026251343063627400206030ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_fstat64() test." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null chmod 644 testdata/testfile echo -n "test nfs_fstat64() ... " ./prog_fstat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "test nfs_ino ... " INO=`stat --printf="%i" testdata/testfile` grep "nfs_ino:$INO" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mode ... " grep "nfs_mode:100644" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_nlink ... " grep "nfs_nlink:1" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_uid ... " grep "nfs_uid:$UID" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_gid ... " grep "nfs_gid:$GID" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_size ... " grep "nfs_size:32768" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_atime ... " ATIME=`stat --printf="%X" testdata/testfile` grep "nfs_atime:$ATIME" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mtime ... " MTIME=`stat --printf="%Y" testdata/testfile` grep "nfs_mtime:$MTIME" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_ctime ... " CTIME=`stat --printf="%Z" testdata/testfile` grep "nfs_ctime:$CTIME" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0211_fstat_paths.sh000077500000000000000000000021771343063627400220050ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_fstat64() test." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_fstat64() for a root file (abs) (1)... " touch "${TESTDIR}/fstat1" ./prog_fstat "${TESTURL}/?version=${VERS}" "." /fstat1 >/dev/null || failure success echo -n "test nfs_fstat64() for a root file (rel) (2)... " ./prog_fstat "${TESTURL}/?version=${VERS}" "." fstat1 >/dev/null || failure success echo -n "test nfs_fstat64() for a subdir file (abs) (3)... " touch "${TESTDIR}/subdir/fstat3" ./prog_fstat "${TESTURL}/?version=${VERS}" "." /subdir/fstat3 >/dev/null || failure success echo -n "test nfs_fstat64() for a subdir file (rel) (4)... " ./prog_fstat "${TESTURL}/?version=${VERS}" "." subdir/fstat3 >/dev/null || failure success echo -n "test nfs_fstat64() from a different cwd (rel) (5)... " ./prog_fstat "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/fstat3 >/dev/null || failure success echo -n "test nfs_fstat64() outside the share (rel) (6)... " ./prog_fstat "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/fstat3 >/dev/null 2>&1 && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0212_fstat_valgrind_leak_check.sh000077500000000000000000000027401343063627400246220ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_fstat64()." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_fstat64() (1) ... " touch "${TESTDIR}/fstat1" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_fstat "${TESTURL}/?version=${VERS}" "." /fstat1 >/dev/null 2>&1 || failure success echo -n "test nfs_fstat64() (2) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_fstat "${TESTURL}/?version=${VERS}" "." fstat1 >/dev/null 2>&1 || failure success echo -n "test nfs_fstat64() (3) ... " touch "${TESTDIR}/subdir/fstat3" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_fstat "${TESTURL}/?version=${VERS}" "." /subdir/fstat3 >/dev/null 2>&1 || failure success echo -n "test nfs_fstat64() (4) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_fstat "${TESTURL}/?version=${VERS}" "." subdir/fstat3 >/dev/null 2>&1 || failure success echo -n "test nfs_fstat64() (5) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_fstat "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/fstat3 >/dev/null 2>&1 || failure success echo -n "test nfs_fstat64() (6) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_fstat "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/fstat3 2>/dev/null || expr $? != 99 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0220_open_paths.sh000077500000000000000000000036431343063627400216240ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic open path tests." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "Open a file in root (abs) (1) ... " echo -n "kangabanga" > "${TESTDIR}/open1" ./prog_open_read "${TESTURL}/?version=${VERS}" "." /open1 O_RDONLY >/dev/null || failure success echo -n "Open a file in root (rel) (2) ... " ./prog_open_read "${TESTURL}/?version=${VERS}" "." open1 O_RDONLY >/dev/null || failure success echo -n "Open a file in a subdir (abs) (3) ... " echo -n "kangabanga" > "${TESTDIR}/subdir/open3" ./prog_open_read "${TESTURL}/?version=${VERS}" "." /subdir/open3 O_RDONLY >/dev/null || failure success echo -n "Open a file in root (rel) (4) ... " ./prog_open_read "${TESTURL}/?version=${VERS}" "." subdir/open3 O_RDONLY >/dev/null || failure success echo -n "Open a file from a different cwd (rel) (5) ... " ./prog_open_read "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/open3 O_RDONLY >/dev/null || failure success echo -n "Open a file outside the share (rel) (5) ... " ./prog_open_read "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/open3 O_RDONLY >/dev/null 2>&1 && failure success echo -n "Create a directory symlink (rel) (6) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "." subdir /subdir4 || failure success echo -n "Open a file in a symlinked subdir (rel) (7) ... " ./prog_open_read "${TESTURL}/?version=${VERS}" "." subdir4/open3 O_RDONLY >/dev/null || failure success echo -n "Create a file symlink (rel) (8) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "." open3 /subdir4/open8 || failure success echo -n "Open a symlinked file (rel) (9) ... " ./prog_open_read "${TESTURL}/?version=${VERS}" "." subdir4/open8 O_RDONLY >/dev/null || failure success echo -n "Open a symlinked file with O_NOFOLLOW (rel) (10) ... " ./prog_open_read "${TESTURL}/?version=${VERS}" "." subdir/open8 O_RDONLY,O_NOFOLLOW 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0222_open_valgrind_leak_check.sh000077500000000000000000000030631343063627400244420ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_open()." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_open() (1) ... " echo -n "kangabanga" > "${TESTDIR}/open1" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_open_read "${TESTURL}/?version=${VERS}" "." /open1 O_RDONLY >/dev/null 2>&1 || failure success echo -n "test nfs_open() (2) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_open_read "${TESTURL}/?version=${VERS}" "." open1 O_RDONLY >/dev/null 2>&1 || failure success echo -n "test nfs_open() (3) ... " echo -n "kangabanga" > "${TESTDIR}/subdir/open3" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_open_read "${TESTURL}/?version=${VERS}" "." /subdir/open3 O_RDONLY >/dev/null 2>&1 || failure success echo -n "test nfs_open() (4) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_open_read "${TESTURL}/?version=${VERS}" "." subdir/open3 O_RDONLY >/dev/null 2>&1 || failure success echo -n "test nfs_open() (5) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_open_read "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/open3 O_RDONLY >/dev/null 2>&1 || failure success echo -n "test nfs_open() (6) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_open_read "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/open3 O_RDONLY 2>/dev/null || expr $? != 99 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0223_open_O_TRUNC.sh000077500000000000000000000014341343063627400216550ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Open(O_TRUNC) test." start_share mkdir "${TESTDIR}/subdir" echo -n "test open(O_WRONLY|O_TRUNC) (1) ... " echo -n "kangabanga" > "${TESTDIR}/open1" ./prog_open_write "${TESTURL}/?version=${VERS}" "." /open1 O_WRONLY,O_TRUNC "" >/dev/null || failure success echo -n "verify the file got truncated ... " expr `stat --printf="%s" "${TESTDIR}/open1"` "==" "0" >/dev/null || failure success echo -n "test open(O_RDONLY|O_TRUNC) (2) ... " echo -n "kangabanga" > "${TESTDIR}/open1" ./prog_open_write "${TESTURL}/?version=${VERS}" "." /open1 O_RDONLY,O_TRUNC "" >/dev/null || failure success echo -n "verify the file did not get truncated ... " expr `stat --printf="%s" "${TESTDIR}/open1"` "==" "10" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0224_open_O_APPEND.sh000077500000000000000000000010371343063627400217310ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Open(O_APPEND) test." start_share mkdir "${TESTDIR}/subdir" echo -n "test open(O_APPEND) (1) ... " echo -n "GOAT:" > "${TESTDIR}/open1" ./prog_open_write "${TESTURL}/?version=${VERS}" "." /open1 O_WRONLY,O_APPEND "NieR" >/dev/null || failure ./prog_open_write "${TESTURL}/?version=${VERS}" "." /open1 O_WRONLY,O_APPEND "Automata" >/dev/null || failure success echo -n "verify it got appended ... " grep "GOAT:NieRAutomata" "${TESTDIR}/open1" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0225_open_O_CREAT.sh000077500000000000000000000005711343063627400216230ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Open(O_CREAT) test." start_share echo -n "test open(O_RDWR|O_CREAT) (1) ... " ./prog_open_write "${TESTURL}/?version=${VERS}" "." /create1 O_WRONLY,O_CREAT LordOfCinder >/dev/null || failure success echo -n "Verify the file content ... " grep LordOfCinder "${TESTDIR}/create1" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0230_creat_paths.sh000077500000000000000000000025431343063627400217600ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic creat path tests." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "Create a file in root (abs) (1) ... " ./prog_create "${TESTURL}/?version=${VERS}" "." /creat1 0750 || failure success echo -n "Stat the new file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." creat1 > "${TESTDIR}/output" || failure success echo -n "Verifying it is a regular file ... " grep "nfs_mode:100750" "${TESTDIR}/output" >/dev/null || failure success echo -n "Remove the file ... " ./prog_unlink "${TESTURL}/?version=${VERS}" "." /creat1 || failure success echo -n "Create a file in root (rel) (2) ... " ./prog_create "${TESTURL}/?version=${VERS}" "." creat2 0750 || failure success echo -n "Create a file in subdirectory (abs) (3) ... " ./prog_create "${TESTURL}/?version=${VERS}" "." /subdir/creat3 0750 || failure success echo -n "Create a file in subdirectory (rel) (4) ... " ./prog_create "${TESTURL}/?version=${VERS}" "." subdir/creat4 0750 || failure success echo -n "Create a file from a different cwd (rel) (5) ... " ./prog_create "${TESTURL}/?version=${VERS}" "subdir" ../subdir2/creat5 0750 || failure success echo -n "Create a file outside the share (rel) (6) ... " ./prog_create "${TESTURL}/?version=${VERS}" "subdir" ../../subdir2/creat6 0750 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0240_link.sh000077500000000000000000000033761343063627400204260ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic link test." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo "kangabanga" > "${TESTDIR}/testfile" echo -n "Link a root path (abs -> abs) (1) ... " ./prog_link "${TESTURL}/?version=${VERS}" "." /testfile /link1 || failure success echo -n "Link a root path (abs -> rel) (2) ... " ./prog_link "${TESTURL}/?version=${VERS}" "." /testfile link2 || failure success echo -n "Link a root path (rel -> abs) (3) ... " ./prog_link "${TESTURL}/?version=${VERS}" "." testfile /link3 || failure success echo -n "Link a root path (rel -> rel) (4) ... " ./prog_link "${TESTURL}/?version=${VERS}" "." testfile link4 || failure success echo -n "Link a subdir path (abs -> abs) (5) ... " ./prog_link "${TESTURL}/?version=${VERS}" "." /testfile /subdir/link5 || failure success echo -n "Link a subdir path (abs -> rel) (6) ... " ./prog_link "${TESTURL}/?version=${VERS}" "." /subdir/link5 subdir2/link6 || failure success echo -n "Link a subdir path (rel -> abs) (7) ... " ./prog_link "${TESTURL}/?version=${VERS}" "." subdir/link5 /subdir2/link7 || failure success echo -n "Link a subdir path (rel -> rel) (8) ... " ./prog_link "${TESTURL}/?version=${VERS}" "." subdir2/link7 subdir/link8 || failure success echo -n "Link from a different cwd (rel -> rel) (9) ... " ./prog_link "${TESTURL}/?version=${VERS}" "subdir2" link7 ../subdir/link9 || failure success echo -n "Link from outside the share (rel -> rel) (10) ... " ./prog_link "${TESTURL}/?version=${VERS}" "subdir2" ../../link7 ../subdir/link10 2>/dev/null && failure success echo -n "Link to outside the share (rel -> rel) (11) ... " ./prog_link "${TESTURL}/?version=${VERS}" "subdir2" link7 ../../subdir/link11 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0242_link_valgrind_leak_check.sh000077500000000000000000000050431343063627400244400ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_link()." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo "kangabanga" > "${TESTDIR}/testfile" echo -n "test nfs_link() (1) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "." /testfile /link1 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (2) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "." /testfile link2 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (3) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "." testfile /link3 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (4) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "." testfile link4 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (5) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "." /testfile /subdir/link5 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (6) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "." /subdir/link5 subdir2/link6 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (7) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "." subdir/link5 /subdir2/link7 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (8) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "." subdir2/link7 /subdir/link8 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (9) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "subdir2" link7 ../subdir/link9 >/dev/null 2>&1 || failure success echo -n "test nfs_link() (10) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "subdir2" ../../link7 ../subdir/link10 2>/dev/null || expr $? != 99 >/dev/null || failure success echo -n "test nfs_link() (11) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_link "${TESTURL}/?version=${VERS}" "subdir2" link7 ../../subdir/link11 2>/dev/null || expr $? != 99 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0250_rename.sh000077500000000000000000000065251343063627400207400ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic rename test." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "Rename a root path (abs -> abs) ... " echo "kangabanga" > "${TESTDIR}/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." /testfile /renamed1 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/renamed1" >/dev/null || failure success echo -n "Rename a root path (rel -> abs) ... " echo "kangabanga" > "${TESTDIR}/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." testfile /renamed2 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/renamed2" >/dev/null || failure success echo -n "Rename a root path (rel -> rel) ... " echo "kangabanga" > "${TESTDIR}/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." testfile renamed3 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/renamed3" >/dev/null || failure success echo -n "Rename a root path (abs -> rel) ... " echo "kangabanga" > "${TESTDIR}/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." /testfile renamed4 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/renamed4" >/dev/null || failure success echo -n "Rename a subdir path (abs -> abs) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." /subdir/testfile /subdir/renamed5 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/subdir/renamed5" >/dev/null || failure success echo -n "Rename a subdir path (rel -> abs) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." subdir/testfile /subdir/renamed6 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/subdir/renamed6" >/dev/null || failure success echo -n "Rename a subdir path (rel -> rel) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." subdir/testfile subdir/renamed7 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/subdir/renamed7" >/dev/null || failure success echo -n "Rename a subdir path (abs -> rel) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." /subdir/testfile subdir/renamed8 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/subdir/renamed8" >/dev/null || failure success echo -n "Rename a subdir path to a different dir (rel -> rel) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "." /subdir/testfile subdir2/renamed9 || failure success echo -n "Verify the new path ... " grep kangabanga "${TESTDIR}/subdir2/renamed9" >/dev/null || failure success echo -n "Rename from different cwd ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "subdir" ./testfile ../subdir2/renamed10 || failure success echo -n "Rename from outside share ... " ./prog_rename "${TESTURL}/?version=${VERS}" "subdir" ../../testfile ../subdir2/renamed11 2>/dev/null && failure success echo -n "Rename to outside share ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" ./prog_rename "${TESTURL}/?version=${VERS}" "subdir" ./testfile ../../subdir2/renamed12 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0252_rename_valgrind_leak_check.sh000077500000000000000000000065011343063627400247530ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_rename()." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_rename() (1) ... " echo "kangabanga" > "${TESTDIR}/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." /testfile /renamed1 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (2) ... " echo "kangabanga" > "${TESTDIR}/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." testfile /renamed2 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (3) ... " echo "kangabanga" > "${TESTDIR}/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." testfile renamed3 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (4) ... " echo "kangabanga" > "${TESTDIR}/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." /testfile renamed4 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (5) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." /subdir/testfile /subdir/renamed5 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (6) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." subdir/testfile /subdir/renamed6 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (7) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." subdir/testfile subdir/renamed7 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (8) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." /subdir/testfile subdir/renamed8 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (9) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "." /subdir/testfile subdir2/renamed9 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (10) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_rename "${TESTURL}/?version=${VERS}" "subdir" ./testfile ../subdir2/renamed10 >/dev/null 2>&1 || failure success echo -n "test nfs_rename() (11) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_rename "${TESTURL}/?version=${VERS}" "subdir" ../../testfile ../subdir2/renamed11 >/dev/null 2>&1 || expr $? != 99 >/dev/null || failure success echo -n "test nfs_rename() (12) ... " echo "kangabanga" > "${TESTDIR}/subdir/testfile" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_rename "${TESTURL}/?version=${VERS}" "subdir" ./testfile ../../subdir2/renamed12 >/dev/null 2>&1 || expr $? != 99 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0260_symlink_paths.sh000077500000000000000000000042711343063627400223530ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic symlink test." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "Create a symlink in root (abs) (1) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "." kangabanga /symlink1 || failure success echo -n "Verify the link ... " ls -l "${TESTDIR}/symlink1" | egrep "\-> kangabanga$" >/dev/null || failure success echo -n "Create a symlink in root (rel) (2) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "." kangabanga symlink2 || failure success echo -n "Verify the link ... " ls -l "${TESTDIR}/symlink2" | egrep "\-> kangabanga$" >/dev/null || failure success echo -n "Create a symlink from a subdir (abs) (3) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "." kangabanga /subdir/symlink3 || failure success echo -n "Verify the link ... " ls -l "${TESTDIR}/subdir/symlink3" | egrep "\-> kangabanga$" >/dev/null || failure success echo -n "Create a symlink from a subdir (rel) (4) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "." kangabanga subdir/symlink4 || failure success echo -n "Verify the link ... " ls -l "${TESTDIR}/subdir/symlink4" | egrep "\-> kangabanga$" >/dev/null || failure success echo -n "Create a symlink from a subdir (rel) (5) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "/subdir" kangabanga symlink5 || failure success echo -n "Verify the link ... " ls -l "${TESTDIR}/subdir/symlink5" | egrep "\-> kangabanga$" >/dev/null || failure success echo -n "Create a symlink in a parent directory (rel) (6) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "/subdir" kangabanga ../symlink6 || failure success echo -n "Verify the link ... " ls -l "${TESTDIR}/symlink6" | egrep "\-> kangabanga$" >/dev/null || failure success echo -n "Create a symlink from different cwd (rel) (7) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "/subdir" kangabanga ../subdir2/symlink7 || failure success echo -n "Verify the link ... " ls -l "${TESTDIR}/subdir2/symlink7" | egrep "\-> kangabanga$" >/dev/null || failure success echo -n "Create a symlink outside the share (rel) (8) ... " ./prog_symlink "${TESTURL}/?version=${VERS}" "/subdir" kangabanga ../../symlink8 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0270_unlink.sh000077500000000000000000000023751343063627400207720ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_unlink() test." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "Unlink a file from the root (abs) (1)... " touch "${TESTDIR}/unlink" ./prog_unlink "${TESTURL}/?version=${VERS}" "." /unlink || failure success echo -n "Verify the file is gone ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." unlink 2>/dev/null && failure success echo -n "Unlink a file from the root (rel) (2)... " touch "${TESTDIR}/unlink" ./prog_unlink "${TESTURL}/?version=${VERS}" "." unlink || failure success echo -n "Unlink a file from a subdir (abs) (3)... " touch "${TESTDIR}/subdir/unlink" ./prog_unlink "${TESTURL}/?version=${VERS}" "." /subdir/unlink || failure success echo -n "Unlink a file from a subdir (rel) (4)... " touch "${TESTDIR}/subdir/unlink" ./prog_unlink "${TESTURL}/?version=${VERS}" "." subdir/unlink || failure success echo -n "Unlink a file from a different dir (rel) (5)... " touch "${TESTDIR}/subdir2/unlink" ./prog_unlink "${TESTURL}/?version=${VERS}" "subdir" ../subdir2/unlink || failure success echo -n "Unlink a file from outside the share (rel) (6)... " ./prog_unlink "${TESTURL}/?version=${VERS}" "subdir" ../../subdir2/unlink 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0272_unlink_valgrind_leak_check.sh000077500000000000000000000030561343063627400250100ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_unlink()." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_unlink() (1) ... " touch "${TESTDIR}/unlink" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_unlink "${TESTURL}/?version=${VERS}" "." /unlink 2>/dev/null || failure success echo -n "test nfs_unlink() (2) ... " touch "${TESTDIR}/unlink" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_unlink "${TESTURL}/?version=${VERS}" "." unlink 2>/dev/null || failure success echo -n "test nfs_unlink() (3) ... " touch "${TESTDIR}/subdir/unlink" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_unlink "${TESTURL}/?version=${VERS}" "." /subdir/unlink 2>/dev/null || failure success echo -n "test nfs_unlink() (4) ... " touch "${TESTDIR}/subdir/unlink" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_unlink "${TESTURL}/?version=${VERS}" "." subdir/unlink 2>/dev/null || failure success echo -n "test nfs_unlink() (5) ... " touch "${TESTDIR}/subdir2/unlink" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_unlink "${TESTURL}/?version=${VERS}" "subdir" ../subdir2/unlink 2>/dev/null || failure success echo -n "test nfs_unlink() (6) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_unlink "${TESTURL}/?version=${VERS}" "subdir" ../../subdir2/unlink 2>/dev/null || expr $? != 99 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0280_mkdir_rmdir.sh000077500000000000000000000050451343063627400217730ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic mkdir/rmdir tests." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_mkdir2() for a root directory (abs) (1) ... " ./prog_mkdir "${TESTURL}/?version=${VERS}" "." /testdir || failure success echo -n "Stat the new directory ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testdir > "${TESTDIR}/output" || failure success echo -n "Verifying it is a directory ... " grep "nfs_mode:40" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_rmdir() for a root directory (abs) (2) ... " ./prog_rmdir "${TESTURL}/?version=${VERS}" "." /testdir || failure success echo -n "test nfs_mkdir2() for a root directory (rel) (3) ... " ./prog_mkdir "${TESTURL}/?version=${VERS}" "." testdir 2>/dev/null || failure success echo -n "test nfs_rmdir() for a root directory (rel) (4) ... " ./prog_rmdir "${TESTURL}/?version=${VERS}" "." testdir 2>/dev/null || failure success echo -n "test nfs_mkdir2() in a subdirectory (abs) (5) ... " ./prog_mkdir "${TESTURL}/?version=${VERS}" "." /subdir/testdir 2>/dev/null || failure success echo -n "test nfs_rmdir() for a subdirectory (abs) (6) ... " ./prog_rmdir "${TESTURL}/?version=${VERS}" "." /subdir/testdir 2>/dev/null || failure success echo -n "test nfs_mkdir2() in a subdirectory (rel) (7) ... " ./prog_mkdir "${TESTURL}/?version=${VERS}" "." subdir/testdir 2>/dev/null || failure success echo -n "test nfs_rmdir() for a subdirectory (rel) (8) ... " ./prog_rmdir "${TESTURL}/?version=${VERS}" "." subdir/testdir 2>/dev/null || failure success echo -n "test nfs_mkdir2() from a different cwd (rel) (9) ... " ./prog_mkdir "${TESTURL}/?version=${VERS}" "subdir" ../subdir2/testdir 2>/dev/null || failure success echo -n "test nfs_rmdir() for a subdirectory (rel) (10) ... " ./prog_rmdir "${TESTURL}/?version=${VERS}" "." subdir2/testdir 2>/dev/null || failure success echo -n "test nfs_mkdir2() outside of the share (rel) (11) ... " ./prog_mkdir "${TESTURL}/?version=${VERS}" "subdir" ../subdir2/../../testdir 2>/dev/null && failure success echo -n "test nfs_rmdir() outside of the share (rel) (12) ... " ./prog_rmdir "${TESTURL}/?version=${VERS}" "subdir" ../subdir2/../../testdir 2>/dev/null && failure success echo -n "test nfs_mkdir2() on an existing dir (rel) (13) ... " ./prog_mkdir "${TESTURL}/?version=${VERS}" "subdir" 2>/dev/null ../subdir2 && failure success echo -n "test nfs_rmdir() that does not exist (rel) (14) ... " ./prog_rmdir "${TESTURL}/?version=${VERS}" "subdir" ../subdir3 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0282_mkdir_rmdir_valgrind_leak_check.sh000077500000000000000000000051411343063627400260110ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_mkdir()/nfs_rmdir()." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_mkdir() (1) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_mkdir "${TESTURL}/?version=${VERS}" "." /mkdir1 2>/dev/null || failure success echo -n "test nfs_rmdir() (2) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_rmdir "${TESTURL}/?version=${VERS}" "." /mkdir1 2>/dev/null || failure success echo -n "test nfs_mkdir() (3) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_mkdir "${TESTURL}/?version=${VERS}" "." mkdir3 2>/dev/null || failure success echo -n "test nfs_rmdir() (4) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_rmdir "${TESTURL}/?version=${VERS}" "." mkdir3 2>/dev/null || failure success echo -n "test nfs_mkdir() (5) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_mkdir "${TESTURL}/?version=${VERS}" "." /subdir/mkdir5 2>/dev/null || failure success echo -n "test nfs_rmdir() (6) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_rmdir "${TESTURL}/?version=${VERS}" "." /subdir/mkdir5 2>/dev/null || failure success echo -n "test nfs_mkdir() (7) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_mkdir "${TESTURL}/?version=${VERS}" "." subdir/mkdir7 2>/dev/null || failure success echo -n "test nfs_rmdir() (8) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_rmdir "${TESTURL}/?version=${VERS}" "." subdir/mkdir7 2>/dev/null || failure success echo -n "test nfs_mkdir() (9) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_mkdir "${TESTURL}/?version=${VERS}" "subdir" ../subdir2/mkdir9 2>/dev/null || failure success echo -n "test nfs_rmdir() (10) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_rmdir "${TESTURL}/?version=${VERS}" "subdir" ../subdir2/mkdir9 2>/dev/null || failure success echo -n "test nfs_mkdir() (11) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_mkdir "${TESTURL}/?version=${VERS}" "subdir" ../../subdir2/mkdir9 2>/dev/null || expr $? != 99 >/dev/null || failure success echo -n "test nfs_rmdir() (12) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_rmdir "${TESTURL}/?version=${VERS}" "subdir" ../../subdir2/mkdir12 2>/dev/null || expr $? != 99 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0290_read.sh000077500000000000000000000010331343063627400203750ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "basic read test" start_share echo -n "Create a 10M file ... " dd if=/dev/urandom of="${TESTDIR}/orig" bs=1M count=10 2>/dev/null || failure success echo -n "Copy file from the NFS server ... " ../utils/nfs-cp "${TESTURL}/orig" "${TESTDIR}/copy" >/dev/null || failure success echo -n "Verify the files are identical ... " ORIGSUM=`md5sum "${TESTDIR}/orig" | cut -d " " -f 1` COPYSUM=`md5sum "${TESTDIR}/copy" | cut -d " " -f 1` [ "${ORIGSUM}" != "${COPYSUM}" ] && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0300_write.sh000077500000000000000000000006631343063627400206140ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_write() test." start_share echo -n "test writing to a file (1) ... " touch "${TESTDIR}/open1" ./prog_open_write "${TESTURL}/?version=${VERS}" "." /open1 O_WRONLY "kangabanga" >/dev/null || failure success echo -n "verify the data is correct ... " echo -n "kangabanga" > "${TESTDIR}/verify1" diff "${TESTDIR}/verify1" "${TESTDIR}/open1" || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0310_mknod.sh000077500000000000000000000035651343063627400205770ustar00rootroot00000000000000#!/bin/sh # # NFS servers generally want us to be root in order to create device nodes. # We can lie and impersonate root by setting uid=0 in the URL. . ./functions.sh echo "NFSv${VERS} Basic mknod test." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "Create a chrdev in the root (abs) (1)... " ./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "." /mknod1 020755 0x1234 || failure success echo -n "Stat the node ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." mknod1 > "${TESTDIR}/output" || failure success echo -n "Testing nfs_mode and verify it is a CHRDEV ... " grep "nfs_mode:20755" "${TESTDIR}/output" >/dev/null || failure success echo -n "Create a chrdev in the root (rel) (2)... " ./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "." mknod2 020775 0x1234 || failure success echo -n "Create a chrdev in a subdirectory (abs) (3)... " ./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "." /subdir/mknod3 020775 0x1234 || failure success echo -n "Create a chrdev in a subdirectory (abs) (4)... " ./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "." subdir/mknod4 020775 0x1234 || failure success echo -n "Create a chrdev from a different cwd (abs) (5)... " ./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "subdir" ../subdir2/mknod5 020775 0x1234 || failure success echo -n "Create a chrdev outside the share (abs) (6)... " ./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "." ../subdir2/mknod6 020775 0x1234 2>/dev/null && failure success echo -n "Create a blkdev in the root (abs) (7)... " ./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "." /mknod7 060755 0x1234 || failure success echo -n "Stat the node ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." mknod7 > "${TESTDIR}/output" || failure success echo -n "Testing nfs_mode and verify it is a BLKDEV ... " grep "nfs_mode:60755" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0320_lstat.sh000077500000000000000000000026501343063627400206110ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic lstat test." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null chmod 644 "${TESTDIR}/testfile" ln -s testfile "${TESTDIR}/lstat1" echo -n "test nfs_lstat64() ... " ./prog_lstat "${TESTURL}/?version=${VERS}" "." /lstat1 > "${TESTDIR}/output" || failure success echo -n "test nfs_ino ... " INO=`stat --printf="%i" testdata/lstat1` grep "nfs_ino:$INO" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mode ... " grep "nfs_mode:120777" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_nlink ... " grep "nfs_nlink:1" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_uid ... " grep "nfs_uid:$UID" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_gid ... " grep "nfs_gid:$GID" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_size ... " grep "nfs_size:8" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_atime ... " ATIME=`stat --printf="%X" testdata/lstat1` grep "nfs_atime:$ATIME" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mtime ... " MTIME=`stat --printf="%Y" testdata/lstat1` grep "nfs_mtime:$MTIME" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_ctime ... " CTIME=`stat --printf="%Z" testdata/lstat1` grep "nfs_ctime:$CTIME" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0321_lstat_paths.sh000077500000000000000000000027351343063627400220150ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} nfs_lstat64() path tests." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_lstat64() for a root file (abs) (1)... " ln -s foo "${TESTDIR}/stat1" ./prog_lstat "${TESTURL}/?version=${VERS}" "." /stat1 >/dev/null || failure success echo -n "test nfs_lstat64() for a root file (rel) (2)... " ./prog_lstat "${TESTURL}/?version=${VERS}" "." stat1 >/dev/null || failure success echo -n "test nfs_lstat64() for a subdir file (abs) (3)... " ln -s foo "${TESTDIR}/subdir/stat3" ./prog_lstat "${TESTURL}/?version=${VERS}" "." /subdir/stat3 >/dev/null || failure success echo -n "test nfs_lstat64() for a subdir file (rel) (4)... " ./prog_lstat "${TESTURL}/?version=${VERS}" "." subdir/stat3 >/dev/null || failure success echo -n "test nfs_lstat64() from a different cwd (rel) (5)... " ./prog_lstat "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/stat3 >/dev/null || failure success echo -n "test nfs_lstat64() outside the share (rel) (6)... " ./prog_lstat "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/stat3 >/dev/null 2>&1 && failure success echo -n "test nfs_lstat64() when target is a symlink (7)... " touch "${TESTDIR}/stat7" ln -s stat7 "${TESTDIR}/symlink7" ./prog_lstat "${TESTURL}/?version=${VERS}" "." symlink7 >"${TESTDIR}/output" || failure success echo -n "test nfs_lstat64() report it is a symlink ... " grep "nfs_mode:120777" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0322_lstat_valgrind_leak_check.sh000077500000000000000000000027401343063627400246320ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_lstat64()." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_lstat64() (1) ... " ln -s foo "${TESTDIR}/stat1" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_lstat "${TESTURL}/?version=${VERS}" "." /stat1 >/dev/null 2>&1 || failure success echo -n "test nfs_lstat64() (2) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_lstat "${TESTURL}/?version=${VERS}" "." stat1 >/dev/null 2>&1 || failure success echo -n "test nfs_lstat64() (3) ... " ln -s foo "${TESTDIR}/subdir/stat3" libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_lstat "${TESTURL}/?version=${VERS}" "." /subdir/stat3 >/dev/null 2>&1 || failure success echo -n "test nfs_lstat64() (4) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_lstat "${TESTURL}/?version=${VERS}" "." subdir/stat3 >/dev/null 2>&1 || failure success echo -n "test nfs_lstat64() (5) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_lstat "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/stat3 >/dev/null 2>&1 || failure success echo -n "test nfs_lstat64() (6) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_lstat "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/stat3 2>/dev/null || expr $? != 99 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0330_ftruncate.sh000077500000000000000000000010261343063627400214520ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_ftruncate() test." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test nfs_ftruncate() ... " ./prog_ftruncate "${TESTURL}/?version=${VERS}" "." testfile 12377 || failure success echo -n "test nfs_fstat64() ... " ./prog_fstat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "verify nfs_size ... " grep "nfs_size:12377" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0332_ftruncate_valgrind_leak_check.sh000077500000000000000000000006271343063627400255010ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check for nfs_ftruncate()." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test nfs_ftruncate() (1) ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=99 ./prog_ftruncate "${TESTURL}/?version=${VERS}" "." testfile 12377 >/dev/null 2>&1 || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0340_truncate.sh000077500000000000000000000010211343063627400213000ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_truncate() tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test nfs_truncate() ... " ./prog_truncate "${TESTURL}/?version=${VERS}" "." /testfile 1998 || failure success echo -n "test nfs_fstat64() ... " ./prog_fstat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "test nfs_size ... " grep "nfs_size:1998" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0341_truncate_paths.sh000077500000000000000000000026061343063627400225120ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} nfs_truncate() path tests." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "test nfs_truncate() for a root file (abs) (1)... " touch "${TESTDIR}/trunc1" ./prog_truncate "${TESTURL}/?version=${VERS}" "." /trunc1 2027 >/dev/null || failure success echo -n "test nfs_truncate() for a root file (rel) (2)... " ./prog_truncate "${TESTURL}/?version=${VERS}" "." trunc1 2028 >/dev/null || failure success echo -n "test nfs_truncate() for a subdir file (abs) (3)... " touch "${TESTDIR}/subdir/trunc3" ./prog_truncate "${TESTURL}/?version=${VERS}" "." /subdir/trunc3 2029 >/dev/null || failure success echo -n "test nfs_truncate() for a subdir file (rel) (4)... " ./prog_truncate "${TESTURL}/?version=${VERS}" "." subdir/trunc3 2030 >/dev/null || failure success echo -n "test nfs_truncate() from a different cwd (rel) (5)... " ./prog_truncate "${TESTURL}/?version=${VERS}" "subdir2" ../subdir/trunc3 2031 >/dev/null || failure success echo -n "test nfs_truncate() outside the share (rel) (6)... " ./prog_truncate "${TESTURL}/?version=${VERS}" "subdir2" ../../subdir/trunc3 2032 >/dev/null 2>&1 && failure success echo -n "test nfs_truncate() when target is a symlink (7)... " touch "${TESTDIR}/trunc7" ln -s trunc7 "${TESTDIR}/symlink7" ./prog_truncate "${TESTURL}/?version=${VERS}" "." symlink7 2033 || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0350_lseek.sh000077500000000000000000000004071343063627400205660ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic lseek test." start_share truncate -s 1024 "${TESTDIR}/testfile" echo -n "test nfs_lseek() ... " ./prog_lseek "${TESTURL}/?version=${VERS}" "." /testfile > /dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0360_statvfs.sh000077500000000000000000000007741343063627400211650ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_statvfs() tests." start_share # check how big the local filesystem is and convert to 4kb blocks BLOCKS=`df -k . | tail -1 | cut -d ' ' -f 2` BLOCKS=`expr "$BLOCKS" "/" "4"` echo -n "test nfs_statvfs() ... " ./prog_statvfs "${TESTURL}/?version=${VERS}" "." / > "${TESTDIR}/output" || failure success echo -n "verify total number of blobs is correct ... " grep "blocks:$BLOCKS" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0370_chmod.sh000077500000000000000000000015601343063627400205600ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic chmod tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test chmod(0600) ... " ./prog_chmod "${TESTURL}/?version=${VERS}" "." /testfile 0600 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the mode is 0600 ... " grep "nfs_mode:100600" "${TESTDIR}/output" >/dev/null || failure success echo -n "test chmod(0755) ... " ./prog_chmod "${TESTURL}/?version=${VERS}" "." /testfile 0755 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the mode is 0755 ... " grep "nfs_mode:100755" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0380_lchmod.sh000077500000000000000000000015651343063627400207420ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic lchmod tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test lchmod(0600) ... " ./prog_lchmod "${TESTURL}/?version=${VERS}" "." /testfile 0600 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the mode is 0600 ... " grep "nfs_mode:100600" "${TESTDIR}/output" >/dev/null || failure success echo -n "test lchmod(0755) ... " ./prog_lchmod "${TESTURL}/?version=${VERS}" "." /testfile 0755 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the mode is 0755 ... " grep "nfs_mode:100755" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0390_fchmod.sh000077500000000000000000000015651343063627400207350ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic fchmod tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test fchmod(0600) ... " ./prog_fchmod "${TESTURL}/?version=${VERS}" "." /testfile 0600 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the mode is 0600 ... " grep "nfs_mode:100600" "${TESTDIR}/output" >/dev/null || failure success echo -n "test fchmod(0755) ... " ./prog_fchmod "${TESTURL}/?version=${VERS}" "." /testfile 0755 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the mode is 0755 ... " grep "nfs_mode:100755" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0400_chown.sh000077500000000000000000000021521343063627400205740ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic chown tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test chown(1000, 2000) ... " ./prog_chown "${TESTURL}/?uid=0&version=${VERS}" "." /testfile 1000 2000 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the uid is 1000 ... " grep "nfs_uid:1000" "${TESTDIR}/output" >/dev/null || failure success echo -n "Verifying the gid is 2000 ... " grep "nfs_gid:2000" "${TESTDIR}/output" >/dev/null || failure success echo -n "test chown(2000, 3000) ... " ./prog_chown "${TESTURL}/?uid=0&version=${VERS}" "." /testfile 2000 3000 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the uid is 2000 ... " grep "nfs_uid:2000" "${TESTDIR}/output" >/dev/null || failure success echo -n "Verifying the gid is 3000 ... " grep "nfs_gid:3000" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0410_lchown.sh000077500000000000000000000021571343063627400207560ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic lchown tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test lchown(1000, 2000) ... " ./prog_lchown "${TESTURL}/?uid=0&version=${VERS}" "." /testfile 1000 2000 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the uid is 1000 ... " grep "nfs_uid:1000" "${TESTDIR}/output" >/dev/null || failure success echo -n "Verifying the gid is 2000 ... " grep "nfs_gid:2000" "${TESTDIR}/output" >/dev/null || failure success echo -n "test lchown(2000, 3000) ... " ./prog_lchown "${TESTURL}/?uid=0&version=${VERS}" "." /testfile 2000 3000 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the uid is 2000 ... " grep "nfs_uid:2000" "${TESTDIR}/output" >/dev/null || failure success echo -n "Verifying the gid is 3000 ... " grep "nfs_gid:3000" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0420_fchown.sh000077500000000000000000000021571343063627400207510ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic fchown tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test fchown(1000, 2000) ... " ./prog_fchown "${TESTURL}/?uid=0&version=${VERS}" "." /testfile 1000 2000 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the uid is 1000 ... " grep "nfs_uid:1000" "${TESTDIR}/output" >/dev/null || failure success echo -n "Verifying the gid is 2000 ... " grep "nfs_gid:2000" "${TESTDIR}/output" >/dev/null || failure success echo -n "test fchown(2000, 3000) ... " ./prog_fchown "${TESTURL}/?uid=0&version=${VERS}" "." /testfile 2000 3000 || failure success echo -n "Stat the file ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile > "${TESTDIR}/output" || failure success echo -n "Verifying the uid is 2000 ... " grep "nfs_uid:2000" "${TESTDIR}/output" >/dev/null || failure success echo -n "Verifying the gid is 3000 ... " grep "nfs_gid:3000" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0430_access.sh000077500000000000000000000023121343063627400207200ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic access tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test access(R_OK) on a readable file ... " chmod 400 "${TESTDIR}/testfile" ./prog_access "${TESTURL}/?version=${VERS}" "." /testfile R_OK || failure success echo -n "test access(W_OK) on a writeable file ... " chmod 200 "${TESTDIR}/testfile" ./prog_access "${TESTURL}/?version=${VERS}" "." /testfile W_OK || failure success echo -n "test access(X_OK) on an executable file ... " chmod 100 "${TESTDIR}/testfile" ./prog_access "${TESTURL}/?version=${VERS}" "." /testfile X_OK || failure success echo -n "test access(R_OK) on a non-readable file ... " chmod 300 "${TESTDIR}/testfile" ./prog_access "${TESTURL}/?version=${VERS}" "." /testfile R_OK 2>/dev/null && failure success echo -n "test access(W_OK) on a non-writeable file ... " chmod 500 "${TESTDIR}/testfile" ./prog_access "${TESTURL}/?version=${VERS}" "." /testfile W_OK 2>/dev/null && failure success echo -n "test access(X_OK) on a non-executable file ... " chmod 600 "${TESTDIR}/testfile" ./prog_access "${TESTURL}/?version=${VERS}" "." /testfile X_OK 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0440_access2.sh000077500000000000000000000023271343063627400210110ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic access2 tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null echo -n "test access2(R_OK) on a readable file ... " chmod 400 "${TESTDIR}/testfile" ./prog_access2 "${TESTURL}/?version=${VERS}" "." /testfile R_OK || failure success echo -n "test access2(W_OK) on a writeable file ... " chmod 200 "${TESTDIR}/testfile" ./prog_access2 "${TESTURL}/?version=${VERS}" "." /testfile W_OK || failure success echo -n "test access2(X_OK) on an executable file ... " chmod 100 "${TESTDIR}/testfile" ./prog_access2 "${TESTURL}/?version=${VERS}" "." /testfile X_OK || failure success echo -n "test access2(R_OK) on a non-readable file ... " chmod 300 "${TESTDIR}/testfile" ./prog_access2 "${TESTURL}/?version=${VERS}" "." /testfile R_OK 2>/dev/null && failure success echo -n "test access2(W_OK) on a non-writeable file ... " chmod 500 "${TESTDIR}/testfile" ./prog_access2 "${TESTURL}/?version=${VERS}" "." /testfile W_OK 2>/dev/null && failure success echo -n "test access2(X_OK) on a non-executable file ... " chmod 600 "${TESTDIR}/testfile" ./prog_access2 "${TESTURL}/?version=${VERS}" "." /testfile X_OK 2>/dev/null && failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0450_utimes.sh000077500000000000000000000012351343063627400207720ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic nfs_utimes() tests." start_share dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null chmod 644 "${TESTDIR}/testfile" echo -n "test nfs_utimes() ... " ./prog_utimes "${TESTURL}/?version=${VERS}" "." /testfile 12345 23456 || failure success echo -n "test nfs_stat64() ... " ./prog_stat "${TESTURL}/?version=${VERS}" "." /testfile > "${TESTDIR}/output" || failure success echo -n "test nfs_atime ... " grep "nfs_atime:12345" "${TESTDIR}/output" >/dev/null || failure success echo -n "test nfs_mtime ... " grep "nfs_mtime:23456" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_0460_opendir.sh000077500000000000000000000031741343063627400211310ustar00rootroot00000000000000#!/bin/sh # # NFS servers generally want us to be root in order to create device nodes. # We can lie and impersonate root by setting uid=0 in the URL. . ./functions.sh echo "NFSv${VERS} Basic opendir test." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir/subdir2" touch "${TESTDIR}/subdir/subdir2/file" echo -n "Open '.' in the root directory (1)... " ./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "." "." > "${TESTDIR}/output" || failure success echo -n "Check the directory listing ... " grep "^subdir$" "${TESTDIR}/output" >/dev/null || failure success echo -n "Open a subdir in the root directory (2)... " ./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "." "subdir" > "${TESTDIR}/output" || failure success echo -n "Check the directory listing ... " grep "^subdir2$" "${TESTDIR}/output" >/dev/null || failure success echo -n "Open '.' in a subdir (3)... " ./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "subdir" "." > "${TESTDIR}/output" || failure success echo -n "Check the directory listing ... " grep "^subdir2$" "${TESTDIR}/output" >/dev/null || failure success echo -n "Open 'subdir2' in a subdir (4)... " ./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "subdir" "subdir2" > "${TESTDIR}/output" || failure success echo -n "Check the directory listing ... " grep "^file$" "${TESTDIR}/output" >/dev/null || failure success echo -n "Open '..' in a subdir (5)... " ./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "subdir/subdir2" ".." > "${TESTDIR}/output" || failure success echo -n "Check the directory listing ... " grep "^subdir2$" "${TESTDIR}/output" >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_1000_mount_paths.sh000077500000000000000000000006651343063627400220230ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic mount path test." start_share echo -n "test nfs_mount() normal share ... " ./prog_mount "${TESTURL}/?version=${VERS}" || failure success mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir/subdir2" ln -s subdir "${TESTDIR}/symlink1" echo -n "test nfs_mount() following a link ... " ./prog_mount "${TESTURL}/symlink1/subdir2/?version=${VERS}" || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_1010_chdir_paths.sh000077500000000000000000000006011343063627400217410ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic chdir path test." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir/subdir2" touch "${TESTDIR}/subdir/stat1" ln -s subdir "${TESTDIR}/symlink1" echo -n "Test nfs_stat64() from a different cwd (rel) (1)... " ./prog_stat "${TESTURL}/?version=${VERS}" "symlink1" stat1 >/dev/null || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_8000_timeout.sh000077500000000000000000000006521343063627400211530ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic timeout test." if [ $VERS -eq 3 ]; then COUNT=28 else COUNT=13 fi start_share touch "${TESTDIR}/testfile" for IDX in `seq 1 $COUNT`; do echo -n "Test timeout at socket event ${IDX} ... " TIMEOUT_START=${IDX} LD_PRELOAD=./ld_timeout.so ./prog_stat "${TESTURL}/?version=${VERS}" "." testfile >/dev/null 2>&1 && failure success done stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_9900_valgrind_leak_check_full.sh000077500000000000000000000047141343063627400244630ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind leak check." start_share mkdir "${TESTDIR}/subdir" mkdir "${TESTDIR}/subdir2" echo -n "Create 100 1M files ... " for IDX in `seq 1 100`; do dd if=/dev/zero of="${TESTDIR}/file.$IDX" bs=1M count=10 2>/dev/null || failure done success echo -n "Testing server discovery for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ../utils/nfs-ls -D nfs:// > "${TESTDIR}/output?version=${VERS}" 2>/dev/null || failure success echo -n "Testing share enumeration for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ../utils/nfs-ls -D nfs://127.0.0.1 > "${TESTDIR}/output?version=${VERS}" 2>/dev/null || failure success echo -n "test nfs-ls for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ../utils/nfs-ls "${TESTURL}?version=${VERS}" >/dev/null 2>&1 || failure success echo -n "test nfs-cp for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ../utils/nfs-cp "${TESTURL}/file.99?version=${VERS}" "${TESTURL}/copy-of-file.99" >/dev/null 2>&1 || failure success echo -n "test nfs_truncate() for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ../examples/nfs-io trunc "${TESTURL}/copy-of-file.99?version=${VERS}" >/dev/null 2>&1 || failure success echo -n "test nfs_unlink() for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ../examples/nfs-io unlink "${TESTURL}/copy-of-file.99?version=${VERS}" >/dev/null 2>&1 || failure success echo -n "test nfs_mkdir() for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ../examples/nfs-io mkdir "${TESTURL}/testdir?version=${VERS}" >/dev/null 2>&1 || failure success echo -n "test nfs_rmdir() for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ../examples/nfs-io rmdir "${TESTURL}/testdir?version=${VERS}" >/dev/null 2>&1 || failure success echo -n "test nfs_stat64() for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_stat "${TESTURL}/?version=${VERS}" "." file.99 >/dev/null 2>&1 || failure success echo -n "test nfs_fstat64() for memory leaks ... " libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_fstat "${TESTURL}/?version=${VERS}" "." file.99 >/dev/null 2>&1 || failure success stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_9910_valgrind_timeout.sh000077500000000000000000000007101343063627400230470ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "NFSv${VERS} Basic valgrind check of timeout handling." start_share touch "${TESTDIR}/testfile" for IDX in `seq 1 28`; do echo -n "Test memory leaks at socket event ${IDX} ... " TIMEOUT_START=${IDX} LD_PRELOAD=./ld_timeout.so libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_timeout "${TESTURL}/testfile?version=${VERS}" >/dev/null 2>&1 || failure success done stop_share exit 0 libnfs-libnfs-4.0.0/tests/test_9990_build_rpm.sh000077500000000000000000000004261343063627400214640ustar00rootroot00000000000000#!/bin/sh . ./functions.sh echo "test we can build libnfs as an rpm" [ -f "/etc/redhat-release" ] || { echo "SKIPPED. This is not a red-hat based system" } echo -n "try building rpm packages ... " ../packaging/RPM/makerpms.sh >/dev/null 2>&1 || failure success exit 0 libnfs-libnfs-4.0.0/utils/000077500000000000000000000000001343063627400154135ustar00rootroot00000000000000libnfs-libnfs-4.0.0/utils/CMakeLists.txt000066400000000000000000000006031343063627400201520ustar00rootroot00000000000000list(APPEND CORE_LIBRARIES ${SOCKET_LIBRARY}) set(SOURCES nfs-cat nfs-ls) if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows) list(APPEND SOURCES nfs-cp) endif() foreach(TARGET ${SOURCES}) add_executable(${TARGET} ${TARGET}.c) target_link_libraries(${TARGET} ${CORE_LIBRARIES}) add_dependencies(${TARGET} nfs) endforeach() add_definitions("-D_U_=__attribute__((unused))") libnfs-libnfs-4.0.0/utils/Makefile.am000066400000000000000000000006031343063627400174460ustar00rootroot00000000000000bin_PROGRAMS = nfs-cat nfs-ls if !HAVE_WIN32 bin_PROGRAMS += nfs-cp endif AM_CPPFLAGS = \ -I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/mount \ -I$(abs_top_srcdir)/win32 \ "-D_U_=__attribute__((unused))" COMMON_LIBS = ../lib/libnfs.la $(LIBSOCKET) nfs_cat_LDADD = $(COMMON_LIBS) nfs_ls_LDADD = $(COMMON_LIBS) nfs_cp_LDADD = $(COMMON_LIBS) libnfs-libnfs-4.0.0/utils/nfs-cat.c000066400000000000000000000107031343063627400171130ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2015 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #else #include #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" struct file_context { int fd; struct nfs_context *nfs; struct nfsfh *nfsfh; struct nfs_url *url; }; void usage(void) { fprintf(stderr, "Usage: nfs-cat \n"); fprintf(stderr, " cat an nfs file.\n"); exit(0); } static void free_file_context(struct file_context *file_context) { if (file_context->fd != -1) { close(file_context->fd); } if (file_context->nfsfh != NULL) { nfs_close(file_context->nfs, file_context->nfsfh); } if (file_context->nfs != NULL) { nfs_destroy_context(file_context->nfs); } nfs_destroy_url(file_context->url); free(file_context); } static struct file_context * open_file(const char *url, int flags) { struct file_context *file_context; file_context = malloc(sizeof(struct file_context)); if (file_context == NULL) { fprintf(stderr, "Failed to malloc file_context\n"); return NULL; } file_context->fd = -1; file_context->nfs = NULL; file_context->nfsfh = NULL; file_context->url = NULL; file_context->nfs = nfs_init_context(); if (file_context->nfs == NULL) { fprintf(stderr, "failed to init context\n"); free_file_context(file_context); return NULL; } file_context->url = nfs_parse_url_full(file_context->nfs, url); if (file_context->url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(file_context->nfs)); free_file_context(file_context); return NULL; } if (nfs_mount(file_context->nfs, file_context->url->server, file_context->url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(file_context->nfs)); free_file_context(file_context); return NULL; } if (flags == O_RDONLY) { if (nfs_open(file_context->nfs, file_context->url->file, flags, &file_context->nfsfh) != 0) { fprintf(stderr, "Failed to open file %s: %s\n", file_context->url->file, nfs_get_error(file_context->nfs)); free_file_context(file_context); return NULL; } } else { if (nfs_creat(file_context->nfs, file_context->url->file, 0660, &file_context->nfsfh) != 0) { fprintf(stderr, "Failed to creat file %s: %s\n", file_context->url->file, nfs_get_error(file_context->nfs)); free_file_context(file_context); return NULL; } } return file_context; } #define BUFSIZE 1024*1024 static char buf[BUFSIZE]; int main(int argc, char *argv[]) { int ret; struct file_context *nf; struct nfs_stat_64 st; uint64_t off; int64_t count; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); return 10; } #endif #ifdef AROS aros_init_socket(); #endif if (argc < 2) { usage(); } nf = open_file(argv[1], O_RDONLY); if (nf == NULL) { fprintf(stderr, "Failed to open %s\n", argv[1]); exit(10); } if (nfs_fstat64(nf->nfs, nf->nfsfh, &st) < 0) { fprintf(stderr, "Failed to stat %s\n", argv[1]); exit(10); } off = 0; while (off < st.nfs_size) { count = st.nfs_size - off; if (count > BUFSIZE) { count = BUFSIZE; } count = nfs_pread(nf->nfs, nf->nfsfh, off, count, buf); if (count < 0) { fprintf(stderr, "Failed to read from file\n"); free_file_context(nf); return 10; } fwrite(buf, count, 1, stdout); off += count; } free_file_context(nf); return 0; } libnfs-libnfs-4.0.0/utils/nfs-cp.c000066400000000000000000000152141343063627400167500ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2013 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #else #include #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" struct file_context { int is_nfs; int fd; struct nfs_context *nfs; struct nfsfh *nfsfh; struct nfs_url *url; }; void usage(void) { fprintf(stderr, "Usage: nfs-cp \n"); fprintf(stderr, ", can either be a local file or " "an nfs URL.\n"); exit(0); } static void free_file_context(struct file_context *file_context) { if (file_context->fd != -1) { close(file_context->fd); } if (file_context->nfsfh != NULL) { nfs_close(file_context->nfs, file_context->nfsfh); } if (file_context->nfs != NULL) { nfs_destroy_context(file_context->nfs); } nfs_destroy_url(file_context->url); free(file_context); } static int fstat_file(struct file_context *fc, struct stat *st) { if (fc->is_nfs == 0) { return fstat(fc->fd, st); } else { int res; struct nfs_stat_64 nfs_st; res = nfs_fstat64(fc->nfs, fc->nfsfh, &nfs_st); st->st_dev = (dev_t)nfs_st.nfs_dev; st->st_ino = (ino_t)nfs_st.nfs_ino; #ifndef WIN32 st->st_mode = (mode_t)nfs_st.nfs_mode; st->st_nlink = (nlink_t)nfs_st.nfs_nlink; st->st_blksize = nfs_st.nfs_blksize; st->st_blocks = nfs_st.nfs_blocks; #endif st->st_uid = (uid_t)nfs_st.nfs_uid; st->st_gid = (gid_t)nfs_st.nfs_gid; st->st_rdev = (dev_t)nfs_st.nfs_rdev; st->st_size = (off_t)nfs_st.nfs_size; st->st_atime = nfs_st.nfs_atime; st->st_mtime = nfs_st.nfs_mtime; st->st_ctime = nfs_st.nfs_ctime; return res; } } static ssize_t file_pread(struct file_context *fc, char *buf, size_t count, off_t off) { if (fc->is_nfs == 0) { lseek(fc->fd, off, SEEK_SET); return read(fc->fd, buf, count); } else { return nfs_pread(fc->nfs, fc->nfsfh, off, count, buf); } } static ssize_t file_pwrite(struct file_context *fc, char *buf, size_t count, off_t off) { if (fc->is_nfs == 0) { lseek(fc->fd, off, SEEK_SET); return write(fc->fd, buf, count); } else { return nfs_pwrite(fc->nfs, fc->nfsfh, off, count, buf); } } static struct file_context * open_file(const char *url, int flags) { struct file_context *file_context; file_context = malloc(sizeof(struct file_context)); if (file_context == NULL) { fprintf(stderr, "Failed to malloc file_context\n"); return NULL; } file_context->is_nfs = 0; file_context->fd = -1; file_context->nfs = NULL; file_context->nfsfh = NULL; file_context->url = NULL; if (strncmp(url, "nfs://", 6)) { file_context->is_nfs = 0; file_context->fd = open(url, flags, 0660); if (file_context->fd == -1) { fprintf(stderr, "Failed to open %s\n", url); free_file_context(file_context); return NULL; } return file_context; } file_context->is_nfs = 1; file_context->nfs = nfs_init_context(); if (file_context->nfs == NULL) { fprintf(stderr, "failed to init context\n"); free_file_context(file_context); return NULL; } file_context->url = nfs_parse_url_full(file_context->nfs, url); if (file_context->url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(file_context->nfs)); free_file_context(file_context); return NULL; } if (nfs_mount(file_context->nfs, file_context->url->server, file_context->url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(file_context->nfs)); free_file_context(file_context); return NULL; } if (flags == O_RDONLY) { if (nfs_open(file_context->nfs, file_context->url->file, flags, &file_context->nfsfh) != 0) { fprintf(stderr, "Failed to open file %s: %s\n", file_context->url->file, nfs_get_error(file_context->nfs)); free_file_context(file_context); return NULL; } } else { if (nfs_create(file_context->nfs, file_context->url->file, flags, 0660, &file_context->nfsfh) != 0) { fprintf(stderr, "Failed to creat file %s: %s\n", file_context->url->file, nfs_get_error(file_context->nfs)); free_file_context(file_context); return NULL; } } return file_context; } #define BUFSIZE 1024*1024 static char buf[BUFSIZE]; int main(int argc, char *argv[]) { struct stat st; struct file_context *src; struct file_context *dst; off_t off; ssize_t count; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); return 10; } #endif #ifdef AROS aros_init_socket(); #endif if (argc != 3) { usage(); } src = open_file(argv[1], O_RDONLY); if (src == NULL) { fprintf(stderr, "Failed to open %s\n", argv[1]); return 10; } dst = open_file(argv[2], O_WRONLY|O_CREAT|O_EXCL|O_TRUNC); if (dst == NULL) { fprintf(stderr, "Failed to open %s\n", argv[2]); free_file_context(src); return 10; } if (fstat_file(src, &st) != 0) { fprintf(stderr, "Failed to fstat source file\n"); free_file_context(src); free_file_context(dst); return 10; } off = 0; while (off < st.st_size) { count = (size_t)(st.st_size - off); if (count > BUFSIZE) { count = BUFSIZE; } count = file_pread(src, buf, count, off); if (count < 0) { fprintf(stderr, "Failed to read from source file\n"); free_file_context(src); free_file_context(dst); return 10; } count = file_pwrite(dst, buf, count, off); if (count < 0) { fprintf(stderr, "Failed to write to dest file\n"); free_file_context(src); free_file_context(dst); return 10; } off += count; } printf("copied %d bytes\n", (int)off); free_file_context(src); free_file_context(dst); return 0; } libnfs-libnfs-4.0.0/utils/nfs-ls.c000066400000000000000000000137041343063627400167660ustar00rootroot00000000000000/* Copyright (C) by Ronnie Sahlberg 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #define _FILE_OFFSET_BITS 64 #define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef AROS #include "aros_compat.h" #endif #ifdef WIN32 #include #pragma comment(lib, "ws2_32.lib") WSADATA wsaData; #define PRId64 "ll" #else #include #include #include #ifndef AROS #ifdef __ANDROID__ #define statvfs statfs #include #else #include #endif #endif #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" struct client { char *server; char *export; uint32_t mount_port; int is_finished; }; int recursive = 0, summary = 0, discovery = 0; void print_usage(void) { fprintf(stderr, "Usage: nfs-ls [-?|--help|--usage] [-R|--recursive] [-s|--summary] [-D|--discovery] \n"); } int process_server(const char *server) { struct exportnode *exports; struct exportnode *export; exports = mount_getexports(server); if (exports == NULL) { fprintf(stderr, "Failed to get exports for server %s.\n", server); return -1; } for (export=exports; export; export = export->ex_next) { printf("nfs://%s%s\n", server, export->ex_dir); } mount_free_export_list(exports); return 0; } void process_dir(struct nfs_context *nfs, char *dir, int level) { int ret; struct nfsdirent *nfsdirent; struct nfsdir *nfsdir; if (!level) { printf("Recursion detected!\n"); exit(10); } ret = nfs_opendir(nfs, dir, &nfsdir); if (ret != 0) { printf("Failed to opendir(\"%s\") %s\n", dir, nfs_get_error(nfs)); exit(10); } while((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) { char path[1024]; if (!strcmp(nfsdirent->name, ".") || !strcmp(nfsdirent->name, "..")) { continue; } snprintf(path, 1024, "%s/%s", dir, nfsdirent->name); switch (nfsdirent->mode & S_IFMT) { case S_IFLNK: printf("l"); break; case S_IFREG: printf("-"); break; case S_IFDIR: printf("d"); break; case S_IFCHR: printf("c"); break; case S_IFBLK: printf("b"); break; } printf("%c%c%c", "-r"[!!(nfsdirent->mode & S_IRUSR)], "-w"[!!(nfsdirent->mode & S_IWUSR)], "-x"[!!(nfsdirent->mode & S_IXUSR)] ); printf("%c%c%c", "-r"[!!(nfsdirent->mode & S_IRGRP)], "-w"[!!(nfsdirent->mode & S_IWGRP)], "-x"[!!(nfsdirent->mode & S_IXGRP)] ); printf("%c%c%c", "-r"[!!(nfsdirent->mode & S_IROTH)], "-w"[!!(nfsdirent->mode & S_IWOTH)], "-x"[!!(nfsdirent->mode & S_IXOTH)] ); printf(" %2d", (int)nfsdirent->nlink); printf(" %5d", (int)nfsdirent->uid); printf(" %5d", (int)nfsdirent->gid); printf(" %12" PRId64, nfsdirent->size); printf(" %s\n", path + 1); if (recursive && (nfsdirent->mode & S_IFMT) == S_IFDIR) { process_dir(nfs, path, level - 1); } } nfs_closedir(nfs, nfsdir); } int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; int i, ret = 1; struct client client; struct statvfs stvfs; struct nfs_url *url = NULL; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("Failed to start Winsock2\n"); exit(10); } #endif #ifdef AROS aros_init_socket(); #endif if (argc < 2) { fprintf(stderr, "No URL specified.\n"); goto finished; } for (i=1; i < argc -1; i++) { if (!strcmp(argv[i], "-R") || !strcmp(argv[i], "--recursive")) { recursive++; } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--summary")) { summary++; } else if (!strcmp(argv[i], "-D") || !strcmp(argv[i], "--discovery")) { discovery++; } else{ goto finished; } } nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); goto finished; } if (discovery) { url = nfs_parse_url_incomplete(nfs, argv[argc - 1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); goto finished; } if (!url->server) { struct nfs_server_list *srvrs; struct nfs_server_list *srv; srvrs = nfs_find_local_servers(); if (srvrs == NULL) { fprintf(stderr, "Failed to find local servers.\n"); goto finished; } for (srv=srvrs; srv; srv = srv->next) { if (recursive) { process_server(srv->addr); } else { printf("nfs://%s\n", srv->addr); } } free_nfs_srvr_list(srvrs); ret = 0; goto finished; } if (url->server && !url->path) { ret = process_server(url->server); goto finished; } nfs_destroy_url(url); } url = nfs_parse_url_dir(nfs, argv[argc - 1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); goto finished; } client.server = url->server; client.export = url->path; client.is_finished = 0; if ((ret = nfs_mount(nfs, client.server, client.export)) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); goto finished; } process_dir(nfs, "", 16); if (summary) { if (nfs_statvfs(nfs, "", &stvfs) != 0) { goto finished; } printf("\n%12" PRId64 " of %12" PRId64 " bytes free.\n", (uint64_t)(stvfs.f_frsize * stvfs.f_bfree), (uint64_t)(stvfs.f_frsize * stvfs.f_blocks)); } ret = 0; finished: if (ret > 0) { print_usage(); } nfs_destroy_url(url); if (nfs != NULL) { nfs_destroy_context(nfs); } return ret; } libnfs-libnfs-4.0.0/win32/000077500000000000000000000000001343063627400152155ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/CMakeLists.txt000066400000000000000000000001621343063627400177540ustar00rootroot00000000000000set(SOURCES win32_compat.c) set(HEADERS win32_compat.h win32_errnowrapper.h) core_add_library(win32) libnfs-libnfs-4.0.0/win32/libnfs/000077500000000000000000000000001343063627400164725ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/libnfs/libnfs.sln000066400000000000000000000131671343063627400204750ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnfs", "libnfs.vcxproj", "{7CAB9B67-6AA9-497F-A900-20D9D05049F5}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nfs-cp", "..\nfs-cp\nfs-cp.vcxproj", "{8C223950-DD30-4C89-BD5D-C105951FE2B6}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nfs-ls", "..\nfs-ls\nfs-ls.vcxproj", "{43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {7CAB9B67-6AA9-497F-A900-20D9D05049F5}.Debug|Win32.ActiveCfg = Debug|Win32 {7CAB9B67-6AA9-497F-A900-20D9D05049F5}.Debug|Win32.Build.0 = Debug|Win32 {7CAB9B67-6AA9-497F-A900-20D9D05049F5}.Debug|x64.ActiveCfg = Debug|x64 {7CAB9B67-6AA9-497F-A900-20D9D05049F5}.Debug|x64.Build.0 = Debug|x64 {7CAB9B67-6AA9-497F-A900-20D9D05049F5}.Release|Win32.ActiveCfg = Release|Win32 {7CAB9B67-6AA9-497F-A900-20D9D05049F5}.Release|Win32.Build.0 = Release|Win32 {7CAB9B67-6AA9-497F-A900-20D9D05049F5}.Release|x64.ActiveCfg = Release|x64 {7CAB9B67-6AA9-497F-A900-20D9D05049F5}.Release|x64.Build.0 = Release|x64 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5}.Debug|Win32.ActiveCfg = Debug|Win32 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5}.Debug|Win32.Build.0 = Debug|Win32 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5}.Debug|x64.ActiveCfg = Debug|x64 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5}.Debug|x64.Build.0 = Debug|x64 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5}.Release|Win32.ActiveCfg = Release|Win32 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5}.Release|Win32.Build.0 = Release|Win32 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5}.Release|x64.ActiveCfg = Release|x64 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5}.Release|x64.Build.0 = Release|x64 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0}.Debug|Win32.ActiveCfg = Debug|Win32 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0}.Debug|Win32.Build.0 = Debug|Win32 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0}.Debug|x64.ActiveCfg = Debug|x64 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0}.Debug|x64.Build.0 = Debug|x64 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0}.Release|Win32.ActiveCfg = Release|Win32 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0}.Release|Win32.Build.0 = Release|Win32 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0}.Release|x64.ActiveCfg = Release|x64 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0}.Release|x64.Build.0 = Release|x64 {4F1B789D-B760-4B27-A5AD-D923765413F4}.Debug|Win32.ActiveCfg = Debug|Win32 {4F1B789D-B760-4B27-A5AD-D923765413F4}.Debug|Win32.Build.0 = Debug|Win32 {4F1B789D-B760-4B27-A5AD-D923765413F4}.Debug|x64.ActiveCfg = Debug|x64 {4F1B789D-B760-4B27-A5AD-D923765413F4}.Debug|x64.Build.0 = Debug|x64 {4F1B789D-B760-4B27-A5AD-D923765413F4}.Release|Win32.ActiveCfg = Release|Win32 {4F1B789D-B760-4B27-A5AD-D923765413F4}.Release|Win32.Build.0 = Release|Win32 {4F1B789D-B760-4B27-A5AD-D923765413F4}.Release|x64.ActiveCfg = Release|x64 {4F1B789D-B760-4B27-A5AD-D923765413F4}.Release|x64.Build.0 = Release|x64 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6}.Debug|Win32.ActiveCfg = Debug|Win32 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6}.Debug|Win32.Build.0 = Debug|Win32 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6}.Debug|x64.ActiveCfg = Debug|x64 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6}.Debug|x64.Build.0 = Debug|x64 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6}.Release|Win32.ActiveCfg = Release|Win32 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6}.Release|Win32.Build.0 = Release|Win32 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6}.Release|x64.ActiveCfg = Release|x64 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6}.Release|x64.Build.0 = Release|x64 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5}.Debug|Win32.ActiveCfg = Debug|Win32 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5}.Debug|Win32.Build.0 = Debug|Win32 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5}.Debug|x64.ActiveCfg = Debug|x64 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5}.Debug|x64.Build.0 = Debug|x64 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5}.Release|Win32.ActiveCfg = Release|Win32 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5}.Release|Win32.Build.0 = Release|Win32 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5}.Release|x64.ActiveCfg = Release|x64 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5}.Release|x64.Build.0 = Release|x64 {8C223950-DD30-4C89-BD5D-C105951FE2B6}.Debug|Win32.ActiveCfg = Debug|Win32 {8C223950-DD30-4C89-BD5D-C105951FE2B6}.Debug|Win32.Build.0 = Debug|Win32 {8C223950-DD30-4C89-BD5D-C105951FE2B6}.Debug|x64.ActiveCfg = Debug|x64 {8C223950-DD30-4C89-BD5D-C105951FE2B6}.Debug|x64.Build.0 = Debug|x64 {8C223950-DD30-4C89-BD5D-C105951FE2B6}.Release|Win32.ActiveCfg = Release|Win32 {8C223950-DD30-4C89-BD5D-C105951FE2B6}.Release|Win32.Build.0 = Release|Win32 {8C223950-DD30-4C89-BD5D-C105951FE2B6}.Release|x64.ActiveCfg = Release|x64 {8C223950-DD30-4C89-BD5D-C105951FE2B6}.Release|x64.Build.0 = Release|x64 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}.Debug|Win32.ActiveCfg = Debug|Win32 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}.Debug|Win32.Build.0 = Debug|Win32 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}.Debug|x64.ActiveCfg = Debug|x64 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}.Debug|x64.Build.0 = Debug|x64 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}.Release|Win32.ActiveCfg = Release|Win32 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}.Release|Win32.Build.0 = Release|Win32 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}.Release|x64.ActiveCfg = Release|x64 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal libnfs-libnfs-4.0.0/win32/libnfs/libnfs.vcxproj000066400000000000000000000265061343063627400213750ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {7CAB9B67-6AA9-497F-A900-20D9D05049F5} Win32Proj libnfs DynamicLibrary true MultiByte DynamicLibrary true MultiByte DynamicLibrary false true MultiByte DynamicLibrary false true MultiByte true $(LibraryPath) $(ExecutablePath) true $(LibraryPath) $(ExecutablePath) false $(LibraryPath) $(ExecutablePath) false $(LibraryPath) $(ExecutablePath) Level3 Disabled WIN32;NDEBUG;_WINDOWS;_USRDLL;_U_=;_USE_32BIT_TIME_T;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\nfs4;..\..\portmap;..\..\lib Default 4996 Windows true ..\..\lib\libnfs-win32.def ws2_32.lib;%(AdditionalDependencies) MSVCRT Level3 Disabled WIN32;NDEBUG;_WINDOWS;_USRDLL;_U_=;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\nfs4;..\..\portmap;..\..\lib Default 4996 Windows true ..\..\lib\libnfs-win32.def ws2_32.lib;%(AdditionalDependencies) MSVCRT Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;_USRDLL;_U_=;_USE_32BIT_TIME_T;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\nfs4;..\..\portmap;..\..\lib 4996 Windows true true true ws2_32.lib;%(AdditionalDependencies) ..\..\lib\libnfs-win32.def Level3 Full true true WIN32;NDEBUG;_WINDOWS;_USRDLL;_U_=;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\nfs4;..\..\portmap;..\..\lib 4996 AnySuitable Speed Windows true true true ws2_32.lib;%(AdditionalDependencies) ..\..\lib\libnfs-win32.def libnfs-libnfs-4.0.0/win32/libnfs/libnfs.vcxproj.filters000066400000000000000000000102501343063627400230310ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files libnfs-libnfs-4.0.0/win32/libnfs/version.rc000066400000000000000000000046521343063627400205140ustar00rootroot00000000000000// Microsoft Visual C++ generated resource script. // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Deutsch (Deutschland) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) LANGUAGE LANG_GERMAN, SUBLANG_GERMAN #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource1.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,8,0,0 PRODUCTVERSION 1,8,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040704b0" BEGIN VALUE "CompanyName", "https://github.com/sahlberg/libnfs" VALUE "FileDescription", "LIBNFS is a client library for accessing NFS shares over a network." VALUE "FileVersion", "1.8.0.0" VALUE "InternalName", "libnfs.dll" VALUE "LegalCopyright", "Copyright (C) 2014" VALUE "OriginalFilename", "libnfs.dll" VALUE "ProductName", "libnfs" VALUE "ProductVersion", "1.8.0.0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x407, 1200 END END #endif // Deutsch (Deutschland) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED libnfs-libnfs-4.0.0/win32/nfs-cp/000077500000000000000000000000001343063627400164035ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/nfs-cp/nfs-cp.vcxproj000066400000000000000000000206011343063627400212050ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {8C223950-DD30-4C89-BD5D-C105951FE2B6} Win32Proj nfsclientsync Application true Unicode Application true Unicode Application false true Unicode Application false true Unicode true ..\libnfs\Debug;..\..\bin;$(LibraryPath) true ..\libnfs\Debug;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) libnfs-libnfs-4.0.0/win32/nfs-cp/nfs-cp.vcxproj.filters000066400000000000000000000007661343063627400226660ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files libnfs-libnfs-4.0.0/win32/nfs-ls/000077500000000000000000000000001343063627400164175ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/nfs-ls/nfs-ls.vcxproj000066400000000000000000000206001343063627400212340ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {43A2C9EF-338F-4326-9DF2-1CE0B1DA1C6B} Win32Proj nfsclientsync Application true Unicode Application true Unicode Application false true Unicode Application false true Unicode true ..\libnfs\Debug;..\..\bin;$(LibraryPath) true ..\libnfs\Debug;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) libnfs-libnfs-4.0.0/win32/nfs-ls/nfs-ls.vcxproj.filters000066400000000000000000000007661343063627400227160ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files libnfs-libnfs-4.0.0/win32/nfsclient-async/000077500000000000000000000000001343063627400203155ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/nfsclient-async/nfsclient-async.vcxproj000066400000000000000000000207101343063627400250320ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {00EB73F2-8DA9-43DC-A0BB-5A09464DA4A0} Win32Proj nfsclientsync Application true Unicode Application true Unicode Application false true Unicode Application false true Unicode true ..\libnfs\Release;..\..\bin;$(LibraryPath) true ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\portmap;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) libnfs-libnfs-4.0.0/win32/nfsclient-async/nfsclient-async.vcxproj.filters000066400000000000000000000010041343063627400264740ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files libnfs-libnfs-4.0.0/win32/nfsclient-bcast/000077500000000000000000000000001343063627400202745ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/nfsclient-bcast/nfsclient-bcast.vcxproj000066400000000000000000000207101343063627400247700ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {4F1B789D-B760-4B27-A5AD-D923765413F4} Win32Proj nfsclientsync Application true Unicode Application true Unicode Application false true Unicode Application false true Unicode true ..\libnfs\Release;..\..\bin;$(LibraryPath) true ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) libnfs-libnfs-4.0.0/win32/nfsclient-bcast/nfsclient-bcast.vcxproj.filters000066400000000000000000000010041343063627400264320ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files libnfs-libnfs-4.0.0/win32/nfsclient-listservers/000077500000000000000000000000001343063627400215655ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/nfsclient-listservers/nfsclient-listservers.vcxproj000066400000000000000000000206261343063627400275600ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {C9EE015F-D35B-4DC6-B024-7C9C2C5D45E6} Win32Proj nfsclientsync Application true Unicode Application true Unicode Application false true Unicode Application false true Unicode true ..\libnfs\Release;..\..\bin;$(LibraryPath) true ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) libnfs-libnfs-4.0.0/win32/nfsclient-listservers/nfsclient-listservers.vcxproj.filters000066400000000000000000000010121343063627400312130ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files libnfs-libnfs-4.0.0/win32/nfsclient-raw/000077500000000000000000000000001343063627400177715ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/nfsclient-raw/nfsclient-raw.vcxproj000066400000000000000000000206501343063627400241650ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {5C31C9BE-13AA-4012-A3C2-12A8042BE0B5} Win32Proj nfsclientsync Application true Unicode Application true Unicode Application false true Unicode Application false true Unicode true ..\libnfs\Release;..\..\bin;$(LibraryPath) true ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\rquota Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap;..\..\rquota Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) libnfs-libnfs-4.0.0/win32/nfsclient-raw/nfsclient-raw.vcxproj.filters000066400000000000000000000010021343063627400256220ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files libnfs-libnfs-4.0.0/win32/nfsclient-sync/000077500000000000000000000000001343063627400201545ustar00rootroot00000000000000libnfs-libnfs-4.0.0/win32/nfsclient-sync/nfsclient-sync.vcxproj000066400000000000000000000206171343063627400245360ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {B907AC9A-50C5-4E43-97C3-27DC7241F6C5} Win32Proj nfsclientsync Application true Unicode Application true Unicode Application false true Unicode Application false true Unicode true ..\libnfs\Release;..\..\bin;$(LibraryPath) true ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) false ..\libnfs\Release;..\..\bin;$(LibraryPath) Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 Disabled WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) false true Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions) ..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap Console true true true libnfs.lib;WS2_32.lib;%(AdditionalDependencies) libnfs-libnfs-4.0.0/win32/nfsclient-sync/nfsclient-sync.vcxproj.filters000066400000000000000000000010031343063627400261710ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files libnfs-libnfs-4.0.0/win32/win32_compat.c000066400000000000000000000115371343063627400176750ustar00rootroot00000000000000/* Copyright (c) 2006 by Dan Kennedy. Copyright (c) 2006 by Juliusz Chroboczek. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef WIN32 static int dummy _U_; #else #include #include #include #undef poll #undef socket #undef connect #undef accept #undef shutdown #undef getpeername #undef sleep #undef inet_aton #undef gettimeofday #undef stat #define assert(a) /* Windows needs this header file for the implementation of inet_aton() */ #include int win32_inet_pton(int af, const char * src, void * dst) { struct sockaddr_in sa; int len = sizeof(SOCKADDR); int ret = -1; int strLen = strlen(src) + 1; #ifdef UNICODE wchar_t *srcNonConst = (wchar_t *)malloc(strLen*sizeof(wchar_t)); memset(srcNonConst, 0, strLen); MultiByteToWideChar(CP_ACP, 0, src, -1, srcNonConst, strLen); #else char *srcNonConst = (char *)malloc(strLen); memset(srcNonConst, 0, strLen); strncpy(srcNonConst, src, strLen); #endif if( WSAStringToAddress(srcNonConst,af,NULL,(LPSOCKADDR)&sa,&len) == 0 ) { ret = 1; } else { if( WSAGetLastError() == WSAEINVAL ) { ret = -1; } } free(srcNonConst); memcpy(dst, &sa.sin_addr, sizeof(struct in_addr)); return ret; } int win32_poll(struct pollfd *fds, unsigned int nfds, int timo) { struct timeval timeout, *toptr; fd_set ifds, ofds, efds, *ip, *op; unsigned int i; int rc; // Set up the file-descriptor sets in ifds, ofds and efds. FD_ZERO(&ifds); FD_ZERO(&ofds); FD_ZERO(&efds); for (i = 0, op = ip = 0; i < nfds; ++i) { fds[i].revents = 0; if(fds[i].events & (POLLIN|POLLPRI)) { ip = &ifds; FD_SET(fds[i].fd, ip); } if(fds[i].events & POLLOUT) { op = &ofds; FD_SET(fds[i].fd, op); } FD_SET(fds[i].fd, &efds); } // Set up the timeval structure for the timeout parameter if(timo < 0) { toptr = 0; } else { toptr = &timeout; timeout.tv_sec = timo / 1000; timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000; } #ifdef DEBUG_POLL printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n", (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op); #endif rc = select(0, ip, op, &efds, toptr); #ifdef DEBUG_POLL printf("Exiting select rc=%d\n", rc); #endif if(rc <= 0) return rc; if(rc > 0) { for (i = 0; i < nfds; ++i) { int fd = fds[i].fd; if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds)) fds[i].revents |= POLLIN; if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds)) fds[i].revents |= POLLOUT; if(FD_ISSET(fd, &efds)) // Some error was detected ... should be some way to know. fds[i].revents |= POLLHUP; #ifdef DEBUG_POLL printf("%d %d %d revent = %x\n", FD_ISSET(fd, &ifds), FD_ISSET(fd, &ofds), FD_ISSET(fd, &efds), fds[i].revents ); #endif } } return rc; } #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 #else #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL #endif #ifndef __MINGW32__ struct timezone { int tz_minuteswest; /* minutes W of Greenwich */ int tz_dsttime; /* type of dst correction */ }; int win32_gettimeofday(struct timeval *tv, struct timezone *tz) { FILETIME ft; unsigned __int64 tmpres = 0; static int tzflag; if (NULL != tv) { GetSystemTimeAsFileTime(&ft); tmpres |= ft.dwHighDateTime; tmpres <<= 32; tmpres |= ft.dwLowDateTime; /*converting file time to unix epoch*/ tmpres -= DELTA_EPOCH_IN_MICROSECS; tmpres /= 10; /*convert into microseconds*/ tv->tv_sec = (long)(tmpres / 1000000UL); tv->tv_usec = (long)(tmpres % 1000000UL); } if (NULL != tz) { if (!tzflag) { _tzset(); tzflag++; } tz->tz_minuteswest = _timezone / 60; tz->tz_dsttime = _daylight; } return 0; } #endif #endif libnfs-libnfs-4.0.0/win32/win32_errnowrapper.h000066400000000000000000000026621343063627400211440ustar00rootroot00000000000000/* Copyright (c) 2014, Ronnie Sahlberg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef WIN32_ERRNOWRAPPER_H_ #define WIN32_ERRNOWRAPPER_H_ #undef errno #define errno WSAGetLastError() #undef EAGAIN #undef EWOULDBLOCK #undef EINTR #undef EINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK #define EAGAIN WSAEWOULDBLOCK //same on windows #define EINTR WSAEINTR #define EINPROGRESS WSAEWOULDBLOCK //does not map to WSAEINPROGRESS ! #endif //WIN32_ERRNOWRAPPER_H_ libnfs-libnfs-4.0.0/win32/win32build.bat000066400000000000000000000056641343063627400177020ustar00rootroot00000000000000rem build script for win32 rem set the rem rem EDIT THESE set LIBNFS_BASE_DIR=.. rem END EDIT cd %LIBNFS_BASE_DIR% rem NFS rem cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd nfs\libnfs-raw-nfs.c -Fonfs\libnfs-raw-nfs.obj cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd nfs\nfs.c -Fonfs\nfs.obj cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd nfs\nfsacl.c -Fonfs\nfsacl.obj rem rem RQUOTA rem cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd rquota\libnfs-raw-rquota.c -Forquota\libnfs-raw-rquota.obj cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd rquota\rquota.c -Forquota\rquota.obj rem rem PORTMAP rem cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd portmap\libnfs-raw-portmap.c -Foportmap\libnfs-raw-portmap.obj cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd portmap\portmap.c -Foportmap\portmap.obj rem rem MOUNT rem cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd mount\libnfs-raw-mount.c -Fomount\libnfs-raw-mount.obj cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd mount\mount.c -Fomount\mount.obj rem rem generate core part of library rem cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd lib\init.c -Folib\init.obj cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd -D_U_="" lib\pdu.c -Folib\pdu.obj cl /I. /Iinclude /Iwin32 -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd -D_U_="" lib\socket.c -Folib\socket.obj cl /I. /Iinclude /Iwin32 /Imount /Infs -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd -D_U_="" lib\libnfs.c -Folib\libnfs.obj cl /I. /Iinclude /Iwin32 /Imount /Infs -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd -D_U_="" lib\libnfs-sync.c -Folib\libnfs-sync.obj rem rem generate win32 compat layer rem cl /I. -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0501 -MDd -D_U_="" win32\win32_compat.c -Fowin32\win32_compat.obj rem rem create a linklibrary/dll rem lib /out:lib\libnfs.lib /def:lib\libnfs-win32.def nfs\nfs.obj nfs\nfsacl.obj nfs\libnfs-raw-nfs.obj rquota\rquota.obj rquota\libnfs-raw-rquota.obj mount\mount.obj mount\libnfs-raw-mount.obj portmap\portmap.obj portmap\libnfs-raw-portmap.obj lib\init.obj lib\pdu.obj lib\socket.obj lib\libnfs.obj lib\libnfs-sync.obj win32\win32_compat.obj link /DLL /out:lib\libnfs.dll /DEBUG /DEBUGTYPE:cv lib\libnfs.exp nfs\nfs.obj nfs\nfsacl.obj nfs\libnfs-raw-nfs.obj rquota\rquota.obj rquota\libnfs-raw-rquota.obj mount\mount.obj mount\libnfs-raw-mount.obj portmap\portmap.obj portmap\libnfs-raw-portmap.obj lib\init.obj lib\pdu.obj lib\socket.obj lib\libnfs.obj lib\libnfs-sync.obj win32\win32_compat.obj ws2_32.lib rem rem build a test application rem cl /I. /Iinclude /Iwin32 /Imount /Infs -Zi -Od -DWIN32 -D_WIN32_WINNT=0x0501 -MDd -D_U_="" examples\nfsclient-sync.c lib\libnfs.lib WS2_32.lib kernel32.lib mswsock.lib advapi32.lib wsock32.lib advapi32.lib libnfs-libnfs-4.0.0/win32build.bat000077500000000000000000000067241343063627400167410ustar00rootroot00000000000000rem build script for win32 rem set the rem rem NFS rem cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd nfs\libnfs-raw-nfs.c -Fonfs\libnfs-raw-nfs.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd nfs\nfs.c -Fonfs\nfs.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd nfs\nfsacl.c -Fonfs\nfsacl.obj rem rem RQUOTA rem cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd rquota\libnfs-raw-rquota.c -Forquota\libnfs-raw-rquota.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd rquota\rquota.c -Forquota\rquota.obj rem rem PORTMAP rem cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd portmap\libnfs-raw-portmap.c -Foportmap\libnfs-raw-portmap.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd portmap\portmap.c -Foportmap\portmap.obj rem rem MOUNT rem cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd mount\libnfs-raw-mount.c -Fomount\libnfs-raw-mount.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd mount\mount.c -Fomount\mount.obj rem rem generate core part of library rem cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\init.c -Folib\init.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd -D_U_="" lib\pdu.c -Folib\pdu.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd -D_U_="" lib\socket.c -Folib\socket.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude /Imount /Infs -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd -D_U_="" lib\libnfs.c -Folib\libnfs.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude /Imount /Infs -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd -D_U_="" lib\libnfs-sync.c -Folib\libnfs-sync.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude /Imount /Infs -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd -D_U_="" lib\libnfs-zdr.c -Folib\libnfs-zdr.obj cl /I. /Iwin32 /Iinclude/nfsc /Iinclude /Imount /Infs -Zi -Od -c -DWIN32 -D_WIN32_WINNT=0x0600 -MDd -D_U_="" win32\win32_compat.c -Fowin32\win32_compat.obj rem rem create a linklibrary/dll rem lib /out:lib\libnfs.lib /def:lib\libnfs-win32.def nfs\nfs.obj nfs\nfsacl.obj nfs\libnfs-raw-nfs.obj rquota\rquota.obj rquota\libnfs-raw-rquota.obj mount\mount.obj mount\libnfs-raw-mount.obj portmap\portmap.obj portmap\libnfs-raw-portmap.obj lib\init.obj lib\pdu.obj lib\socket.obj lib\libnfs.obj lib\libnfs-sync.obj lib\libnfs-zdr.obj win32\win32_compat.obj link /DLL /out:lib\libnfs.dll /DEBUG /DEBUGTYPE:cv lib\libnfs.exp nfs\nfs.obj nfs\nfsacl.obj nfs\libnfs-raw-nfs.obj rquota\rquota.obj rquota\libnfs-raw-rquota.obj mount\mount.obj mount\libnfs-raw-mount.obj portmap\portmap.obj portmap\libnfs-raw-portmap.obj lib\init.obj lib\pdu.obj lib\socket.obj lib\libnfs.obj lib\libnfs-sync.obj lib\libnfs-zdr.obj win32\win32_compat.obj ws2_32.lib rem rem build a test application rem cl /I. /Iwin32 /Iinclude/nfsc /Iinclude /Imount /Infs -Zi -Od -DWIN32 -D_WIN32_WINNT=0x0600 -MDd -D_U_="" examples\nfs-ls.c lib\libnfs.lib WS2_32.lib kernel32.lib mswsock.lib advapi32.lib wsock32.lib advapi32.lib cl /I. /Iwin32 /Iinclude/nfsc /Iinclude /Imount /Infs -Zi -Od -DWIN32 -D_WIN32_WINNT=0x0600 -MDd -D_U_="" examples\nfs-cp.c lib\libnfs.lib WS2_32.lib kernel32.lib mswsock.lib advapi32.lib wsock32.lib advapi32.lib