Compare commits
114 Commits
libnfs-4.0
...
master
Author | SHA1 | Date |
---|---|---|
Vitaliy Filippov | 5a991e1fcb | |
Vitaliy Filippov | 338e176320 | |
Ronnie Sahlberg | 1703d4479d | |
Vitaliy Filippov | 45430b3c38 | |
Ronnie Sahlberg | 4785ab7eae | |
Ronnie Sahlberg | 2772c70be6 | |
Ronnie Sahlberg | 32349ab58b | |
Ronnie Sahlberg | beaf4cd769 | |
Ronnie Sahlberg | c33e0c3825 | |
Ronnie Sahlberg | 382905495f | |
heitbaum | fe62199737 | |
heitbaum | 680ceb8d2c | |
heitbaum | 7b7648e0d8 | |
heitbaum | 26133258fd | |
Ronnie Sahlberg | a48f019e05 | |
Ronnie Sahlberg | 29b4cea00f | |
Ronnie Sahlberg | f85c21755e | |
Ronnie Sahlberg | 0550a5c83f | |
Ronnie Sahlberg | 61e5863e46 | |
Ronnie Sahlberg | 4ca1e05f4e | |
Ronnie Sahlberg | 1716b14104 | |
Ronnie Sahlberg | 630a80c056 | |
Ronnie Sahlberg | 1648cd8393 | |
Ronnie Sahlberg | efa9085cfa | |
Ronnie Sahlberg | c851f458a0 | |
Ronnie Sahlberg | 20b39fd251 | |
Ronnie Sahlberg | 52c7bd7bc5 | |
Ronnie Sahlberg | f55637619e | |
Ronnie Sahlberg | 81f4609076 | |
Vitaliy Filippov | d1999dc956 | |
Ronnie Sahlberg | 4fa3b79569 | |
Daniel Abrecht | 939814826f | |
Ronnie Sahlberg | b1fbe322be | |
rhynec | f6a3b0147d | |
Ronnie Sahlberg | f965ec74cf | |
Ronnie Sahlberg | f88cca547d | |
Ronnie Sahlberg | fca28fe112 | |
Ronnie Sahlberg | 820dc73e32 | |
Ronnie Sahlberg | 965b1914ef | |
Ronnie Sahlberg | af90dbfbcf | |
Ronnie Sahlberg | d1494d41de | |
Ronnie Sahlberg | 752cb4134d | |
Ronnie Sahlberg | cdb377532a | |
Ronnie Sahlberg | 1cdc8657de | |
Ronnie Sahlberg | be437aa102 | |
Ronnie Sahlberg | a7c6637980 | |
Daniel Abrecht | 4ae2f12b74 | |
Ronnie Sahlberg | 9a10e17800 | |
Damian | 901d4a0040 | |
Ronnie Sahlberg | bbb9c337b5 | |
Damian Parrino | 5f74b69624 | |
Ronnie Sahlberg | da61d648e6 | |
Damian | 0df1d4beac | |
Damián Parrino | ef0056cd13 | |
Damian | 1bafddb264 | |
Damian | c14a5acb51 | |
Damian | c7ad0762d8 | |
Ronnie Sahlberg | ef0ca03565 | |
Ronnie Sahlberg | 8cf8c620f3 | |
Alan Somers | 172f46756e | |
Alan Somers | 2b3e8f450b | |
Ronnie Sahlberg | cf47ea7e6a | |
Adam Yi | dfa85d4c36 | |
Ronnie Sahlberg | 17f882fbdb | |
Ronnie Sahlberg | c5d022b638 | |
Ronnie Sahlberg | da2a3dd9d3 | |
Ronnie Sahlberg | ff73bb6cc3 | |
Ronnie Sahlberg | de3d1e5f3f | |
Ronnie Sahlberg | d690031049 | |
Ronnie Sahlberg | 523df1eee4 | |
Ronnie Sahlberg | 52f905291c | |
Ronnie Sahlberg | a45799ca50 | |
Ronnie Sahlberg | 61d235ae44 | |
Ronnie Sahlberg | f7b6bef8ef | |
Ronnie Sahlberg | af97775bfc | |
Ronnie Sahlberg | 0b4c428ed3 | |
Ronnie Sahlberg | b994dd08a3 | |
Ronnie Sahlberg | a18aff5e7a | |
Ronnie Sahlberg | 0971e9531f | |
Ronnie Sahlberg | 03a47809cb | |
Ronnie Sahlberg | be084815fa | |
Ronnie Sahlberg | edce6654a3 | |
Ronnie Sahlberg | 4f1925c280 | |
peak3d | 74ac9b5e11 | |
Ronnie Sahlberg | 3fbec953e6 | |
Ronnie Sahlberg | 46c8a3006a | |
Ronnie Sahlberg | f79745d281 | |
Ronnie Sahlberg | 4dd823b4a1 | |
Dirk Meister | 483be177fe | |
Dirk Meister | 1336b5280e | |
Ronnie Sahlberg | 12b56b8f52 | |
DetlefGolze | b9c85afc4f | |
Alwin Esch | b2fd0fe140 | |
Ronnie Sahlberg | 394b185486 | |
Ronnie Sahlberg | 548fa961a8 | |
Ronnie Sahlberg | 33a5d08b05 | |
Ronnie Sahlberg | 4c20a3f8eb | |
Volker Lendecke | 338837f6de | |
Ronnie Sahlberg | a7b9994971 | |
crusader-mike | 4b12b5e005 | |
crusader-mike | 70801203e2 | |
Ronnie Sahlberg | ac60feabf0 | |
crusader-mike | 9d5427bbd4 | |
Ronnie Sahlberg | e4fa3b5bcb | |
Ronnie Sahlberg | c635cae6f6 | |
crusader-mike | 4da7bb4fec | |
crusader-mike | 3cd06883e0 | |
crusader-mike | 6564abaa1f | |
Ronnie Sahlberg | 4de9fb8ff8 | |
Peter Lieven | 68faa72c85 | |
Ronnie Sahlberg | ca939ba918 | |
Volker Lendecke | 4bd145ba44 | |
Volker Lendecke | dfca3e447d | |
Balint Reczey | d214e3376b |
|
@ -1,6 +1,4 @@
|
|||
.*
|
||||
*.h
|
||||
*.c
|
||||
*.in
|
||||
*.la
|
||||
*.a
|
||||
|
@ -39,3 +37,18 @@ stamp-h1
|
|||
libnfs.pc
|
||||
!libnfs.pc.in
|
||||
build
|
||||
/win32/libnfs/x64/Debug/libnfs.tlog/CL.command.1.tlog
|
||||
/win32/libnfs/x64/Debug/libnfs.tlog/libnfs.lastbuildstate
|
||||
/win32/libnfs/x64/Debug/libnfs.tlog/unsuccessfulbuild
|
||||
/win32/libnfs/x64/Debug/libnfs.log
|
||||
/win32/libnfs/x64/Debug/vc143.idb
|
||||
/win32/nfs-cp/x64/Debug/nfs-cp.tlog/CL.command.1.tlog
|
||||
*.tlog
|
||||
/win32/nfs-cp/x64/Debug/nfs-cp.exe.recipe
|
||||
/win32/nfs-cp/x64/Debug/nfs-cp.log
|
||||
/win32/nfs-cp/x64/Debug/vc143.idb
|
||||
/win32/nfs-ls/x64/Debug/nfs-ls.exe.recipe
|
||||
/win32/nfs-ls/x64/Debug/nfs-ls.log
|
||||
/win32/nfs-ls/x64/Debug/vc143.idb
|
||||
/win32/libnfs/x64/Debug/libnfs.vcxproj.FileListAbsolute.txt
|
||||
/win32/libnfs/x64/Debug/version.res
|
||||
|
|
13
CHANGELOG
13
CHANGELOG
|
@ -1,3 +1,16 @@
|
|||
Changes since 5.0.0
|
||||
Fix non-pthread build
|
||||
|
||||
Changes since 4.0.0
|
||||
|
||||
Multithread support for Linux and Windows
|
||||
Fix NFS4 behavior of chmod/chown/utimes
|
||||
Add marshalling / unmarshalling of various NFSv4.1 structures (but not 4.1 support)
|
||||
PS3 support
|
||||
PS2 EE support
|
||||
Support escaped characters in the URL
|
||||
Fix MINGW build
|
||||
|
||||
Changes since 3.0.0
|
||||
|
||||
Fix the versioning in makerpms.sh
|
||||
|
|
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.2)
|
|||
|
||||
project(libnfs
|
||||
LANGUAGES C
|
||||
VERSION 2.0.0)
|
||||
VERSION 5.0.1)
|
||||
|
||||
set(SOVERSION 11.0.0 CACHE STRING "" FORCE)
|
||||
|
||||
|
@ -29,21 +29,42 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}
|
|||
include
|
||||
include/nfsc)
|
||||
|
||||
set(CORE_LIBRARIES nfs)
|
||||
set(core_DEPENDS "" CACHE STRING "" FORCE)
|
||||
# list of system libs (sockets/etc) to be linked on this system
|
||||
set(SYSTEM_LIBRARIES "")
|
||||
# list of core (static) libraries built in current configuration (used by lib/CMakeLists.txt)
|
||||
set(CORE_LIBRARIES "" CACHE INTERNAL "")
|
||||
|
||||
# make sure related functions are exported in final dll
|
||||
if(WIN32 AND BUILD_SHARED_LIBS)
|
||||
add_definitions(-Dlibnfs_EXPORTS)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
|
||||
list(APPEND CORE_LIBRARIES -lws2_32.lib)
|
||||
add_definitions("-D_U_=" -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
list(APPEND SYSTEM_LIBRARIES ws2_32)
|
||||
add_subdirectory(win32)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL Solaris)
|
||||
add_definitions("-D_U_=__attribute__((unused))")
|
||||
find_library(SOCKET_LIBRARY socket)
|
||||
find_library(NSL_LIBRARY nsl)
|
||||
list(APPEND CORE_LIBRARIES ${SOCKET_LIBRARY} ${NSL_LIBRARY})
|
||||
list(APPEND SYSTEM_LIBRARIES ${SOCKET_LIBRARY} ${NSL_LIBRARY})
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL aros)
|
||||
add_definitions("-D_U_=__attribute__((unused))")
|
||||
add_definitions(-DAROS)
|
||||
add_subdirectory(aros)
|
||||
else()
|
||||
add_definitions("-D_U_=__attribute__((unused))")
|
||||
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) # this has to be last (it links all static libs mentioned in CORE_LIBRARIES)
|
||||
|
||||
if(ENABLE_DOCUMENTATION)
|
||||
add_subdirectory(doc)
|
||||
endif()
|
||||
|
@ -61,23 +82,35 @@ 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)
|
||||
# this will create build-tree-specific config file (so downstream client can use this specific build without having to install package)
|
||||
export(EXPORT libnfs
|
||||
NAMESPACE libnfs::
|
||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/libnfs-config.cmake")
|
||||
|
||||
# this will create relocatable config file in installation directory
|
||||
install(EXPORT libnfs
|
||||
DESTINATION "${INSTALL_CMAKE_DIR}"
|
||||
NAMESPACE libnfs::
|
||||
FILE libnfs-config.cmake)
|
||||
|
||||
# handle version file
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/libnfs-config-version.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
|
||||
install(FILES cmake/FindNFS.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libnfs-config-version.cmake
|
||||
DESTINATION ${INSTALL_CMAKE_DIR})
|
||||
|
||||
# handle pc-config files
|
||||
configure_file(cmake/libnfs.pc.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libnfs.pc @ONLY)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfs.pc
|
||||
DESTINATION ${INSTALL_PKGCONFIG_DIR})
|
||||
|
||||
# handle headers installation
|
||||
install(DIRECTORY include/nfsc
|
||||
DESTINATION ${INSTALL_INC_DIR})
|
||||
|
||||
|
@ -88,10 +121,3 @@ install(FILES mount/libnfs-raw-mount.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})
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
To install
|
||||
|
||||
./bootstrap
|
||||
./configure (plus arguments)
|
||||
make
|
||||
sudo make install
|
||||
|
||||
|
||||
To build the examples specify --enable-examples to configure.
|
14
README
14
README
|
@ -40,7 +40,17 @@ URL-FORMAT:
|
|||
Libnfs uses RFC2224 style URLs extended with some minor libnfs extensions.
|
||||
The basic syntax of these URLs is :
|
||||
|
||||
nfs://<server|ipv4|ipv6>/path[?arg=val[&arg=val]*]
|
||||
nfs://<server|ipv4|ipv6>[:<port>]/path[?arg=val[&arg=val]*]
|
||||
|
||||
Special characters in 'path' are escaped using %-hex-hex syntax.
|
||||
|
||||
For example '?' must be escaped if it occurs in a path as '?' is also used to
|
||||
separate the path from the optional list of url arguments.
|
||||
|
||||
Example:
|
||||
nfs://127.0.0.1/my?path/?version=4
|
||||
must be escaped as
|
||||
nfs://127.0.0.1/my%3Fpath/?version=4
|
||||
|
||||
Arguments supported by libnfs are :
|
||||
tcp-syncnt=<int> : Number of SYNs to send during the session establish
|
||||
|
@ -136,6 +146,8 @@ Windows:- tested on Windows 7 64 and Windows XP 32 using Visual Studio 10 (see R
|
|||
- 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'
|
||||
Playstation 2: - Build and install with 'cd ps2ee; make -f Makefile.PS2_EE install'
|
||||
PlayStation 3: - Build and install the library with 'make -f ps3_ppu/Makefile.PS3_PPU install'
|
||||
|
||||
|
||||
LD_PRELOAD
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
Multithreading
|
||||
==============
|
||||
Libnfs supports multithreading using the pthread API on linux/unix and using
|
||||
the native API for Windows.
|
||||
By default libnfs is beuilt without pthread support to avoid the overhead
|
||||
for locking, but pthread support, and thus support for multithreading, can be
|
||||
configured using --enable-pthread
|
||||
|
||||
$ ./configure --prefix=/usr --enable-examples --enable-pthread
|
||||
|
||||
It is not supported to mix the eventdriven ASYNC interface with multithreading
|
||||
thus once multithreading is enabled from the application you can not use
|
||||
the async interface any more and must only use the multithread safe
|
||||
SYNC API.
|
||||
|
||||
The process to use multithreading from your application is:
|
||||
1, nfs_init_context() to create an NFS context. This context defaults to
|
||||
not (yet) be multithreading aware.
|
||||
2, nfs_mount(...) to mount the NFS share.
|
||||
|
||||
IF the share mounted successfully we can now turn on multithreading for all I/O
|
||||
to the share:
|
||||
3, nfs_mt_service_thread_start(nfs)
|
||||
this starts a dedicated thread to manage all socket
|
||||
I/O and queue management and also flags the context
|
||||
to be multithreading ready.
|
||||
If this returns successfully you can now start using
|
||||
this context from separate threads in your
|
||||
application. But remember, only the SYNC API
|
||||
is supported from this point.
|
||||
... use the nfs context from all your threads ...
|
||||
|
||||
Once the application is finished and ready to terminate, first close all other
|
||||
threads, or make sure that they will NOT perform any further I/O to the nfs
|
||||
context. Wait until all in-flight I/O has stopped.
|
||||
|
||||
Then call nfs_mt_service_thread_stop(nfs) to terminate the service thread and
|
||||
disable the multithreading support.
|
||||
|
||||
|
||||
See examples/nfs-pthreads-example.c for an example utility that
|
||||
mounts a share, enables multithreading and then creates a number of worker
|
||||
threads that share the same nfs context.
|
||||
(In the example the threads just runs a busy loop calling nfs_stat64().)
|
||||
|
||||
|
||||
Porting
|
||||
-------
|
||||
The multithreading support is abstracted out into two separate files to make
|
||||
it easier to add other threading APIs instead of pthreads.
|
||||
include/libnfs-multithreading.h and lib/multithreading.c
|
||||
|
||||
Multithreading requires two separate defines to be present.
|
||||
The global one is HAVE_MULTITHREADING which will activate general
|
||||
multithreading support in the library and the second one that enables a specific
|
||||
implementation of threading.
|
||||
HAVE_PTHREAD is defined when you want to use libpthread.
|
||||
For other threading APIs you will need a new define HAVE_OTHER_API
|
||||
to select it.
|
||||
|
||||
include/libnfs-multithreading.h
|
||||
-------------------------------
|
||||
This file consists of two parts.
|
||||
The first part is creating typedefs for a tread, a mutex and a semaphore.
|
||||
When porting to a different threads API, add a new section that adds suitable
|
||||
typedefs for thread/mutex/semaphore.
|
||||
|
||||
The second part is the wrapper API for the libnfs threading abstractions and
|
||||
should not need to be changed.
|
||||
|
||||
lib/multithreading.c
|
||||
--------------------
|
||||
This file contains the actual abstraction used for multithreading.
|
||||
When porting to a different threads API you will need to create replacement
|
||||
functions for :
|
||||
|
||||
nfs_mt_service_thread() : This is the service thread that is responsible
|
||||
for performing all socket I/O.
|
||||
nfs_mt_service_thread_start()
|
||||
nfs_mt_service_thread_stop()
|
||||
: Functions to start/stop the service thread.
|
||||
|
||||
nfs_mt_mutex_init()
|
||||
nfs_mt_mutex_destroy()
|
||||
nfs_mt_mutex_lock()
|
||||
nfs_mt_mutex_unlock() : Wrappers that implement the 4 basic mutex calls.
|
||||
|
||||
nfs_mt_sem_init()
|
||||
nfs_mt_sem_destroy()
|
||||
nfs_mt_sem_post()
|
||||
nfs_mt_sem_wait() : Wrappers that implement the 4 basic semaphore calls.
|
||||
|
||||
nfs_mt_get_tid() : Get an identifier for the current thread.
|
||||
|
||||
|
||||
TODO
|
||||
----
|
||||
* Optimization: have the service thread just read the PDU from the socket and
|
||||
add it to a new queue. Then have a pool of threads to read from this queue and
|
||||
unmarshall the pdu's in concurrently.
|
|
@ -5,11 +5,11 @@
|
|||
# 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}
|
||||
# Library will be built and added to ${CORE_LIBRARIES}
|
||||
function(core_add_library name)
|
||||
set(name core_${name})
|
||||
set(name nfs_${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)
|
||||
add_library(${name} OBJECT ${SOURCES} ${HEADERS})
|
||||
target_include_directories(${name} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
set(CORE_LIBRARIES "${name};${CORE_LIBRARIES}" CACHE INTERNAL "")
|
||||
endfunction()
|
||||
|
|
22
configure.ac
22
configure.ac
|
@ -1,5 +1,5 @@
|
|||
AC_PREREQ(2.50)
|
||||
AC_INIT([libnfs], [4.0.0], [ronniesahlberg@gmail.com])
|
||||
AC_INIT([libnfs], [5.0.1], [ronniesahlberg@gmail.com])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
||||
AC_CANONICAL_HOST
|
||||
|
@ -70,6 +70,26 @@ fi
|
|||
|
||||
AC_SUBST(MAYBE_EXAMPLES)
|
||||
|
||||
#option: examples
|
||||
AC_ARG_ENABLE([pthread],
|
||||
[AC_HELP_STRING([--enable-pthread],
|
||||
[Build with pthread multithreading support])],
|
||||
[ENABLE_PTHREAD=$enableval],
|
||||
[ENABLE_PTHREAD="no"])
|
||||
if test x$ENABLE_PTHREAD = xyes; then
|
||||
# check for lpthread
|
||||
AC_CACHE_CHECK([for pthread support],libnfs_cv_HAVE_PTHREAD,[
|
||||
AC_TRY_COMPILE([
|
||||
#include <pthread.h>],
|
||||
[pthread_t thread1, thread2;],
|
||||
libnfs_cv_HAVE_PTHREAD=yes,libnfs_cv_HAVE_PTHREAD=no)])
|
||||
if test x"$libnfs_cv_HAVE_PTHREAD" = x"yes"; then
|
||||
AC_DEFINE(HAVE_PTHREAD,1,[Whether we have pthread support])
|
||||
AC_DEFINE(HAVE_MULTITHREADING,1,[Whether we have multithreading support])
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_PTHREAD], [test $libnfs_cv_HAVE_PTHREAD = yes])
|
||||
|
||||
AC_MSG_CHECKING(whether SO_BINDTODEVICE is available)
|
||||
AC_TRY_COMPILE([#include <net/if.h>], [
|
||||
int i = SO_BINDTODEVICE;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
find_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(EXTRA_LIBRARIES "")
|
||||
|
||||
set(SOURCES nfsclient-async
|
||||
set(EXAMPLES nfsclient-async
|
||||
nfsclient-raw
|
||||
nfsclient-sync
|
||||
nfsclient-bcast
|
||||
|
@ -15,20 +14,17 @@ set(SOURCES nfsclient-async
|
|||
portmap-client)
|
||||
|
||||
if(HAVE_TALLOC_TEVENT)
|
||||
list(APPEND SOURCES nfs4-cat-talloc)
|
||||
list(APPEND CORE_LIBRARIES ${TALLOC_EVENT_LIBRARY} ${TALLOC_LIBRARY})
|
||||
list(APPEND EXAMPLES nfs4-cat-talloc)
|
||||
list(APPEND EXTRA_LIBRARIES ${TALLOC_EVENT_LIBRARY} ${TALLOC_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(EVENT_LIBARY)
|
||||
list(APPEND SOURCES nfs4-cat
|
||||
list(APPEND EXAMPLES nfs4-cat
|
||||
portmap-server)
|
||||
list(APPEND CORE_LIBRARIES ${EVENT_LIBARY})
|
||||
list(APPEND EXTRA_LIBRARIES ${EVENT_LIBARY})
|
||||
endif()
|
||||
|
||||
foreach(TARGET ${SOURCES})
|
||||
foreach(TARGET ${EXAMPLES})
|
||||
add_executable(${TARGET} ${TARGET}.c)
|
||||
target_link_libraries(${TARGET} ${CORE_LIBRARIES})
|
||||
add_dependencies(${TARGET} nfs)
|
||||
target_link_libraries(${TARGET} nfs ${EXTRA_LIBRARIES})
|
||||
endforeach()
|
||||
|
||||
add_definitions("-D_U_=__attribute__((unused))")
|
||||
|
|
|
@ -4,6 +4,11 @@ if HAVE_TALLOC_TEVENT
|
|||
noinst_PROGRAMS += nfs4-cat-talloc
|
||||
endif
|
||||
|
||||
if HAVE_PTHREAD
|
||||
LIBS += -lpthread
|
||||
noinst_PROGRAMS += nfs-pthreads-example nfs-pthreads-fstat
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(abs_top_srcdir)/include \
|
||||
-I$(abs_top_srcdir)/include/nfsc \
|
||||
|
@ -28,3 +33,5 @@ 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
|
||||
nfs_pthreads_example_LDADD = $(COMMON_LIBS)
|
||||
nfs_pthreads_fstat_LDADD = $(COMMON_LIBS)
|
||||
|
|
|
@ -35,6 +35,7 @@ WSADATA wsaData;
|
|||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/statvfs.h>
|
||||
#ifndef AROS
|
||||
#include <sys/statvfs.h>
|
||||
|
@ -51,13 +52,36 @@ WSADATA wsaData;
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "libnfs.h"
|
||||
#include "libnfs-raw.h"
|
||||
#include "libnfs-raw-mount.h"
|
||||
#include "../include/nfsc/libnfs.h"
|
||||
#include "../include/nfsc/libnfs-raw.h"
|
||||
#include "../mount/libnfs-raw-mount.h"
|
||||
#include "../nfs/libnfs-raw-nfs.h"
|
||||
#include "../nfs4/libnfs-raw-nfs4.h"
|
||||
|
||||
void print_usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: nfs-io [-?|--help|--usage] [stat|creat|trunc|unlink|mkdir|rmdir] <url>\n");
|
||||
fprintf(stderr, "Usage: nfs-io [-?|--help|--usage] [stat|creat|trunc|unlink|mkdir|rmdir|touch|chmod] <url>\n");
|
||||
}
|
||||
|
||||
|
||||
static char *acl3_type(int type)
|
||||
{
|
||||
switch(type) {
|
||||
case NFSACL_TYPE_USER_OBJ: return "USER_OBJ";
|
||||
case NFSACL_TYPE_USER: return "USER";
|
||||
case NFSACL_TYPE_GROUP_OBJ: return "GROUP_OBJ";
|
||||
case NFSACL_TYPE_GROUP: return "GROUP";
|
||||
case NFSACL_TYPE_CLASS_OBJ: return "CLASS_OBJ";
|
||||
case NFSACL_TYPE_CLASS: return "CLASS";
|
||||
case NFSACL_TYPE_DEFAULT: return "DEFAULT";
|
||||
case NFSACL_TYPE_DEFAULT_USER_OBJ: return "DEFAULT_USER_OBJ";
|
||||
case NFSACL_TYPE_DEFAULT_USER: return "DEFAULT_USER";
|
||||
case NFSACL_TYPE_DEFAULT_GROUP_OBJ: return "DEFAULT_GROUP_OBJ";
|
||||
case NFSACL_TYPE_DEFAULT_GROUP: return "DEFAULT_GROUP";
|
||||
case NFSACL_TYPE_DEFAULT_CLASS_OBJ: return "DEFAULT_CLASS_OBJ";
|
||||
case NFSACL_TYPE_DEFAULT_OTHER_OBJ: return "DEFAULT_OTHER_OBJ";
|
||||
}
|
||||
return "Unknown ACE type";
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -66,6 +90,9 @@ int main(int argc, char *argv[])
|
|||
struct nfs_context *nfs = NULL;
|
||||
struct nfsfh *nfsfh = NULL;
|
||||
struct nfs_url *url = NULL;
|
||||
fattr4_acl acl4;
|
||||
fattr3_acl acl3;
|
||||
int i;
|
||||
|
||||
#ifdef WIN32
|
||||
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
|
||||
|
@ -110,6 +137,26 @@ int main(int argc, char *argv[])
|
|||
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], "touch", 5)) {
|
||||
struct timeval times[2];
|
||||
gettimeofday(×[0], NULL);
|
||||
gettimeofday(×[1], NULL);
|
||||
ret = nfs_utimes(nfs, url->file, times);
|
||||
} else if (!strncmp(argv[1], "chmod", 5)) {
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "Invalid arguments for chmod");
|
||||
goto finished;
|
||||
}
|
||||
int mode = strtol(argv[2], NULL, 8);
|
||||
ret = nfs_chmod(nfs, url->file, mode);
|
||||
} else if (!strncmp(argv[1], "chown", 5)) {
|
||||
if (argc < 5) {
|
||||
fprintf(stderr, "Invalid arguments for chown");
|
||||
goto finished;
|
||||
}
|
||||
int uid = strtol(argv[2], NULL, 10);
|
||||
int gid = strtol(argv[3], NULL, 10);
|
||||
ret = nfs_chown(nfs, url->file, uid, gid);
|
||||
} else if (!strncmp(argv[1], "stat", 4)) {
|
||||
struct nfs_stat_64 st;
|
||||
ret = nfs_stat64(nfs, url->file, &st);
|
||||
|
@ -136,24 +183,70 @@ int main(int argc, char *argv[])
|
|||
printf("%c%c%c",
|
||||
"-r"[!!(st.nfs_mode & S_IRUSR)],
|
||||
"-w"[!!(st.nfs_mode & S_IWUSR)],
|
||||
"-x"[!!(st.nfs_mode & S_IXUSR)]
|
||||
"-xSs"[ !!(st.nfs_mode & S_IXUSR) +
|
||||
2*!!(st.nfs_mode & S_ISUID)]
|
||||
);
|
||||
printf("%c%c%c",
|
||||
"-r"[!!(st.nfs_mode & S_IRGRP)],
|
||||
"-w"[!!(st.nfs_mode & S_IWGRP)],
|
||||
"-x"[!!(st.nfs_mode & S_IXGRP)]
|
||||
"-xSs"[ !!(st.nfs_mode & S_IXGRP) +
|
||||
2*!!(st.nfs_mode & S_ISGID)]
|
||||
);
|
||||
printf("%c%c%c",
|
||||
"-r"[!!(st.nfs_mode & S_IROTH)],
|
||||
"-w"[!!(st.nfs_mode & S_IWOTH)],
|
||||
"-x"[!!(st.nfs_mode & S_IXOTH)]
|
||||
"-xTt"[ !!(st.nfs_mode & S_IXOTH) +
|
||||
2*!!(st.nfs_mode & S_ISVTX)]
|
||||
);
|
||||
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(" size: %12" PRId64, st.nfs_size);
|
||||
printf(" mtime: %lu %lu", st.nfs_mtime, st.nfs_mtime_nsec);
|
||||
printf("\n");
|
||||
}
|
||||
} else if (!strncmp(argv[1], "acl", 3)) {
|
||||
ret = nfs_open(nfs, url->file, 0600, &nfsfh);
|
||||
if (ret != 0) {
|
||||
printf("failed to open %s. %s\n", url->file, nfs_get_error(nfs));
|
||||
goto finished;
|
||||
}
|
||||
|
||||
printf("ACL version:%d\n", nfs_get_version(nfs));
|
||||
|
||||
if (nfs_get_version(nfs) == NFS_V3) {
|
||||
printf("Get v3 ACL\n");
|
||||
memset(&acl3, 0, sizeof(fattr3_acl));
|
||||
if (nfs3_getacl(nfs, nfsfh, &acl3) != 0) {
|
||||
printf("nfs3_getacl_async failed\n");
|
||||
}
|
||||
printf("Number of ACEs: %d\n", acl3.ace_count);
|
||||
for (i = 0; i < acl3.ace_count; i++) {
|
||||
printf("%s(%d) ", acl3_type(acl3.ace[i].type), acl3.ace[i].type);
|
||||
printf("Id: %d ", acl3.ace[i].id);
|
||||
printf("Perm: 0x%x: %s%s%s\n", acl3.ace[i].perm,
|
||||
acl3.ace[i].perm & NFSACL_PERM_READ ? "READ ":"",
|
||||
acl3.ace[i].perm & NFSACL_PERM_WRITE ? "WRITE ":"",
|
||||
acl3.ace[i].perm & NFSACL_PERM_EXEC ? "EXEC ":"");
|
||||
}
|
||||
nfs3_acl_free(&acl3);
|
||||
goto finished;
|
||||
}
|
||||
|
||||
/* NFS_V4 */
|
||||
if (nfs4_getacl(nfs, nfsfh, &acl4)) {
|
||||
printf("Failed to read ACLs %s\n", nfs_get_error(nfs));
|
||||
goto finished;
|
||||
}
|
||||
for (i = 0; i < acl4.fattr4_acl_len; i++) {
|
||||
printf("Type:%d Flag:%d Mask:0x%08x Who:%s\n",
|
||||
acl4.fattr4_acl_val[i].type,
|
||||
acl4.fattr4_acl_val[i].flag,
|
||||
acl4.fattr4_acl_val[i].access_mask,
|
||||
acl4.fattr4_acl_val[i].who.utf8string_val);
|
||||
}
|
||||
nfs4_acl_free(&acl4);
|
||||
ret = 0;
|
||||
} else {
|
||||
goto finished;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2021
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <win32/win32_compat.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
WSADATA wsaData;
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include "libnfs.h"
|
||||
#include "libnfs-raw.h"
|
||||
#include "libnfs-raw-nfs.h"
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: nfs-pthread-example <url> <num-threads>\n");
|
||||
fprintf(stderr, "\tExample program using pthreads.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
struct stat_data {
|
||||
struct nfs_context *nfs;
|
||||
int idx;
|
||||
char *path;
|
||||
int is_finished;
|
||||
};
|
||||
|
||||
static void *nfs_stat_thread(void *arg)
|
||||
{
|
||||
struct stat_data *sd = arg;
|
||||
struct nfs_stat_64 st;
|
||||
int i, ret;
|
||||
|
||||
printf("Stat thread %03d\n", sd->idx);
|
||||
i = 0;
|
||||
while(!sd->is_finished) {
|
||||
ret = nfs_stat64(sd->nfs, sd->path, &st);
|
||||
if (ret < 0) {
|
||||
printf("Stat failed: %s\n", nfs_get_error(sd->nfs));
|
||||
exit(10);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
printf("%03d:%d ret:%d st->ino:%d\n", sd->idx, i, ret, (int)st.nfs_ino);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, num_threads;
|
||||
int ret = 0;
|
||||
struct nfs_context *nfs = NULL;
|
||||
struct nfsfh *nfsfh = NULL;
|
||||
struct nfs_fh3 *fh3;
|
||||
struct nfs_url *url = NULL;
|
||||
pthread_t *stat_thread;
|
||||
struct stat_data *sd;
|
||||
|
||||
#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 < 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
num_threads = atoi(argv[2]);
|
||||
printf("Number of threads : %d\n", num_threads);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before we can use multithreading we must initialize and
|
||||
* start the service thread.
|
||||
*/
|
||||
printf("Start the service thread\n");
|
||||
if (nfs_mt_service_thread_start(nfs)) {
|
||||
printf("failed to start service thread\n");
|
||||
exit(10);
|
||||
}
|
||||
printf("Service thread is active. Ready to do I/O\n");
|
||||
|
||||
|
||||
printf("Start %d thread(s) calling stat on %s\n", num_threads, url->file);
|
||||
if ((sd = malloc(sizeof(struct stat_data) * num_threads)) == NULL) {
|
||||
printf("Failed to allocated stat_data\n");
|
||||
exit(10);
|
||||
}
|
||||
if ((stat_thread = malloc(sizeof(pthread_t) * num_threads)) == NULL) {
|
||||
printf("Failed to allocated stat_thread\n");
|
||||
exit(10);
|
||||
}
|
||||
for (i = 0; i < num_threads; i++) {
|
||||
sd[i].nfs = nfs;
|
||||
sd[i].path = url->file;
|
||||
sd[i].is_finished = 0;
|
||||
sd[i].idx = i;
|
||||
if (pthread_create(&stat_thread[i], NULL,
|
||||
&nfs_stat_thread, &sd[i])) {
|
||||
printf("Failed to create stat thread %d\n", i);
|
||||
exit(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sleep(1);
|
||||
/*
|
||||
* Terminate all the worker threads
|
||||
*/
|
||||
printf("Closing all worker threads\n");
|
||||
for (i = 0; i < num_threads; i++) {
|
||||
sd[i].is_finished = 1;
|
||||
}
|
||||
for (i = 0; i < num_threads; i++) {
|
||||
pthread_join(stat_thread[i], NULL);
|
||||
}
|
||||
|
||||
printf("closing service thread\n");
|
||||
nfs_mt_service_thread_stop(nfs);
|
||||
|
||||
finished:
|
||||
if (nfsfh) {
|
||||
nfs_close(nfs, nfsfh);
|
||||
}
|
||||
nfs_umount(nfs);
|
||||
if (url) {
|
||||
nfs_destroy_url(url);
|
||||
}
|
||||
if (nfs) {
|
||||
nfs_destroy_context(nfs);
|
||||
}
|
||||
free(sd);
|
||||
free(stat_thread);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2021
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <win32/win32_compat.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
WSADATA wsaData;
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include "libnfs.h"
|
||||
#include "libnfs-raw.h"
|
||||
#include "libnfs-raw-nfs.h"
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: nfs-pthread-example <url> <num-threads>\n");
|
||||
fprintf(stderr, "\tExample program using pthreads.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
struct stat_data {
|
||||
struct nfs_context *nfs;
|
||||
int idx;
|
||||
char *path;
|
||||
int is_finished;
|
||||
};
|
||||
|
||||
static void *nfs_stat_thread(void *arg)
|
||||
{
|
||||
struct stat_data *sd = arg;
|
||||
struct nfs_stat_64 st;
|
||||
int i, ret;
|
||||
struct nfsfh *nfsfh = NULL;
|
||||
|
||||
printf("Stat thread %03d\n", sd->idx);
|
||||
i = 0;
|
||||
while(!sd->is_finished) {
|
||||
ret = nfs_open(sd->nfs, sd->path, 0600, &nfsfh);
|
||||
if (ret != 0) {
|
||||
printf("failed to open %s. %s\n", sd->path, nfs_get_error(sd->nfs));
|
||||
exit(10);
|
||||
}
|
||||
if (nfsfh == NULL) {
|
||||
printf("nfsfh is NULL after nfs_open()\n");
|
||||
exit(10);
|
||||
}
|
||||
ret = nfs_fstat64(sd->nfs, nfsfh, &st);
|
||||
if (ret < 0) {
|
||||
printf("Stat failed: %s\n", nfs_get_error(sd->nfs));
|
||||
exit(10);
|
||||
}
|
||||
nfs_close(sd->nfs, nfsfh);
|
||||
nfsfh = NULL;
|
||||
i++;
|
||||
}
|
||||
printf("%03d:%d ret:%d st->ino:%d\n", sd->idx, i, ret, (int)st.nfs_ino);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, num_threads;
|
||||
int ret = 0;
|
||||
struct nfs_context *nfs = NULL;
|
||||
struct nfsfh *nfsfh = NULL;
|
||||
struct nfs_fh3 *fh3;
|
||||
struct nfs_url *url = NULL;
|
||||
pthread_t *stat_thread;
|
||||
struct stat_data *sd;
|
||||
|
||||
#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 < 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
num_threads = atoi(argv[2]);
|
||||
printf("Number of threads : %d\n", num_threads);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before we can use multithreading we must initialize and
|
||||
* start the service thread.
|
||||
*/
|
||||
printf("Start the service thread\n");
|
||||
if (nfs_mt_service_thread_start(nfs)) {
|
||||
printf("failed to start service thread\n");
|
||||
exit(10);
|
||||
}
|
||||
printf("Service thread is active. Ready to do I/O\n");
|
||||
|
||||
|
||||
printf("Start %d thread(s) calling stat on %s\n", num_threads, url->file);
|
||||
if ((sd = malloc(sizeof(struct stat_data) * num_threads)) == NULL) {
|
||||
printf("Failed to allocated stat_data\n");
|
||||
exit(10);
|
||||
}
|
||||
if ((stat_thread = malloc(sizeof(pthread_t) * num_threads)) == NULL) {
|
||||
printf("Failed to allocated stat_thread\n");
|
||||
exit(10);
|
||||
}
|
||||
for (i = 0; i < num_threads; i++) {
|
||||
sd[i].nfs = nfs;
|
||||
sd[i].path = url->file;
|
||||
sd[i].is_finished = 0;
|
||||
sd[i].idx = i;
|
||||
if (pthread_create(&stat_thread[i], NULL,
|
||||
&nfs_stat_thread, &sd[i])) {
|
||||
printf("Failed to create stat thread %d\n", i);
|
||||
exit(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sleep(1);
|
||||
/*
|
||||
* Terminate all the worker threads
|
||||
*/
|
||||
printf("Closing all worker threads\n");
|
||||
for (i = 0; i < num_threads; i++) {
|
||||
sd[i].is_finished = 1;
|
||||
}
|
||||
for (i = 0; i < num_threads; i++) {
|
||||
pthread_join(stat_thread[i], NULL);
|
||||
}
|
||||
|
||||
printf("closing service thread\n");
|
||||
nfs_mt_service_thread_stop(nfs);
|
||||
|
||||
finished:
|
||||
if (nfsfh) {
|
||||
nfs_close(nfs, nfsfh);
|
||||
}
|
||||
nfs_umount(nfs);
|
||||
if (url) {
|
||||
nfs_destroy_url(url);
|
||||
}
|
||||
if (nfs) {
|
||||
nfs_destroy_context(nfs);
|
||||
}
|
||||
free(sd);
|
||||
free(stat_thread);
|
||||
return ret;
|
||||
}
|
|
@ -680,7 +680,7 @@ void setclientid_cb(struct rpc_context *rpc, int status, void *data,
|
|||
/*
|
||||
* NULL procedure for the callback protocol.
|
||||
*/
|
||||
static int cb_null_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
||||
static int cb_null_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
rpc_send_reply(rpc, call, NULL, (zdrproc_t)zdr_void, 0);
|
||||
|
||||
|
@ -691,7 +691,7 @@ static int cb_null_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
|||
* 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)
|
||||
static int cb_compound_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
CB_COMPOUND4args *args = call->body.cbody.args;
|
||||
|
||||
|
|
|
@ -682,7 +682,7 @@ void setclientid_cb(struct rpc_context *rpc, int status, void *data,
|
|||
/*
|
||||
* NULL procedure for the callback protocol.
|
||||
*/
|
||||
static int cb_null_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
||||
static int cb_null_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
rpc_send_reply(rpc, call, NULL, (zdrproc_t)zdr_void, 0);
|
||||
|
||||
|
@ -693,7 +693,7 @@ static int cb_null_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
|||
* 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)
|
||||
static int cb_compound_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
CB_COMPOUND4args *args = call->body.cbody.args;
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
#pragma comment(lib, "ws2_32.lib")
|
||||
WSADATA wsaData;
|
||||
#endif
|
||||
#define SERVER "10.1.1.27"
|
||||
#define EXPORT "/shared"
|
||||
#define SERVER "10.10.10.11"
|
||||
#define EXPORT "/data/SNAP-4"
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
|
|
|
@ -36,11 +36,24 @@ WSADATA wsaData;
|
|||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include "libnfs.h"
|
||||
#include "libnfs-raw.h"
|
||||
|
|
|
@ -248,7 +248,7 @@ void map_remove(int prog, int vers, char *netid)
|
|||
* 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)
|
||||
static int pmap2_null_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
rpc_send_reply(rpc, call, NULL, (zdrproc_t)zdr_void, 0);
|
||||
|
||||
|
@ -262,7 +262,7 @@ static int pmap2_null_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
|||
* 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)
|
||||
static int pmap2_getport_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
PMAP2GETPORTargs *args = call->body.cbody.args;
|
||||
struct mapping *tmp;
|
||||
|
@ -290,7 +290,7 @@ static int pmap2_getport_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
|||
* 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)
|
||||
static int pmap2_dump_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
PMAP2DUMPres reply;
|
||||
struct mapping *tmp;
|
||||
|
@ -336,7 +336,7 @@ static int pmap2_dump_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
|||
* 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)
|
||||
static int pmap2_set_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
PMAP2GETPORTargs *args = call->body.cbody.args;
|
||||
char *prot;
|
||||
|
@ -369,7 +369,7 @@ static int pmap2_set_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
|||
* 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)
|
||||
static int pmap2_unset_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
PMAP2GETPORTargs *args = call->body.cbody.args;
|
||||
char *prot;
|
||||
|
@ -424,7 +424,7 @@ struct service_proc pmap2_pt[] = {
|
|||
* 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)
|
||||
static int pmap3_null_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
rpc_send_reply(rpc, call, NULL, (zdrproc_t)zdr_void, 0);
|
||||
|
||||
|
@ -436,7 +436,7 @@ static int pmap3_null_proc(struct rpc_context *rpc, struct rpc_msg *call)
|
|||
* 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)
|
||||
static int pmap3_dump_proc(struct rpc_context *rpc, struct rpc_msg *call, void *opaque)
|
||||
{
|
||||
PMAP3DUMPres reply;
|
||||
struct mapping *tmp;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
Copyright (C) 2021 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _LIBNFS_MULTITHREADING_H_
|
||||
#define _LIBNFS_MULTITHREADING_H_
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
typedef pthread_t libnfs_thread_t;
|
||||
typedef pthread_mutex_t libnfs_mutex_t;
|
||||
typedef sem_t libnfs_sem_t;
|
||||
typedef pid_t nfs_tid_t;
|
||||
#endif /* HAVE_PTHREAD */
|
||||
|
||||
#ifdef WIN32
|
||||
typedef HANDLE libnfs_thread_t;
|
||||
typedef HANDLE libnfs_mutex_t;
|
||||
typedef HANDLE libnfs_sem_t;
|
||||
typedef DWORD nfs_tid_t;
|
||||
#endif
|
||||
|
||||
nfs_tid_t nfs_mt_get_tid(void);
|
||||
int nfs_mt_mutex_init(libnfs_mutex_t *mutex);
|
||||
int nfs_mt_mutex_destroy(libnfs_mutex_t *mutex);
|
||||
int nfs_mt_mutex_lock(libnfs_mutex_t *mutex);
|
||||
int nfs_mt_mutex_unlock(libnfs_mutex_t *mutex);
|
||||
|
||||
int nfs_mt_sem_init(libnfs_sem_t *sem, int value);
|
||||
int nfs_mt_sem_destroy(libnfs_sem_t *sem);
|
||||
int nfs_mt_sem_post(libnfs_sem_t *sem);
|
||||
int nfs_mt_sem_wait(libnfs_sem_t *sem);
|
||||
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_LIBNFS_MULTITHREADING_H_ */
|
|
@ -27,7 +27,7 @@
|
|||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#if !defined(WIN32) && !defined(PS2_EE)
|
||||
#include <sys/socket.h> /* struct sockaddr_storage */
|
||||
#endif
|
||||
|
||||
|
@ -35,6 +35,15 @@
|
|||
#define IFNAMSIZ 255
|
||||
#endif
|
||||
|
||||
#if defined(PS3_PPU) && !defined(IFNAMSIZ)
|
||||
#define IFNAMSIZ 16
|
||||
#endif
|
||||
|
||||
#if defined(PS2_EE) && !defined(IFNAMSIZ)
|
||||
#define IFNAMSIZ 16
|
||||
#endif
|
||||
|
||||
#include "libnfs-multithreading.h"
|
||||
#include "libnfs-zdr.h"
|
||||
#include "../nfs/libnfs-raw-nfs.h"
|
||||
#include "../nfs4/libnfs-raw-nfs4.h"
|
||||
|
@ -50,7 +59,7 @@ extern "C" {
|
|||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SOCKADDR_STORAGE) && !defined(WIN32)
|
||||
#if !defined(HAVE_SOCKADDR_STORAGE) && !defined(WIN32) && !defined(PS2_EE)
|
||||
/*
|
||||
* RFC 2553: protocol-independent placeholder for socket addresses
|
||||
*/
|
||||
|
@ -123,6 +132,9 @@ struct rpc_context {
|
|||
struct sockaddr_storage udp_src;
|
||||
struct rpc_queue waitpdu[HASHES];
|
||||
uint32_t waitpdu_len;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
libnfs_mutex_t rpc_mutex;
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
uint32_t inpos;
|
||||
char rm_buf[4];
|
||||
|
@ -205,12 +217,16 @@ void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)
|
|||
#endif
|
||||
;
|
||||
|
||||
#if defined(PS2_EE)
|
||||
#define RPC_LOG(rpc, level, format, ...) ;
|
||||
#else
|
||||
#define RPC_LOG(rpc, level, format, ...) \
|
||||
do { \
|
||||
if (level <= rpc->debug) { \
|
||||
fprintf(stderr, "libnfs:%d " format "\n", level, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
const char *nfs_get_server(struct nfs_context *nfs);
|
||||
const char *nfs_get_export(struct nfs_context *nfs);
|
||||
|
@ -271,22 +287,19 @@ struct nfs_fh {
|
|||
char *val;
|
||||
};
|
||||
|
||||
struct nfs_context {
|
||||
struct rpc_context *rpc;
|
||||
struct nfs_context_internal {
|
||||
char *server;
|
||||
char *export;
|
||||
char *cwd;
|
||||
struct nfs_fh rootfh;
|
||||
uint64_t readmax;
|
||||
uint64_t writemax;
|
||||
char *cwd;
|
||||
int dircache_enabled;
|
||||
int auto_reconnect;
|
||||
int dircache_enabled;
|
||||
struct nfsdir *dircache;
|
||||
uint16_t mask;
|
||||
|
||||
int auto_traverse_mounts;
|
||||
struct nested_mounts *nested_mounts;
|
||||
|
||||
int version;
|
||||
int nfsport;
|
||||
int mountport;
|
||||
|
@ -296,10 +309,35 @@ struct nfs_context {
|
|||
char *client_name;
|
||||
uint64_t clientid;
|
||||
verifier4 setclientid_confirm;
|
||||
uint32_t seqid;
|
||||
uint32_t open_counter;
|
||||
int has_lock_owner;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
int multithreading_enabled;
|
||||
libnfs_thread_t service_thread;
|
||||
libnfs_mutex_t nfs_mutex;
|
||||
libnfs_mutex_t nfs4_open_mutex;
|
||||
struct nfs_thread_context *thread_ctx;
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
};
|
||||
|
||||
struct nfs_context {
|
||||
struct rpc_context *rpc;
|
||||
struct nfs_context_internal *nfsi;
|
||||
char *error_string;
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
struct nfs_context *master_ctx;
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
};
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
struct nfs_thread_context {
|
||||
struct nfs_thread_context *next;
|
||||
nfs_tid_t tid;
|
||||
struct nfs_context nfs;
|
||||
};
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_attr *attr,
|
||||
struct nfs_cb_data *data);
|
||||
|
||||
|
@ -384,7 +422,9 @@ struct nfsfh {
|
|||
|
||||
/* NFSv4 */
|
||||
struct stateid stateid;
|
||||
uint32_t lock_owner;
|
||||
/* locking */
|
||||
uint32_t open_seqid;
|
||||
uint32_t lock_seqid;
|
||||
struct stateid lock_stateid;
|
||||
};
|
||||
|
@ -560,6 +600,8 @@ int nfs4_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
|||
uint64_t count, const void *buf, nfs_cb cb,
|
||||
void *private_data);
|
||||
|
||||
int rpc_write_to_socket(struct rpc_context *rpc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -114,13 +114,14 @@ EXTERN struct rpc_context *rpc_init_server_context(int s);
|
|||
* !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);
|
||||
typedef int (*service_fn)(struct rpc_context *rpc, struct rpc_msg *call, void *opaque);
|
||||
|
||||
struct service_proc {
|
||||
int proc;
|
||||
service_fn func;
|
||||
zdrproc_t decode_fn;
|
||||
int decode_buf_size;
|
||||
void *opaque;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -2270,6 +2271,28 @@ struct COMPOUND4args;
|
|||
EXTERN int rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
|
||||
struct COMPOUND4args *args,
|
||||
void *private_data);
|
||||
/*
|
||||
* Call NFS4/COMPOUND with extra allocation.
|
||||
|
||||
* 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_async2(struct rpc_context *rpc, rpc_cb cb,
|
||||
struct COMPOUND4args *args,
|
||||
void *private_data,
|
||||
size_t alloc_hint);
|
||||
|
||||
/*
|
||||
* Call <generic>/NULL
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#define CADDR_T_DEFINED
|
||||
typedef char *caddr_t;
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -92,7 +93,9 @@ struct ZDR {
|
|||
typedef struct ZDR ZDR;
|
||||
|
||||
|
||||
#ifdef __MINGW32__
|
||||
typedef uint32_t u_int;
|
||||
#endif
|
||||
typedef uint32_t enum_t;
|
||||
typedef uint32_t bool_t;
|
||||
|
||||
|
@ -100,6 +103,7 @@ typedef uint32_t (*zdrproc_t) (ZDR *, void *,...);
|
|||
|
||||
#define AUTH_NONE 0
|
||||
#define AUTH_NULL 0
|
||||
#define AUTH_SYS 1
|
||||
#define AUTH_UNIX 1
|
||||
|
||||
struct opaque_auth {
|
||||
|
|
|
@ -23,8 +23,12 @@
|
|||
#ifndef _LIBNFS_H_
|
||||
#define _LIBNFS_H_
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#if defined(__ANDROID__) || defined(AROS) \
|
||||
#if defined(__ANDROID__) || defined(AROS) || defined(__PPU__) \
|
||||
|| ( defined(__APPLE__) && defined(__MACH__) )
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
|
@ -38,6 +42,9 @@ extern "C" {
|
|||
#define LIBNFS_FEATURE_READAHEAD
|
||||
#define LIBNFS_FEATURE_PAGECACHE
|
||||
#define LIBNFS_FEATURE_DEBUG
|
||||
#define LIBNFS_FEATURE_UMOUNT
|
||||
#define LIBNFS_FEATURE_MULTITHREADING
|
||||
|
||||
#define NFS_BLKSIZE 4096
|
||||
#define NFS_PAGECACHE_DEFAULT_TTL 5
|
||||
|
||||
|
@ -50,7 +57,7 @@ struct nfs_url {
|
|||
char *file;
|
||||
};
|
||||
|
||||
#if defined(WIN32)
|
||||
#if defined(WIN32) && defined(libnfs_EXPORTS)
|
||||
#define EXTERN __declspec( dllexport )
|
||||
#else
|
||||
#ifndef EXTERN
|
||||
|
@ -244,15 +251,25 @@ EXTERN void nfs_destroy_url(struct nfs_url *url);
|
|||
struct nfsfh;
|
||||
|
||||
/*
|
||||
* Get the maximum supported READ3 size by the server
|
||||
* Get the maximum supported READ size by the server
|
||||
*/
|
||||
EXTERN uint64_t nfs_get_readmax(struct nfs_context *nfs);
|
||||
|
||||
/*
|
||||
* Get the maximum supported WRITE3 size by the server
|
||||
* Get the maximum supported WRITE size by the server
|
||||
*/
|
||||
EXTERN uint64_t nfs_get_writemax(struct nfs_context *nfs);
|
||||
|
||||
/*
|
||||
* Set the maximum supported READ size by the server
|
||||
*/
|
||||
EXTERN void nfs_set_readmax(struct nfs_context *nfs, uint64_t readmax);
|
||||
|
||||
/*
|
||||
* Set the maximum supported WRITE size by the server
|
||||
*/
|
||||
EXTERN void nfs_set_writemax(struct nfs_context *nfs, uint64_t writemax);
|
||||
|
||||
/*
|
||||
* MODIFY CONNECT PARAMETERS
|
||||
*/
|
||||
|
@ -273,6 +290,12 @@ EXTERN void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries);
|
|||
* NFS_V4
|
||||
*/
|
||||
EXTERN int nfs_set_version(struct nfs_context *nfs, int version);
|
||||
/*
|
||||
* Get NFS version of a connected share. Supported versions are
|
||||
* NFS_V3
|
||||
* NFS_V4
|
||||
*/
|
||||
EXTERN int nfs_get_version(struct nfs_context *nfs);
|
||||
|
||||
/*
|
||||
* Invalidate the pagecache
|
||||
|
@ -1902,6 +1925,16 @@ EXTERN int mount_getexports_async(struct rpc_context *rpc, const char *server,
|
|||
*/
|
||||
EXTERN struct exportnode *mount_getexports(const char *server);
|
||||
|
||||
/*
|
||||
* Sync getexports_timeout(<server>, <timeout>)
|
||||
* 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_timeout(const char *server, int timeout);
|
||||
|
||||
EXTERN void mount_free_export_list(struct exportnode *exports);
|
||||
|
||||
|
||||
|
@ -1959,6 +1992,20 @@ EXTERN void nfs4_set_client_name(struct nfs_context *nfs, const char *id);
|
|||
*/
|
||||
EXTERN void nfs4_set_verifier(struct nfs_context *nfs, const char *verifier);
|
||||
|
||||
/*
|
||||
* MULTITHREADING
|
||||
*/
|
||||
/*
|
||||
* This function starts a separate service thread for multithreading support.
|
||||
* When multithreading is enabled the eventdriven async API is no longer
|
||||
* supported and you can only use the synchronous API.
|
||||
*/
|
||||
EXTERN int nfs_mt_service_thread_start(struct nfs_context *nfs);
|
||||
/*
|
||||
* Shutdown multithreading support.
|
||||
*/
|
||||
EXTERN void nfs_mt_service_thread_stop(struct nfs_context *nfs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@ THE SOFTWARE.
|
|||
#include <io.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <stddef.h> // For size_t type
|
||||
|
||||
typedef unsigned long fsblkcnt_t;
|
||||
typedef unsigned long fsfilcnt_t;
|
||||
|
@ -133,7 +134,7 @@ struct pollfd {
|
|||
|
||||
/* Wrapper macros to call misc. functions win32 is missing */
|
||||
#define poll(x, y, z) win32_poll(x, y, z)
|
||||
#define snprintf sprintf_s
|
||||
//#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
|
||||
|
@ -151,4 +152,8 @@ int win32_gettimeofday(struct timeval *tv, struct timezone *tz);
|
|||
|
||||
#define DllExport
|
||||
|
||||
#ifdef __MINGW32__
|
||||
char* strndup(const char *s, size_t n);
|
||||
#endif
|
||||
|
||||
#endif//win32_COMPAT_H_
|
||||
|
|
|
@ -2,21 +2,26 @@ set(SOURCES init.c
|
|||
libnfs.c
|
||||
libnfs-sync.c
|
||||
libnfs-zdr.c
|
||||
multithreading.c
|
||||
nfs_v3.c
|
||||
nfs_v4.c
|
||||
pdu.c
|
||||
socket.c)
|
||||
socket.c
|
||||
)
|
||||
|
||||
# deal with version info in "dll" case
|
||||
if(WIN32 AND BUILD_SHARED_LIBS)
|
||||
configure_file(../win32/version.rc.template version.rc @ONLY)
|
||||
list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
add_library(nfs ${SOURCES})
|
||||
target_link_libraries(nfs PUBLIC ${core_DEPENDS})
|
||||
target_include_directories(nfs PUBLIC ../include)
|
||||
target_link_libraries(nfs PRIVATE ${CORE_LIBRARIES} PUBLIC ${SYSTEM_LIBRARIES})
|
||||
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
|
||||
install(TARGETS nfs EXPORT libnfs
|
||||
RUNTIME DESTINATION bin
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib)
|
||||
|
|
|
@ -19,13 +19,14 @@ libnfs_la_SOURCES = \
|
|||
libnfs.c \
|
||||
libnfs-sync.c \
|
||||
libnfs-zdr.c \
|
||||
multithreading.c \
|
||||
nfs_v3.c \
|
||||
nfs_v4.c \
|
||||
pdu.c \
|
||||
socket.c \
|
||||
../win32/win32_compat.c
|
||||
|
||||
SOCURRENT=13
|
||||
SOCURRENT=14
|
||||
SOREVISION=0
|
||||
SOAGE=0
|
||||
libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE)
|
||||
|
|
59
lib/init.c
59
lib/init.c
|
@ -1,3 +1,4 @@
|
|||
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
|
@ -22,6 +23,14 @@
|
|||
#include "aros_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS3_PPU
|
||||
#include "ps3_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#endif
|
||||
|
@ -76,6 +85,10 @@ struct rpc_context *rpc_init_context(void)
|
|||
|
||||
rpc->magic = RPC_CONTEXT_MAGIC;
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_init(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
rpc->auth = authunix_create_default();
|
||||
if (rpc->auth == NULL) {
|
||||
free(rpc);
|
||||
|
@ -83,21 +96,27 @@ struct rpc_context *rpc_init_context(void)
|
|||
}
|
||||
// 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);
|
||||
rpc->xid = salt + (uint32_t)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)
|
||||
#if defined(WIN32) || defined(ANDROID) || defined(PS3_PPU)
|
||||
rpc->uid = 65534;
|
||||
rpc->gid = 65534;
|
||||
#else
|
||||
rpc->uid = getuid();
|
||||
rpc->gid = getgid();
|
||||
#endif
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
rpc_reset_queue(&rpc->outqueue);
|
||||
for (i = 0; i < HASHES; i++)
|
||||
rpc_reset_queue(&rpc->waitpdu[i]);
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
/* Default is no timeout */
|
||||
rpc->timeout = -1;
|
||||
|
@ -123,6 +142,9 @@ struct rpc_context *rpc_init_server_context(int s)
|
|||
rpc->is_udp = rpc_is_udp_socket(rpc);
|
||||
rpc_reset_queue(&rpc->outqueue);
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_init(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
return rpc;
|
||||
}
|
||||
|
||||
|
@ -241,10 +263,12 @@ void rpc_set_gid(struct rpc_context *rpc, int 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);
|
||||
char *old_error_string;
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
old_error_string = rpc->error_string;
|
||||
va_start(ap, error_string);
|
||||
rpc->error_string = malloc(1024);
|
||||
vsnprintf(rpc->error_string, 1024, error_string, ap);
|
||||
|
@ -255,13 +279,16 @@ void rpc_set_error(struct rpc_context *rpc, const char *error_string, ...)
|
|||
if (old_error_string != NULL) {
|
||||
free(old_error_string);
|
||||
}
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
}
|
||||
|
||||
char *rpc_get_error(struct rpc_context *rpc)
|
||||
{
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
return rpc->error_string;
|
||||
return rpc->error_string ? rpc->error_string : "";
|
||||
}
|
||||
|
||||
static void rpc_purge_all_pdus(struct rpc_context *rpc, int status, const char *error)
|
||||
|
@ -279,6 +306,9 @@ static void rpc_purge_all_pdus(struct rpc_context *rpc, int status, const char *
|
|||
* pdus when called.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
outqueue = rpc->outqueue;
|
||||
|
||||
rpc_reset_queue(&rpc->outqueue);
|
||||
|
@ -288,11 +318,21 @@ static void rpc_purge_all_pdus(struct rpc_context *rpc, int status, const char *
|
|||
pdu->cb(rpc, status, (void *) error, pdu->private_data);
|
||||
rpc_free_pdu(rpc, pdu);
|
||||
}
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
for (i = 0; i < HASHES; i++) {
|
||||
struct rpc_queue waitqueue = rpc->waitpdu[i];
|
||||
struct rpc_queue waitqueue;
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
waitqueue = rpc->waitpdu[i];
|
||||
rpc_reset_queue(&rpc->waitpdu[i]);
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
while((pdu = waitqueue.head) != NULL) {
|
||||
waitqueue.head = pdu->next;
|
||||
pdu->next = NULL;
|
||||
|
@ -302,8 +342,6 @@ static void rpc_purge_all_pdus(struct rpc_context *rpc, int status, const char *
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -380,6 +418,9 @@ void rpc_destroy_context(struct rpc_context *rpc)
|
|||
rpc->inbuf = NULL;
|
||||
|
||||
rpc->magic = 0;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_destroy(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
free(rpc);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,6 +17,8 @@ nfs_close_async
|
|||
nfs_closedir
|
||||
nfs_creat
|
||||
nfs_creat_async
|
||||
nfs_create
|
||||
nfs_create_async
|
||||
nfs_destroy_context
|
||||
nfs_fchmod
|
||||
nfs_fchmod_async
|
||||
|
@ -26,6 +28,8 @@ nfs_fcntl
|
|||
nfs_fcntl_async
|
||||
nfs_fstat
|
||||
nfs_fstat_async
|
||||
nfs_fstat64
|
||||
nfs_fstat64_async
|
||||
nfs_fsync
|
||||
nfs_fsync_async
|
||||
nfs_ftruncate
|
||||
|
@ -35,6 +39,7 @@ nfs_get_fd
|
|||
nfs_get_readmax
|
||||
nfs_get_writemax
|
||||
nfs_getcwd
|
||||
nfs_get_version
|
||||
nfs_get_timeout
|
||||
nfs_init_context
|
||||
nfs_link
|
||||
|
@ -51,6 +56,8 @@ nfs_mknod
|
|||
nfs_mknod_async
|
||||
nfs_mount
|
||||
nfs_mount_async
|
||||
nfs_mt_service_thread_start
|
||||
nfs_mt_service_thread_stop
|
||||
nfs_open
|
||||
nfs_open_async
|
||||
nfs_open2
|
||||
|
@ -85,10 +92,12 @@ nfs_set_gid
|
|||
nfs_set_pagecache
|
||||
nfs_set_pagecache_ttl
|
||||
nfs_set_readahead
|
||||
nfs_set_readmax
|
||||
nfs_set_tcp_syncnt
|
||||
nfs_set_timeout
|
||||
nfs_set_uid
|
||||
nfs_set_version
|
||||
nfs_set_writemax
|
||||
nfs_stat
|
||||
nfs_stat_async
|
||||
nfs_stat64
|
||||
|
@ -116,8 +125,13 @@ nfsstat3_to_errno
|
|||
nfsstat3_to_str
|
||||
nfsstat4_to_errno
|
||||
nfsstat4_to_str
|
||||
nfs3_getacl
|
||||
nfs3_getacl_async
|
||||
nfs4_set_client_name
|
||||
nfs4_set_verifier
|
||||
nfs4_acl_free
|
||||
nfs4_getacl
|
||||
nfs4_getacl_async
|
||||
win32_poll
|
||||
rpc_connect_async
|
||||
rpc_connect_port_async
|
||||
|
|
|
@ -33,6 +33,14 @@
|
|||
#include "aros_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS3_PPU
|
||||
#include "ps3_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
@ -185,11 +193,7 @@ bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize
|
|||
}
|
||||
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;
|
||||
|
@ -289,16 +293,12 @@ bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize)
|
|||
* 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.
|
||||
|
@ -317,17 +317,23 @@ bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize)
|
|||
bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc)
|
||||
{
|
||||
int i;
|
||||
uint32_t s;
|
||||
|
||||
if (!libnfs_zdr_u_int(zdrs, size)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (*size > UINT32_MAX/elsize) {
|
||||
return FALSE;
|
||||
}
|
||||
s = *size * elsize;
|
||||
|
||||
if (zdrs->x_op == ZDR_DECODE) {
|
||||
*arrp = zdr_malloc(zdrs, *size * elsize);
|
||||
*arrp = zdr_malloc(zdrs, s);
|
||||
if (*arrp == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
memset(*arrp, 0, *size * elsize);
|
||||
memset(*arrp, 0, s);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)*size; i++) {
|
||||
|
@ -589,7 +595,7 @@ struct AUTH *libnfs_authunix_create(const char *host, uint32_t uid, uint32_t gid
|
|||
|
||||
struct AUTH *libnfs_authunix_create_default(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
#if defined(WIN32) || defined(PS3_PPU)
|
||||
return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL);
|
||||
#else
|
||||
return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL);
|
||||
|
|
401
lib/libnfs.c
401
lib/libnfs.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,282 @@
|
|||
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef AROS
|
||||
#include "aros_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS3_PPU
|
||||
#include "ps3_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#endif
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "libnfs.h"
|
||||
#include "libnfs-raw.h"
|
||||
#include "libnfs-private.h"
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
nfs_tid_t nfs_mt_get_tid(void)
|
||||
{
|
||||
#ifdef SYS_gettid
|
||||
pid_t tid = syscall(SYS_gettid);
|
||||
return tid;
|
||||
#else
|
||||
#error "SYS_gettid unavailable on this system"
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *nfs_mt_service_thread(void *arg)
|
||||
{
|
||||
struct nfs_context *nfs = (struct nfs_context *)arg;
|
||||
struct pollfd pfd;
|
||||
int revents;
|
||||
int ret;
|
||||
|
||||
nfs->nfsi->multithreading_enabled = 1;
|
||||
|
||||
while (nfs->nfsi->multithreading_enabled) {
|
||||
pfd.fd = nfs_get_fd(nfs);
|
||||
pfd.events = nfs_which_events(nfs);
|
||||
pfd.revents = 0;
|
||||
|
||||
ret = poll(&pfd, 1, 0);
|
||||
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");
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nfs_mt_service_thread_start(struct nfs_context *nfs)
|
||||
{
|
||||
if (pthread_create(&nfs->nfsi->service_thread, NULL,
|
||||
&nfs_mt_service_thread, nfs)) {
|
||||
nfs_set_error(nfs, "Failed to start service thread");
|
||||
return -1;
|
||||
}
|
||||
while (nfs->nfsi->multithreading_enabled == 0) {
|
||||
struct timespec ts = {0, 1000000};
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nfs_mt_service_thread_stop(struct nfs_context *nfs)
|
||||
{
|
||||
nfs->nfsi->multithreading_enabled = 0;
|
||||
pthread_join(nfs->nfsi->service_thread, NULL);
|
||||
}
|
||||
|
||||
int nfs_mt_mutex_init(libnfs_mutex_t *mutex)
|
||||
{
|
||||
pthread_mutex_init(mutex, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_mutex_destroy(libnfs_mutex_t *mutex)
|
||||
{
|
||||
pthread_mutex_destroy(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_mutex_lock(libnfs_mutex_t *mutex)
|
||||
{
|
||||
return pthread_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
int nfs_mt_mutex_unlock(libnfs_mutex_t *mutex)
|
||||
{
|
||||
return pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
int nfs_mt_sem_init(libnfs_sem_t *sem, int value)
|
||||
{
|
||||
return sem_init(sem, 0, value);
|
||||
}
|
||||
|
||||
int nfs_mt_sem_destroy(libnfs_sem_t *sem)
|
||||
{
|
||||
return sem_destroy(sem);
|
||||
}
|
||||
|
||||
int nfs_mt_sem_post(libnfs_sem_t *sem)
|
||||
{
|
||||
return sem_post(sem);
|
||||
}
|
||||
|
||||
int nfs_mt_sem_wait(libnfs_sem_t *sem)
|
||||
{
|
||||
return sem_wait(sem);
|
||||
}
|
||||
|
||||
#elif WIN32
|
||||
nfs_tid_t nfs_mt_get_tid(void)
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
static void* nfs_mt_service_thread(void* arg)
|
||||
{
|
||||
struct nfs_context* nfs = (struct nfs_context*)arg;
|
||||
struct pollfd pfd;
|
||||
int revents;
|
||||
int ret;
|
||||
|
||||
nfs->nfsi->multithreading_enabled = 1;
|
||||
|
||||
while (nfs->nfsi->multithreading_enabled) {
|
||||
pfd.fd = nfs_get_fd(nfs);
|
||||
pfd.events = nfs_which_events(nfs);
|
||||
pfd.revents = 0;
|
||||
|
||||
ret = poll(&pfd, 1, 0);
|
||||
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");
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DWORD WINAPI service_thread_init(LPVOID lpParam)
|
||||
{
|
||||
HANDLE hStdout;
|
||||
struct nfs_context* nfs;
|
||||
|
||||
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hStdout == INVALID_HANDLE_VALUE) {
|
||||
return 1;
|
||||
}
|
||||
nfs = (struct nfs_context *)lpParam;
|
||||
printf("SERVICE THREAD\n");
|
||||
nfs_mt_service_thread(nfs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_service_thread_start(struct nfs_context* nfs)
|
||||
{
|
||||
nfs->nfsi->service_thread = CreateThread(NULL, 1024*1024, service_thread_init, nfs, 0, NULL);
|
||||
if (nfs->nfsi->service_thread == NULL) {
|
||||
nfs_set_error(nfs, "Failed to start service thread");
|
||||
return -1;
|
||||
}
|
||||
while (nfs->nfsi->multithreading_enabled == 0) {
|
||||
Sleep(100);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nfs_mt_service_thread_stop(struct nfs_context* nfs)
|
||||
{
|
||||
nfs->nfsi->multithreading_enabled = 0;
|
||||
while (WaitForSingleObject(nfs->nfsi->service_thread, INFINITE) != WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
int nfs_mt_mutex_init(libnfs_mutex_t* mutex)
|
||||
{
|
||||
*mutex = CreateMutex(NULL, 0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_mutex_destroy(libnfs_mutex_t* mutex)
|
||||
{
|
||||
CloseHandle(*mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_mutex_lock(libnfs_mutex_t* mutex)
|
||||
{
|
||||
while (WaitForSingleObject(*mutex, INFINITE) != WAIT_OBJECT_0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_mutex_unlock(libnfs_mutex_t* mutex)
|
||||
{
|
||||
ReleaseMutex(*mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_sem_init(libnfs_sem_t* sem, int value)
|
||||
{
|
||||
*sem = CreateSemaphoreA(NULL, 0, 16, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_sem_destroy(libnfs_sem_t* sem)
|
||||
{
|
||||
CloseHandle(*sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_sem_post(libnfs_sem_t* sem)
|
||||
{
|
||||
ReleaseSemaphore(*sem, 1, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_mt_sem_wait(libnfs_sem_t* sem)
|
||||
{
|
||||
while (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
249
lib/nfs_v3.c
249
lib/nfs_v3.c
|
@ -30,6 +30,14 @@
|
|||
#include "aros_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS3_PPU
|
||||
#include "ps3_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#endif
|
||||
|
@ -184,8 +192,8 @@ nfs3_lookup_path_2_cb(struct rpc_context *rpc, int status, void *command_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 (strstr(path, nfs_get_export(nfs)) == path) {
|
||||
char *ptr = path + strlen(nfs_get_export(nfs));
|
||||
if (*ptr == '/') {
|
||||
newpath = strdup(ptr);
|
||||
} else if (*ptr == '\0') {
|
||||
|
@ -240,7 +248,7 @@ nfs3_lookup_path_2_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
data->path = data->saved_path;
|
||||
nfs3_lookup_path_async_internal(nfs, NULL, data, &nfs->rootfh);
|
||||
nfs3_lookup_path_async_internal(nfs, NULL, data, &nfs->nfsi->rootfh);
|
||||
return;
|
||||
|
||||
nomem:
|
||||
|
@ -451,7 +459,7 @@ nfs3_lookup_path_getattr_cb(struct rpc_context *rpc, int status,
|
|||
/* 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);
|
||||
nfs3_lookup_path_async_internal(nfs, &attr, data, &nfs->nfsi->rootfh);
|
||||
}
|
||||
|
||||
/* This function will free continue_data on error */
|
||||
|
@ -470,7 +478,7 @@ nfs3_lookuppath_async(struct nfs_context *nfs, const char *path, int no_follow,
|
|||
path = ".";
|
||||
}
|
||||
|
||||
data = malloc(sizeof(struct nfs_cb_data));
|
||||
data = calloc(1, sizeof(struct nfs_cb_data));
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory: failed to allocate "
|
||||
"nfs_cb_data structure");
|
||||
|
@ -479,7 +487,6 @@ nfs3_lookuppath_async(struct nfs_context *nfs, const char *path, int no_follow,
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(struct nfs_cb_data));
|
||||
data->nfs = nfs;
|
||||
data->cb = cb;
|
||||
data->continue_cb = continue_cb;
|
||||
|
@ -491,14 +498,14 @@ nfs3_lookuppath_async(struct nfs_context *nfs, const char *path, int no_follow,
|
|||
if (path[0] == '/') {
|
||||
data->saved_path = strdup(path);
|
||||
} else {
|
||||
data->saved_path = malloc(strlen(path) + strlen(nfs->cwd) + 2);
|
||||
data->saved_path = malloc(strlen(path) + strlen(nfs->nfsi->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);
|
||||
sprintf(data->saved_path, "%s/%s", nfs->nfsi->cwd, path);
|
||||
}
|
||||
|
||||
if (data->saved_path == NULL) {
|
||||
|
@ -513,7 +520,7 @@ nfs3_lookuppath_async(struct nfs_context *nfs, const char *path, int no_follow,
|
|||
}
|
||||
|
||||
data->path = data->saved_path;
|
||||
fh = &nfs->rootfh;
|
||||
fh = &nfs->nfsi->rootfh;
|
||||
|
||||
if (data->path[0]) {
|
||||
struct nested_mounts *mnt;
|
||||
|
@ -524,7 +531,7 @@ nfs3_lookuppath_async(struct nfs_context *nfs, const char *path, int no_follow,
|
|||
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) {
|
||||
for (mnt = nfs->nfsi->nested_mounts; mnt; mnt = mnt->next) {
|
||||
if (strlen(mnt->path) < max_match_len)
|
||||
continue;
|
||||
if (strncmp(mnt->path, data->saved_path,
|
||||
|
@ -613,7 +620,7 @@ nfs3_mount_7_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!nfs->nested_mounts)
|
||||
if (!nfs->nfsi->nested_mounts)
|
||||
goto finished;
|
||||
|
||||
/* nested mount traversals are best-effort only, so any
|
||||
|
@ -626,7 +633,7 @@ nfs3_mount_7_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
memset(ma, 0, sizeof(struct mount_attr_cb));
|
||||
ma->data = data;
|
||||
|
||||
for(mnt = nfs->nested_mounts; mnt; mnt = mnt->next) {
|
||||
for(mnt = nfs->nfsi->nested_mounts; mnt; mnt = mnt->next) {
|
||||
struct mount_attr_item_cb *ma_item;
|
||||
struct GETATTR3args args;
|
||||
|
||||
|
@ -678,7 +685,7 @@ nfs3_mount_6_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
|
||||
if (res->status != NFS3_OK) {
|
||||
nfs_set_error(nfs, "NFS: FSINFO of %s failed with %s(%d)",
|
||||
nfs->export, nfsstat3_to_str(res->status),
|
||||
nfs_get_export(nfs), 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);
|
||||
|
@ -686,35 +693,35 @@ nfs3_mount_6_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
return;
|
||||
}
|
||||
|
||||
nfs->readmax = res->FSINFO3res_u.resok.rtmax;
|
||||
nfs->writemax = res->FSINFO3res_u.resok.wtmax;
|
||||
nfs->nfsi->readmax = res->FSINFO3res_u.resok.rtmax;
|
||||
nfs->nfsi->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) {
|
||||
if (nfs->nfsi->readmax > NFS_MAX_XFER_SIZE)
|
||||
nfs->nfsi->readmax = NFS_MAX_XFER_SIZE;
|
||||
else if (nfs->nfsi->readmax < NFSMAXDATA2) {
|
||||
nfs_set_error(nfs, "server max rsize of %" PRIu64,
|
||||
nfs->readmax);
|
||||
nfs->nfsi->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) {
|
||||
if (nfs->nfsi->writemax > NFS_MAX_XFER_SIZE)
|
||||
nfs->nfsi->writemax = NFS_MAX_XFER_SIZE;
|
||||
else if (nfs->nfsi->writemax < NFSMAXDATA2) {
|
||||
nfs_set_error(nfs, "server max wsize of %" PRIu64,
|
||||
nfs->writemax);
|
||||
nfs->nfsi->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;
|
||||
args.object.data.data_len = nfs->nfsi->rootfh.len;
|
||||
args.object.data.data_val = nfs->nfsi->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));
|
||||
|
@ -742,10 +749,10 @@ nfs3_mount_5_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
/* 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);
|
||||
rpc_set_autoreconnect(rpc, nfs->nfsi->auto_reconnect);
|
||||
|
||||
args.fsroot.data.data_len = nfs->rootfh.len;
|
||||
args.fsroot.data.data_val = nfs->rootfh.val;
|
||||
args.fsroot.data.data_len = nfs->nfsi->rootfh.len;
|
||||
args.fsroot.data.data_val = nfs->nfsi->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);
|
||||
|
@ -829,7 +836,7 @@ nfs3_mount_4_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
mnt->path = md_item_cb->path;
|
||||
md_item_cb->path = NULL;
|
||||
|
||||
LIBNFS_LIST_ADD(&nfs->nested_mounts, mnt);
|
||||
LIBNFS_LIST_ADD(&nfs->nfsi->nested_mounts, mnt);
|
||||
|
||||
finished:
|
||||
free(md_item_cb->path);
|
||||
|
@ -854,8 +861,9 @@ finished:
|
|||
return;
|
||||
}
|
||||
|
||||
if (nfs->nfsport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport,
|
||||
if (nfs->nfsi->nfsport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs_get_server(nfs),
|
||||
nfs->nfsi->nfsport,
|
||||
NFS_PROGRAM, NFS_V3,
|
||||
nfs3_mount_5_cb, data) != 0) {
|
||||
nfs_set_error(nfs, "%s: %s", __FUNCTION__,
|
||||
|
@ -869,7 +877,8 @@ finished:
|
|||
return;
|
||||
}
|
||||
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM,
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs_get_server(nfs),
|
||||
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);
|
||||
|
@ -900,7 +909,7 @@ nfs3_mount_3_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
/* Iterate over all exports and check if there are any mounts nested
|
||||
* below the current mount.
|
||||
*/
|
||||
len = strlen(nfs->export);
|
||||
len = strlen(nfs_get_export(nfs));
|
||||
if (!len) {
|
||||
data->cb(-EFAULT, nfs, "Export is empty", data->private_data);
|
||||
free_nfs_cb_data(data);
|
||||
|
@ -910,7 +919,7 @@ nfs3_mount_3_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
while (res) {
|
||||
struct mount_discovery_item_cb *md_item_cb;
|
||||
|
||||
if (strncmp(nfs->export, res->ex_dir, len)) {
|
||||
if (strncmp(nfs_get_export(nfs), res->ex_dir, len)) {
|
||||
res = res->ex_next;
|
||||
continue;
|
||||
}
|
||||
|
@ -931,7 +940,7 @@ nfs3_mount_3_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
memset(md_item_cb, 0, sizeof(*md_item_cb));
|
||||
|
||||
md_item_cb->path = strdup(res->ex_dir + len
|
||||
- (nfs->export[len -1] == '/'));
|
||||
- (nfs_get_export(nfs)[len -1] == '/'));
|
||||
if (md_item_cb->path == NULL) {
|
||||
free(md_item_cb);
|
||||
continue;
|
||||
|
@ -976,8 +985,9 @@ nfs3_mount_3_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
*/
|
||||
rpc_disconnect(rpc, "normal disconnect");
|
||||
|
||||
if (nfs->nfsport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport,
|
||||
if (nfs->nfsi->nfsport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs_get_server(nfs),
|
||||
nfs->nfsi->nfsport,
|
||||
NFS_PROGRAM, NFS_V3,
|
||||
nfs3_mount_5_cb, data) != 0) {
|
||||
nfs_set_error(nfs, "%s: %s", __FUNCTION__,
|
||||
|
@ -990,7 +1000,8 @@ nfs3_mount_3_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
return;
|
||||
}
|
||||
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM,
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs_get_server(nfs),
|
||||
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);
|
||||
|
@ -1028,19 +1039,19 @@ nfs3_mount_2_cb(struct rpc_context *rpc, int status, void *command_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->nfsi->rootfh.len = res->mountres3_u.mountinfo.fhandle.fhandle3_len;
|
||||
nfs->nfsi->rootfh.val = malloc(nfs->nfsi->rootfh.len);
|
||||
if (nfs->nfsi->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,
|
||||
memcpy(nfs->nfsi->rootfh.val,
|
||||
res->mountres3_u.mountinfo.fhandle.fhandle3_val,
|
||||
nfs->rootfh.len);
|
||||
nfs->nfsi->rootfh.len);
|
||||
|
||||
if (nfs->auto_traverse_mounts) {
|
||||
if (nfs->nfsi->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));
|
||||
|
@ -1053,8 +1064,9 @@ nfs3_mount_2_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
rpc_disconnect(rpc, "normal disconnect");
|
||||
if (nfs->nfsport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport,
|
||||
if (nfs->nfsi->nfsport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs_get_server(nfs),
|
||||
nfs->nfsi->nfsport,
|
||||
NFS_PROGRAM, NFS_V3,
|
||||
nfs3_mount_5_cb, data) != 0) {
|
||||
nfs_set_error(nfs, "%s: %s", __FUNCTION__,
|
||||
|
@ -1067,7 +1079,8 @@ nfs3_mount_2_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
return;
|
||||
}
|
||||
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM,
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs_get_server(nfs),
|
||||
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);
|
||||
|
@ -1091,7 +1104,7 @@ nfs3_mount_1_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
return;
|
||||
}
|
||||
|
||||
if (rpc_mount3_mnt_async(rpc, nfs3_mount_2_cb, nfs->export,
|
||||
if (rpc_mount3_mnt_async(rpc, nfs3_mount_2_cb, nfs->nfsi->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);
|
||||
|
@ -1116,20 +1129,20 @@ nfs3_mount_async(struct nfs_context *nfs, const char *server,
|
|||
memset(data, 0, sizeof(struct nfs_cb_data));
|
||||
new_server = strdup(server);
|
||||
new_export = strdup(export);
|
||||
if (nfs->server != NULL) {
|
||||
free(nfs->server);
|
||||
if (nfs->nfsi->server != NULL) {
|
||||
free(nfs->nfsi->server);
|
||||
}
|
||||
nfs->server = new_server;
|
||||
if (nfs->export != NULL) {
|
||||
free(nfs->export);
|
||||
nfs->nfsi->server = new_server;
|
||||
if (nfs->nfsi->export != NULL) {
|
||||
free(nfs->nfsi->export);
|
||||
}
|
||||
nfs->export = new_export;
|
||||
nfs->nfsi->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,
|
||||
if (nfs->nfsi->mountport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, server, nfs->nfsi->mountport,
|
||||
MOUNT_PROGRAM, MOUNT_V3,
|
||||
nfs3_mount_1_cb, data) != 0) {
|
||||
nfs_set_error(nfs, "Failed to start connection. %s",
|
||||
|
@ -1185,7 +1198,7 @@ nfs3_umount_1_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
return;
|
||||
}
|
||||
|
||||
if (rpc_mount3_umnt_async(rpc, nfs3_umount_2_cb, nfs->export,
|
||||
if (rpc_mount3_umnt_async(rpc, nfs3_umount_2_cb, nfs->nfsi->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);
|
||||
|
@ -1213,9 +1226,9 @@ nfs3_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data)
|
|||
|
||||
rpc_disconnect(nfs->rpc, "umount");
|
||||
|
||||
if (nfs->mountport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs->server,
|
||||
nfs->mountport,
|
||||
if (nfs->nfsi->mountport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs_get_server(nfs),
|
||||
nfs->nfsi->mountport,
|
||||
MOUNT_PROGRAM, MOUNT_V3,
|
||||
nfs3_umount_1_cb, data) != 0) {
|
||||
nfs_set_error(nfs, "Failed to start connection. %s",
|
||||
|
@ -1226,7 +1239,7 @@ nfs3_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs->server,
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs_get_server(nfs),
|
||||
MOUNT_PROGRAM, MOUNT_V3,
|
||||
nfs3_umount_1_cb, data) != 0) {
|
||||
nfs_set_error(nfs, "Failed to start connection. %s",
|
||||
|
@ -2920,7 +2933,7 @@ nfs3_opendir_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
splen = 0;
|
||||
|
||||
/* No name attributes. Is it a nested mount then?*/
|
||||
for(mnt = nfs->nested_mounts; mnt; mnt = mnt->next) {
|
||||
for(mnt = nfs->nfsi->nested_mounts; mnt; mnt = mnt->next) {
|
||||
if (strncmp(data->saved_path, mnt->path, splen))
|
||||
continue;
|
||||
if (mnt->path[splen] != '/')
|
||||
|
@ -3987,6 +4000,98 @@ nfs3_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nfs3_getacl_cb(struct rpc_context *rpc, int status, void *command_data,
|
||||
void *private_data)
|
||||
{
|
||||
GETACL3res *res;
|
||||
GETACL3resok *resok;
|
||||
struct nfs_cb_data *data = private_data;
|
||||
struct nfs_context *nfs = data->nfs;
|
||||
fattr3_acl acl;
|
||||
int i;
|
||||
|
||||
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: GETACL 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(&acl, 0, sizeof(acl));
|
||||
resok = &res->GETACL3res_u.resok;
|
||||
acl.ace_count = resok->ace_count;
|
||||
if (acl.ace_count) {
|
||||
acl.ace = calloc(acl.ace_count, sizeof(struct nfsacl_ace));
|
||||
if (acl.ace == NULL) {
|
||||
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
|
||||
free_nfs_cb_data(data);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < acl.ace_count; i++) {
|
||||
acl.ace[i] = resok->ace.ace_val[i];
|
||||
}
|
||||
}
|
||||
acl.default_ace_count = resok->default_ace_count;
|
||||
if (acl.default_ace_count) {
|
||||
acl.default_ace = calloc(acl.default_ace_count, sizeof(struct nfsacl_ace));
|
||||
if (acl.default_ace == NULL) {
|
||||
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
|
||||
free_nfs_cb_data(data);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < acl.default_ace_count; i++) {
|
||||
acl.default_ace[i] = resok->default_ace.default_ace_val[i];
|
||||
}
|
||||
}
|
||||
data->cb(0, nfs, &acl, data->private_data);
|
||||
free_nfs_cb_data(data);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs3_getacl_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
|
||||
void *private_data)
|
||||
{
|
||||
struct nfs_cb_data *data;
|
||||
GETACL3args args;
|
||||
|
||||
printf("getacl async\n");
|
||||
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(GETACL3args));
|
||||
args.dir.data.data_len = nfsfh->fh.len;
|
||||
args.dir.data.data_val = nfsfh->fh.val;
|
||||
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(nfs->rpc, nfs3_getacl_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_stat_1_cb(struct rpc_context *rpc, int status, void *command_data,
|
||||
void *private_data)
|
||||
|
@ -4637,6 +4742,13 @@ nfs3_pread_mcb(struct rpc_context *rpc, int status, void *command_data,
|
|||
data->buffer = res->READ3res_u.resok.data.data_val;
|
||||
data->not_my_buffer = 1;
|
||||
} else if (count <= mdata->count) {
|
||||
if (data->buffer == NULL) {
|
||||
data->buffer = malloc(data->org_count);
|
||||
if (data->buffer == NULL) {
|
||||
data->oom = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* copy data into reassembly buffer */
|
||||
memcpy(&data->buffer[mdata->offset - data->offset], res->READ3res_u.resok.data.data_val, count);
|
||||
} else {
|
||||
|
@ -4738,7 +4850,7 @@ nfs3_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
|||
data->private_data = private_data;
|
||||
data->nfsfh = nfsfh;
|
||||
data->org_offset = offset;
|
||||
data->org_count = (count3)count;
|
||||
data->org_count = count;
|
||||
data->update_pos = update_pos;
|
||||
|
||||
assert(data->num_calls == 0);
|
||||
|
@ -4871,8 +4983,15 @@ nfs3_chdir_continue_internal(struct nfs_context *nfs,
|
|||
struct nfs_cb_data *data)
|
||||
{
|
||||
/* steal saved_path */
|
||||
free(nfs->cwd);
|
||||
nfs->cwd = data->saved_path;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&nfs->rpc->rpc_mutex);
|
||||
#endif
|
||||
free(nfs->nfsi->cwd);
|
||||
nfs->nfsi->cwd = data->saved_path;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&nfs->rpc->rpc_mutex);
|
||||
#endif
|
||||
|
||||
data->saved_path = NULL;
|
||||
|
||||
data->cb(0, nfs, NULL, data->private_data);
|
||||
|
|
427
lib/nfs_v4.c
427
lib/nfs_v4.c
|
@ -30,6 +30,14 @@
|
|||
#include "aros_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS3_PPU
|
||||
#include "ps3_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#endif
|
||||
|
@ -95,6 +103,7 @@
|
|||
#include "slist.h"
|
||||
#include "libnfs.h"
|
||||
#include "libnfs-raw.h"
|
||||
#include "libnfs-raw-nfs4.h"
|
||||
#include "libnfs-private.h"
|
||||
|
||||
#ifndef discard_const
|
||||
|
@ -143,6 +152,7 @@ struct nfs4_cb_data {
|
|||
*/
|
||||
#define LOOKUP_FLAG_NO_FOLLOW 0x0001
|
||||
#define LOOKUP_FLAG_IS_STATVFS64 0x0002
|
||||
#define MUTEX_HELD 0x0004
|
||||
int flags;
|
||||
|
||||
/* Internal callback for open-with-continuation use */
|
||||
|
@ -152,6 +162,9 @@ struct nfs4_cb_data {
|
|||
nfs_cb cb;
|
||||
void *private_data;
|
||||
|
||||
/* Used to track lock_owner during open() */
|
||||
uint32_t lock_owner;
|
||||
|
||||
/* internal callback */
|
||||
rpc_cb continue_cb;
|
||||
|
||||
|
@ -189,6 +202,10 @@ static uint32_t statvfs_attributes[2] = {
|
|||
1 << (FATTR4_SPACE_TOTAL - 32))
|
||||
};
|
||||
|
||||
static uint32_t getacl_attributes[1] = {
|
||||
(1 << FATTR4_ACL )
|
||||
};
|
||||
|
||||
static int
|
||||
nfs4_open_async_internal(struct nfs_context *nfs, struct nfs4_cb_data *data,
|
||||
int flags, int mode);
|
||||
|
@ -206,9 +223,9 @@ nfs4_resolve_path(struct nfs_context *nfs, const char *path)
|
|||
if (path[0] == '/') {
|
||||
new_path = strdup(path);
|
||||
} else {
|
||||
new_path = malloc(strlen(path) + strlen(nfs->cwd) + 2);
|
||||
new_path = malloc(strlen(path) + strlen(nfs->nfsi->cwd) + 2);
|
||||
if (new_path != NULL) {
|
||||
sprintf(new_path, "%s/%s", nfs->cwd, path);
|
||||
sprintf(new_path, "%s/%s", nfs->nfsi->cwd, path);
|
||||
}
|
||||
}
|
||||
if (new_path == NULL) {
|
||||
|
@ -397,7 +414,8 @@ nfs_pntoh64(const uint32_t *buf)
|
|||
{
|
||||
uint64_t val;
|
||||
|
||||
val = ntohl(*(uint32_t *)(void *)buf++);
|
||||
val = ntohl(*(uint32_t *)(void *)buf);
|
||||
buf++;
|
||||
val <<= 32;
|
||||
val |= ntohl(*(uint32_t *)(void *)buf);
|
||||
|
||||
|
@ -625,6 +643,23 @@ nfs4_op_commit(struct nfs_context *nfs, nfs_argop4 *op)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
static int
|
||||
nfs4_op_release_lockowner(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh)
|
||||
{
|
||||
RELEASE_LOCKOWNER4args *rlargs;
|
||||
|
||||
op->argop = OP_RELEASE_LOCKOWNER;
|
||||
rlargs = &op->nfs_argop4_u.oprelease_lockowner;
|
||||
|
||||
rlargs->lock_owner.clientid = nfs->nfsi->clientid;
|
||||
rlargs->lock_owner.owner.owner_len = 4;
|
||||
rlargs->lock_owner.owner.owner_val = (char *)&fh->lock_owner;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
nfs4_op_close(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh)
|
||||
{
|
||||
|
@ -637,10 +672,14 @@ nfs4_op_close(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh)
|
|||
|
||||
op[i].argop = OP_CLOSE;
|
||||
clargs = &op[i++].nfs_argop4_u.opclose;
|
||||
clargs->seqid = nfs->seqid;
|
||||
clargs->seqid = fh->open_seqid;
|
||||
clargs->open_stateid.seqid = fh->stateid.seqid;
|
||||
memcpy(clargs->open_stateid.other, fh->stateid.other, 12);
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
i += nfs4_op_release_lockowner(nfs, &op[i], fh);
|
||||
#endif
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -686,8 +725,7 @@ nfs4_op_setclientid(struct nfs_context *nfs, nfs_argop4 *op, verifier4 verifier,
|
|||
}
|
||||
|
||||
static int
|
||||
nfs4_op_open_confirm(struct nfs_context *nfs, nfs_argop4 *op, uint32_t seqid,
|
||||
struct nfsfh *fh)
|
||||
nfs4_op_open_confirm(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh)
|
||||
{
|
||||
OPEN_CONFIRM4args *ocargs;
|
||||
|
||||
|
@ -695,7 +733,7 @@ nfs4_op_open_confirm(struct nfs_context *nfs, nfs_argop4 *op, uint32_t seqid,
|
|||
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;
|
||||
ocargs->seqid = fh->open_seqid;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -732,8 +770,10 @@ nfs4_op_chmod(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh,
|
|||
|
||||
op[0].argop = OP_SETATTR;
|
||||
saargs = &op[0].nfs_argop4_u.opsetattr;
|
||||
if (fh) {
|
||||
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;
|
||||
|
@ -755,8 +795,10 @@ nfs4_op_chown(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh,
|
|||
|
||||
op[0].argop = OP_SETATTR;
|
||||
saargs = &op[0].nfs_argop4_u.opsetattr;
|
||||
if (fh) {
|
||||
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;
|
||||
|
@ -778,8 +820,10 @@ nfs4_op_utimes(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh,
|
|||
|
||||
op[0].argop = OP_SETATTR;
|
||||
saargs = &op[0].nfs_argop4_u.opsetattr;
|
||||
if (fh) {
|
||||
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;
|
||||
|
@ -921,7 +965,7 @@ nfs4_op_lock(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh,
|
|||
largs->offset = offset;
|
||||
largs->length = length;
|
||||
|
||||
if (nfs->has_lock_owner) {
|
||||
if (nfs->nfsi->has_lock_owner) {
|
||||
largs->locker.new_lock_owner = 0;
|
||||
largs->locker.locker4_u.lock_owner.lock_stateid.seqid =
|
||||
fh->lock_stateid.seqid;
|
||||
|
@ -932,17 +976,17 @@ nfs4_op_lock(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh,
|
|||
} else {
|
||||
largs->locker.new_lock_owner = 1;
|
||||
largs->locker.locker4_u.open_owner.open_seqid =
|
||||
nfs->seqid;
|
||||
fh->open_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;
|
||||
nfs->nfsi->clientid;
|
||||
largs->locker.locker4_u.open_owner.lock_owner.owner.owner_len =
|
||||
strlen(nfs->client_name);
|
||||
strlen(nfs->nfsi->client_name);
|
||||
largs->locker.locker4_u.open_owner.lock_owner.owner.owner_val =
|
||||
nfs->client_name;
|
||||
nfs->nfsi->client_name;
|
||||
largs->locker.locker4_u.open_owner.lock_seqid =
|
||||
fh->lock_seqid;
|
||||
}
|
||||
|
@ -984,9 +1028,9 @@ nfs4_op_lockt(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh,
|
|||
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;
|
||||
ltargs->owner.clientid = nfs->nfsi->clientid;
|
||||
ltargs->owner.owner.owner_len = strlen(nfs->nfsi->client_name);
|
||||
ltargs->owner.owner.owner_val = nfs->nfsi->client_name;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1091,11 +1135,11 @@ nfs4_allocate_op(struct nfs_context *nfs, nfs_argop4 **op,
|
|||
}
|
||||
|
||||
i = 0;
|
||||
if (nfs->rootfh.len) {
|
||||
if (nfs->nfsi->rootfh.len) {
|
||||
struct nfsfh fh;
|
||||
|
||||
fh.fh.len = nfs->rootfh.len;
|
||||
fh.fh.val = nfs->rootfh.val;
|
||||
fh.fh.len = nfs->nfsi->rootfh.len;
|
||||
fh.fh.val = nfs->nfsi->rootfh.val;
|
||||
i += nfs4_op_putfh(nfs, &(*op)[i], &fh);
|
||||
} else {
|
||||
i += nfs4_op_putrootfh(nfs, &(*op)[i]);
|
||||
|
@ -1170,7 +1214,7 @@ nfs4_lookup_path_2_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
rlres = &res->resarray.resarray_val[i].nfs_resop4_u.opreadlink;
|
||||
|
||||
tmp = malloc(strlen(data->path) + 3 + strlen(rlres->READLINK4res_u.resok4.link.utf8string_val));
|
||||
tmp = malloc(strlen(data->path) + 3 + rlres->READLINK4res_u.resok4.link.utf8string_len);
|
||||
if (tmp == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory duplicating path.");
|
||||
data->cb(-ENOMEM, nfs, nfs_get_error(nfs),
|
||||
|
@ -1180,7 +1224,9 @@ nfs4_lookup_path_2_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
return;
|
||||
}
|
||||
|
||||
sprintf(tmp, "%s/%s/%s", path, rlres->READLINK4res_u.resok4.link.utf8string_val, end);
|
||||
sprintf(tmp, "%s/%.*s/%s",
|
||||
path, rlres->READLINK4res_u.resok4.link.utf8string_len,
|
||||
rlres->READLINK4res_u.resok4.link.utf8string_val, end);
|
||||
free(path);
|
||||
free(data->path);
|
||||
data->path = tmp;
|
||||
|
@ -1453,17 +1499,17 @@ nfs4_mount_4_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
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->nfsi->rootfh.len = gfhresok->object.nfs_fh4_len;
|
||||
nfs->nfsi->rootfh.val = malloc(nfs->nfsi->rootfh.len);
|
||||
if (nfs->nfsi->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,
|
||||
memcpy(nfs->nfsi->rootfh.val,
|
||||
gfhresok->object.nfs_fh4_val,
|
||||
nfs->rootfh.len);
|
||||
nfs->nfsi->rootfh.len);
|
||||
|
||||
|
||||
data->cb(0, nfs, NULL, data->private_data);
|
||||
|
@ -1523,15 +1569,15 @@ nfs4_mount_2_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
scidresok = &res->resarray.resarray_val[0].nfs_resop4_u.opsetclientid.SETCLIENTID4res_u.resok4;
|
||||
nfs->clientid = scidresok->clientid;
|
||||
memcpy(nfs->setclientid_confirm,
|
||||
nfs->nfsi->clientid = scidresok->clientid;
|
||||
memcpy(nfs->nfsi->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);
|
||||
i = nfs4_op_setclientid_confirm(nfs, &op[0], nfs->nfsi->clientid,
|
||||
nfs->nfsi->setclientid_confirm);
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.argarray.argarray_len = i;
|
||||
|
@ -1565,7 +1611,7 @@ nfs4_mount_1_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
|
||||
memset(op, 0, sizeof(op));
|
||||
|
||||
i = nfs4_op_setclientid(nfs, &op[0], nfs->verifier, nfs->client_name);
|
||||
i = nfs4_op_setclientid(nfs, &op[0], nfs->nfsi->verifier, nfs->nfsi->client_name);
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.argarray.argarray_len = i;
|
||||
|
@ -1589,8 +1635,8 @@ nfs4_mount_async(struct nfs_context *nfs, const char *server,
|
|||
int port;
|
||||
|
||||
new_server = strdup(server);
|
||||
free(nfs->server);
|
||||
nfs->server = new_server;
|
||||
free(nfs->nfsi->server);
|
||||
nfs->nfsi->server = new_server;
|
||||
|
||||
new_export = strdup(export);
|
||||
if (nfs_normalize_path(nfs, new_export)) {
|
||||
|
@ -1599,8 +1645,8 @@ nfs4_mount_async(struct nfs_context *nfs, const char *server,
|
|||
free(new_export);
|
||||
return -1;
|
||||
}
|
||||
free(nfs->export);
|
||||
nfs->export = new_export;
|
||||
free(nfs->nfsi->export);
|
||||
nfs->nfsi->export = new_export;
|
||||
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
|
@ -1616,7 +1662,7 @@ nfs4_mount_async(struct nfs_context *nfs, const char *server,
|
|||
data->private_data = private_data;
|
||||
data->path = strdup(new_export);
|
||||
|
||||
port = nfs->nfsport ? nfs->nfsport : 2049;
|
||||
port = nfs->nfsi->nfsport ? nfs->nfsi->nfsport : 2049;
|
||||
if (rpc_connect_port_async(nfs->rpc, server, port,
|
||||
NFS4_PROGRAM, NFS_V4,
|
||||
nfs4_mount_1_cb, data) != 0) {
|
||||
|
@ -1643,8 +1689,15 @@ nfs4_chdir_1_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
/* Ok, all good. Lets steal the path string. */
|
||||
free(nfs->cwd);
|
||||
nfs->cwd = data->path;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&nfs->rpc->rpc_mutex);
|
||||
#endif
|
||||
free(nfs->nfsi->cwd);
|
||||
nfs->nfsi->cwd = data->path;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&nfs->rpc->rpc_mutex);
|
||||
#endif
|
||||
|
||||
data->path = NULL;
|
||||
|
||||
data->cb(0, nfs, NULL, data->private_data);
|
||||
|
@ -1895,7 +1948,7 @@ nfs4_rmdir_async(struct nfs_context *nfs, const char *path,
|
|||
}
|
||||
|
||||
static void
|
||||
nfs_increment_seqid(struct nfs_context *nfs, uint32_t status)
|
||||
nfs_increment_seqid(struct nfsfh *nfsfh, uint32_t status)
|
||||
{
|
||||
/* RFC3530 8.1.5 */
|
||||
switch (status) {
|
||||
|
@ -1908,7 +1961,7 @@ nfs_increment_seqid(struct nfs_context *nfs, uint32_t status)
|
|||
case NFS4ERR_NOFILEHANDLE:
|
||||
break;
|
||||
default:
|
||||
nfs->seqid++;
|
||||
nfsfh->open_seqid++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2004,12 +2057,12 @@ nfs4_open_confirm_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
COMPOUND4res *res = command_data;
|
||||
OPEN_CONFIRM4resok *ocresok;
|
||||
int i;
|
||||
struct nfsfh *fh;
|
||||
struct nfsfh *fh = data->filler.blob0.val;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (res) {
|
||||
nfs_increment_seqid(nfs, res->status);
|
||||
nfs_increment_seqid(fh, res->status);
|
||||
}
|
||||
|
||||
if (check_nfs4_error(nfs, status, data, res, "OPEN_CONFIRM")) {
|
||||
|
@ -2051,10 +2104,6 @@ nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (res) {
|
||||
nfs_increment_seqid(nfs, res->status);
|
||||
}
|
||||
|
||||
if (check_nfs4_error(nfs, status, data, res, "OPEN")) {
|
||||
return;
|
||||
}
|
||||
|
@ -2101,6 +2150,8 @@ nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
return;
|
||||
}
|
||||
memcpy(fh->fh.val, gresok->object.nfs_fh4_val, fh->fh.len);
|
||||
fh->open_seqid = 1;
|
||||
fh->lock_owner = data->lock_owner;
|
||||
|
||||
if (data->filler.flags & O_SYNC) {
|
||||
fh->is_sync = 1;
|
||||
|
@ -2125,7 +2176,7 @@ nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
|
||||
memset(op, 0, sizeof(op));
|
||||
i = nfs4_op_putfh(nfs, &op[0], fh);
|
||||
i += nfs4_op_open_confirm(nfs, &op[i], nfs->seqid, fh);
|
||||
i += nfs4_op_open_confirm(nfs, &op[i], fh);
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.argarray.argarray_len = i;
|
||||
|
@ -2199,7 +2250,6 @@ nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op)
|
|||
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;
|
||||
}
|
||||
|
@ -2207,9 +2257,10 @@ nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op)
|
|||
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;
|
||||
oargs->owner.clientid = nfs->nfsi->clientid;
|
||||
oargs->owner.owner.owner_len = 4;
|
||||
oargs->owner.owner.owner_val = (char *)&data->lock_owner;
|
||||
oargs->seqid = 0;
|
||||
if (data->filler.flags & O_CREAT) {
|
||||
createhow4 *ch;
|
||||
fattr4 *fa;
|
||||
|
@ -2271,7 +2322,7 @@ nfs4_open_readlink_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
rlresok = &res->resarray.resarray_val[i].nfs_resop4_u.opreadlink.READLINK4res_u.resok4;
|
||||
|
||||
path = malloc(2 + strlen(data->path) +
|
||||
strlen(rlresok->link.utf8string_val));
|
||||
rlresok->link.utf8string_len);
|
||||
if (path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"path");
|
||||
|
@ -2280,8 +2331,8 @@ nfs4_open_readlink_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
free_nfs4_cb_data(data);
|
||||
return;
|
||||
}
|
||||
sprintf(path, "%s/%s", data->path, rlresok->link.utf8string_val);
|
||||
|
||||
sprintf(path, "%s/%.*s", data->path,
|
||||
rlresok->link.utf8string_len, rlresok->link.utf8string_val);
|
||||
|
||||
|
||||
free(data->path);
|
||||
|
@ -2300,6 +2351,14 @@ nfs4_open_readlink_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
|
||||
data_split_path(data);
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&data->nfs->nfsi->nfs4_open_mutex);
|
||||
#endif
|
||||
data->lock_owner = nfs->nfsi->open_counter++;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&data->nfs->nfsi->nfs4_open_mutex);
|
||||
#endif
|
||||
|
||||
data->filler.func = nfs4_populate_open;
|
||||
data->filler.max_op = 3;
|
||||
|
||||
|
@ -2416,6 +2475,13 @@ nfs4_open_async_internal(struct nfs_context *nfs, struct nfs4_cb_data *data,
|
|||
data->filler.blob2.free = free;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&data->nfs->nfsi->nfs4_open_mutex);
|
||||
#endif
|
||||
data->lock_owner = nfs->nfsi->open_counter++;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&data->nfs->nfsi->nfs4_open_mutex);
|
||||
#endif
|
||||
data->filler.func = nfs4_populate_open;
|
||||
data->filler.max_op = 3;
|
||||
data->filler.flags = flags;
|
||||
|
@ -2434,6 +2500,7 @@ nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,
|
|||
{
|
||||
struct nfs4_cb_data *data;
|
||||
uint32_t m;
|
||||
int ret;
|
||||
|
||||
data = init_cb_data_split_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
|
@ -2480,7 +2547,8 @@ nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,
|
|||
memcpy(data->filler.blob3.val, &m, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
return nfs4_open_async_internal(nfs, data, flags, mode);
|
||||
ret = nfs4_open_async_internal(nfs, data, flags, mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -2520,6 +2588,86 @@ nfs4_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nfs4_getacl_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;
|
||||
fattr4_acl acl;
|
||||
ZDR zdr;
|
||||
int i;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (check_nfs4_error(nfs, status, data, res, "GETACL")) {
|
||||
data->cb(-EIO, nfs, "GETACL failed", data->private_data);
|
||||
free_nfs4_cb_data(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((i = nfs4_find_op(nfs, data, res, OP_GETATTR, "GETATTR")) < 0) {
|
||||
data->cb(-EIO, nfs, "GETACL failed", data->private_data);
|
||||
free_nfs4_cb_data(data);
|
||||
return;
|
||||
}
|
||||
garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4;
|
||||
|
||||
memset(&acl, 0, sizeof(acl));
|
||||
zdrmem_create(&zdr,
|
||||
garesok->obj_attributes.attr_vals.attrlist4_val,
|
||||
garesok->obj_attributes.attr_vals.attrlist4_len,
|
||||
ZDR_DECODE);
|
||||
if (zdr_fattr4_acl(&zdr, &acl)) {
|
||||
data->cb(0, nfs, &acl, data->private_data);
|
||||
} else {
|
||||
data->cb(-EIO, nfs, "Failed to unmarshall fattr4_acl", data->private_data);
|
||||
}
|
||||
|
||||
zdr_destroy(&zdr);
|
||||
free_nfs4_cb_data(data);
|
||||
}
|
||||
|
||||
int
|
||||
nfs4_getacl_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], getacl_attributes, 1);
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.argarray.argarray_len = i;
|
||||
args.argarray.argarray_val = op;
|
||||
|
||||
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_getacl_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)
|
||||
|
@ -2527,11 +2675,12 @@ nfs4_close_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
struct nfs4_cb_data *data = private_data;
|
||||
struct nfs_context *nfs = data->nfs;
|
||||
COMPOUND4res *res = command_data;
|
||||
struct nfsfh *nfsfh = data->filler.blob0.val;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (res) {
|
||||
nfs_increment_seqid(nfs, res->status);
|
||||
nfs_increment_seqid(nfsfh, res->status);
|
||||
}
|
||||
|
||||
if (check_nfs4_error(nfs, status, data, res, "CLOSE")) {
|
||||
|
@ -2547,7 +2696,7 @@ nfs4_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
|
|||
void *private_data)
|
||||
{
|
||||
COMPOUND4args args;
|
||||
nfs_argop4 op[3];
|
||||
nfs_argop4 op[4];
|
||||
struct nfs4_cb_data *data;
|
||||
int i;
|
||||
|
||||
|
@ -2730,6 +2879,7 @@ nfs4_readlink_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
struct nfs_context *nfs = data->nfs;
|
||||
COMPOUND4res *res = command_data;
|
||||
READLINK4resok *rlresok;
|
||||
char* target;
|
||||
int i;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
@ -2744,7 +2894,16 @@ nfs4_readlink_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
|
||||
rlresok = &res->resarray.resarray_val[i].nfs_resop4_u.opreadlink.READLINK4res_u.resok4;
|
||||
|
||||
data->cb(0, nfs, rlresok->link.utf8string_val, data->private_data);
|
||||
target = strdup(rlresok->link.utf8string_val);
|
||||
if (target == NULL) {
|
||||
data->cb(-ENOMEM, nfs, "Failed to allocate memory",
|
||||
data->private_data);
|
||||
free_nfs4_cb_data(data);
|
||||
return;
|
||||
}
|
||||
data->filler.blob0.val = target;
|
||||
data->filler.blob0.free = free;
|
||||
data->cb(0, nfs, target, data->private_data);
|
||||
free_nfs4_cb_data(data);
|
||||
}
|
||||
|
||||
|
@ -2852,10 +3011,12 @@ nfs4_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
|||
args.argarray.argarray_len = i;
|
||||
args.argarray.argarray_val = op;
|
||||
|
||||
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_pwrite_cb, &args,
|
||||
data) != 0) {
|
||||
if (rpc_nfs4_compound_async2(nfs->rpc, nfs4_pwrite_cb, &args,
|
||||
data, count) != 0) {
|
||||
nfs_set_error(nfs, "PWRITE "
|
||||
"failed: %s", rpc_get_error(nfs->rpc));
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2957,10 +3118,12 @@ nfs4_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count,
|
|||
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) {
|
||||
if (rpc_nfs4_compound_async2(nfs->rpc, nfs4_write_append_cb,
|
||||
&args, data, count) != 0) {
|
||||
nfs_set_error(nfs, "PWRITE "
|
||||
"failed: %s", rpc_get_error(nfs->rpc));
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -3474,6 +3637,7 @@ nfs4_parse_readdir(struct nfs_context *nfs, struct nfs4_cb_data *data,
|
|||
return;
|
||||
}
|
||||
|
||||
nfsdirent->inode = st.nfs_ino;
|
||||
nfsdirent->mode = (uint32_t)st.nfs_mode;
|
||||
switch (st.nfs_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
|
@ -3660,11 +3824,12 @@ nfs4_truncate_close_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
struct nfs4_cb_data *data = private_data;
|
||||
struct nfs_context *nfs = data->nfs;
|
||||
COMPOUND4res *res = command_data;
|
||||
struct nfsfh *fh = data->filler.blob0.val;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (res) {
|
||||
nfs_increment_seqid(nfs, res->status);
|
||||
nfs_increment_seqid(fh, res->status);
|
||||
}
|
||||
|
||||
if (check_nfs4_error(nfs, status, data, res, "CLOSE")) {
|
||||
|
@ -4001,7 +4166,7 @@ nfs4_lockf_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
lresok = &res->resarray.resarray_val[i].nfs_resop4_u.oplock.LOCK4res_u.resok4;
|
||||
nfs->has_lock_owner = 1;
|
||||
nfs->nfsi->has_lock_owner = 1;
|
||||
fh->lock_stateid.seqid = lresok->lock_stateid.seqid;
|
||||
memcpy(fh->lock_stateid.other, lresok->lock_stateid.other, 12);
|
||||
break;
|
||||
|
@ -4120,7 +4285,7 @@ nfs4_fcntl_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
lresok = &res->resarray.resarray_val[i].nfs_resop4_u.oplock.LOCK4res_u.resok4;
|
||||
nfs->has_lock_owner = 1;
|
||||
nfs->nfsi->has_lock_owner = 1;
|
||||
fh->lock_stateid.seqid = lresok->lock_stateid.seqid;
|
||||
memcpy(fh->lock_stateid.other,
|
||||
lresok->lock_stateid.other, 12);
|
||||
|
@ -4545,8 +4710,8 @@ nfs4_statvfs_async_internal(struct nfs_context *nfs, const char *path,
|
|||
data->flags |= LOOKUP_FLAG_IS_STATVFS64;
|
||||
}
|
||||
|
||||
fh.fh.len = nfs->rootfh.len;
|
||||
fh.fh.val = nfs->rootfh.val;
|
||||
fh.fh.len = nfs->nfsi->rootfh.len;
|
||||
fh.fh.val = nfs->nfsi->rootfh.val;
|
||||
|
||||
i = nfs4_op_putfh(nfs, &op[0], &fh);
|
||||
i += nfs4_op_getattr(nfs, &op[i], statvfs_attributes, 2);
|
||||
|
@ -4581,36 +4746,25 @@ nfs4_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
|
|||
}
|
||||
|
||||
static void
|
||||
nfs4_chmod_open_cb(struct rpc_context *rpc, int status, void *command_data,
|
||||
nfs4_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[4];
|
||||
int i;
|
||||
|
||||
if (check_nfs4_error(nfs, status, data, res, "OPEN")) {
|
||||
if (check_nfs4_error(nfs, status, data, res, "CHMOD")) {
|
||||
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);
|
||||
data->cb(0, nfs, NULL, data->private_data);
|
||||
free_nfs4_cb_data(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nfs4_populate_chmod(struct nfs4_cb_data *data, nfs_argop4 *op)
|
||||
{
|
||||
return nfs4_op_chmod(data->nfs, op, NULL, data->filler.blob3.val);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -4621,14 +4775,15 @@ nfs4_chmod_async_internal(struct nfs_context *nfs, const char *path,
|
|||
struct nfs4_cb_data *data;
|
||||
uint32_t m;
|
||||
|
||||
data = init_cb_data_split_path(nfs, path);
|
||||
data = init_cb_data_full_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->open_cb = nfs4_chmod_open_cb;
|
||||
data->filler.func = nfs4_populate_chmod;
|
||||
data->filler.max_op = 1;
|
||||
|
||||
if (no_follow) {
|
||||
data->flags |= LOOKUP_FLAG_NO_FOLLOW;
|
||||
|
@ -4645,7 +4800,7 @@ nfs4_chmod_async_internal(struct nfs_context *nfs, const char *path,
|
|||
m = htonl(mode);
|
||||
memcpy(data->filler.blob3.val, &m, sizeof(uint32_t));
|
||||
|
||||
if (nfs4_open_async_internal(nfs, data, O_WRONLY, 0) < 0) {
|
||||
if (nfs4_lookup_path_async(nfs, data, nfs4_chmod_cb) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -4754,37 +4909,26 @@ nfs4_create_chown_buffer(struct nfs_context *nfs, struct nfs4_cb_data *data,
|
|||
}
|
||||
|
||||
static void
|
||||
nfs4_chown_open_cb(struct rpc_context *rpc, int status, void *command_data,
|
||||
nfs4_chown_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);
|
||||
data->cb(0, nfs, NULL, data->private_data);
|
||||
free_nfs4_cb_data(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nfs4_populate_chown(struct nfs4_cb_data *data, nfs_argop4 *op)
|
||||
{
|
||||
return nfs4_op_chown(data->nfs, op, NULL, data->filler.blob3.val,
|
||||
data->filler.blob3.len);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -4801,7 +4945,8 @@ nfs4_chown_async_internal(struct nfs_context *nfs, const char *path,
|
|||
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->open_cb = nfs4_chown_open_cb;
|
||||
data->filler.func = nfs4_populate_chown;
|
||||
data->filler.max_op = 1;
|
||||
|
||||
if (no_follow) {
|
||||
data->flags |= LOOKUP_FLAG_NO_FOLLOW;
|
||||
|
@ -4812,7 +4957,7 @@ nfs4_chown_async_internal(struct nfs_context *nfs, const char *path,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (nfs4_open_async_internal(nfs, data, O_WRONLY, 0) < 0) {
|
||||
if (nfs4_lookup_path_async(nfs, data, nfs4_chown_cb) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -4976,37 +5121,28 @@ nfs4_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
|
|||
}
|
||||
|
||||
static void
|
||||
nfs4_utimes_open_cb(struct rpc_context *rpc, int status, void *command_data,
|
||||
nfs4_utimes_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")) {
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (check_nfs4_error(nfs, status, data, res, "UTIMES")) {
|
||||
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);
|
||||
data->cb(0, nfs, NULL, data->private_data);
|
||||
free_nfs4_cb_data(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nfs4_populate_utimes(struct nfs4_cb_data *data, nfs_argop4 *op)
|
||||
{
|
||||
return nfs4_op_utimes(data->nfs, op, NULL, data->filler.blob3.val,
|
||||
data->filler.blob3.len);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -5019,14 +5155,15 @@ nfs4_utimes_async_internal(struct nfs_context *nfs, const char *path,
|
|||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
|
||||
data = init_cb_data_split_path(nfs, path);
|
||||
data = init_cb_data_full_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->open_cb = nfs4_utimes_open_cb;
|
||||
data->filler.func = nfs4_populate_utimes;
|
||||
data->filler.max_op = 1;
|
||||
|
||||
if (no_follow) {
|
||||
data->flags |= LOOKUP_FLAG_NO_FOLLOW;
|
||||
|
@ -5038,8 +5175,10 @@ nfs4_utimes_async_internal(struct nfs_context *nfs, const char *path,
|
|||
nfs_set_error(nfs, "Out of memory");
|
||||
return -1;
|
||||
}
|
||||
memset(buf, 0, data->filler.blob3.len);
|
||||
data->filler.blob3.free = free;
|
||||
|
||||
if (times != NULL) {
|
||||
/* atime */
|
||||
u32 = htonl(SET_TO_CLIENT_TIME4);
|
||||
memcpy(buf, &u32, sizeof(uint32_t));
|
||||
|
@ -5055,8 +5194,18 @@ nfs4_utimes_async_internal(struct nfs_context *nfs, const char *path,
|
|||
memcpy(buf + 4, &u64, sizeof(uint64_t));
|
||||
u32 = htonl(times[1].tv_usec * 1000);
|
||||
memcpy(buf + 12, &u32, sizeof(uint32_t));
|
||||
} else {
|
||||
/* atime */
|
||||
u32 = htonl(SET_TO_SERVER_TIME4);
|
||||
memcpy(buf, &u32, sizeof(uint32_t));
|
||||
/* mtime */
|
||||
u32 = htonl(SET_TO_SERVER_TIME4);
|
||||
memcpy(buf + 4, &u32, sizeof(uint32_t));
|
||||
data->filler.blob3.len = 8;
|
||||
}
|
||||
|
||||
if (nfs4_open_async_internal(nfs, data, O_WRONLY, 0) < 0) {
|
||||
if (nfs4_lookup_path_async(nfs, data, nfs4_utimes_cb) < 0) {
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -5067,6 +5216,10 @@ int
|
|||
nfs4_utime_async(struct nfs_context *nfs, const char *path,
|
||||
struct utimbuf *times, nfs_cb cb, void *private_data)
|
||||
{
|
||||
if (times == NULL) {
|
||||
return nfs4_utimes_async_internal(nfs, path, 0, NULL,
|
||||
cb, private_data);
|
||||
}
|
||||
struct timeval new_times[2];
|
||||
|
||||
new_times[0].tv_sec = times->actime;
|
||||
|
|
64
lib/pdu.c
64
lib/pdu.c
|
@ -23,6 +23,14 @@
|
|||
#include "aros_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS3_PPU
|
||||
#include "ps3_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#endif
|
||||
|
@ -152,7 +160,13 @@ struct rpc_pdu *rpc_allocate_pdu2(struct rpc_context *rpc, int program, int vers
|
|||
return NULL;
|
||||
}
|
||||
memset(pdu, 0, pdu_size);
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
pdu->xid = rpc->xid++;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
pdu->cb = cb;
|
||||
pdu->private_data = private_data;
|
||||
pdu->zdr_decode_fn = zdr_decode_fn;
|
||||
|
@ -214,12 +228,19 @@ void rpc_free_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu)
|
|||
|
||||
void rpc_set_next_xid(struct rpc_context *rpc, uint32_t xid)
|
||||
{
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
rpc->xid = xid;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
}
|
||||
|
||||
int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu)
|
||||
{
|
||||
int size, recordmarker;
|
||||
int size;
|
||||
int32_t recordmarker;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
|
@ -255,8 +276,14 @@ int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu)
|
|||
}
|
||||
|
||||
hash = rpc_hash_xid(pdu->xid);
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
rpc_enqueue(&rpc->waitpdu[hash], pdu);
|
||||
rpc->waitpdu_len++;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -266,7 +293,18 @@ int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu)
|
|||
zdr_int(&pdu->zdr, &recordmarker);
|
||||
|
||||
pdu->outdata.size = size;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
rpc_enqueue(&rpc->outqueue, pdu);
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
if (rpc->outqueue.head == pdu) {
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
rpc_write_to_socket(rpc);
|
||||
} else {
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
}
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -440,7 +478,8 @@ static int rpc_process_call(struct rpc_context *rpc, ZDR *zdr)
|
|||
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);
|
||||
(int)call.body.cbody.prog,
|
||||
(int)call.body.cbody.vers);
|
||||
if (!found_program) {
|
||||
return rpc_send_error_reply(rpc, &call, PROG_UNAVAIL,
|
||||
0, 0);
|
||||
|
@ -458,7 +497,7 @@ static int rpc_process_call(struct rpc_context *rpc, ZDR *zdr)
|
|||
"call payload");
|
||||
return rpc_send_error_reply(rpc, &call, GARBAGE_ARGS, 0 ,0);
|
||||
}
|
||||
return endpoint->procs[i].func(rpc, &call);
|
||||
return endpoint->procs[i].func(rpc, &call, endpoint->procs[i].opaque);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,7 +509,8 @@ 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;
|
||||
int pos;
|
||||
int32_t recordmarker = 0;
|
||||
unsigned int hash;
|
||||
uint32_t xid;
|
||||
char *reasbuf = NULL;
|
||||
|
@ -505,6 +545,11 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
|
|||
zdr_destroy(&zdr);
|
||||
for (fragment = rpc->fragments; fragment; fragment = fragment->next) {
|
||||
total += fragment->size;
|
||||
if (total < fragment->size) {
|
||||
rpc_set_error(rpc, "Fragments too large");
|
||||
rpc_free_all_fragments(rpc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
reasbuf = malloc(total);
|
||||
|
@ -535,7 +580,7 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
|
|||
}
|
||||
|
||||
pos = zdr_getpos(&zdr);
|
||||
if (zdr_int(&zdr, (int *)&xid) == 0) {
|
||||
if (zdr_u_int(&zdr, &xid) == 0) {
|
||||
rpc_set_error(rpc, "zdr_int reading xid failed");
|
||||
zdr_destroy(&zdr);
|
||||
if (reasbuf != NULL) {
|
||||
|
@ -547,6 +592,9 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
|
|||
|
||||
/* Look up the transaction in a hash table of our requests */
|
||||
hash = rpc_hash_xid(xid);
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
q = &rpc->waitpdu[hash];
|
||||
|
||||
/* Follow the hash chain. Linear traverse singly-linked list,
|
||||
|
@ -567,6 +615,9 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
|
|||
prev_pdu->next = pdu->next;
|
||||
rpc->waitpdu_len--;
|
||||
}
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
if (rpc_process_reply(rpc, pdu, &zdr) != 0) {
|
||||
rpc_set_error(rpc, "rpc_procdess_reply failed");
|
||||
}
|
||||
|
@ -579,6 +630,9 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
zdr_destroy(&zdr);
|
||||
if (reasbuf != NULL) {
|
||||
|
|
80
lib/socket.c
80
lib/socket.c
|
@ -23,6 +23,14 @@
|
|||
#include "aros_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef PS3_PPU
|
||||
#include "ps3_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#endif
|
||||
|
@ -87,7 +95,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#if (defined(__APPLE__) && defined(__MACH__)) || defined(PS2_EE)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
#endif
|
||||
|
@ -122,17 +130,19 @@ set_nonblocking(int fd)
|
|||
#else
|
||||
v = fcntl(fd, F_GETFL, 0);
|
||||
v = fcntl(fd, F_SETFL, v | O_NONBLOCK);
|
||||
#endif //FIXME
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
set_nolinger(int fd)
|
||||
{
|
||||
#if !defined(PS2_EE)
|
||||
struct linger lng;
|
||||
lng.l_onoff = 1;
|
||||
lng.l_linger = 0;
|
||||
setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&lng, sizeof(lng));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -204,17 +214,24 @@ rpc_which_events(struct rpc_context *rpc)
|
|||
return POLLIN;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
if (rpc_has_queue(&rpc->outqueue)) {
|
||||
events |= POLLOUT;
|
||||
}
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
return events;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
rpc_write_to_socket(struct rpc_context *rpc)
|
||||
{
|
||||
int32_t count;
|
||||
struct rpc_pdu *pdu;
|
||||
int ret = 0;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
|
@ -223,6 +240,9 @@ rpc_write_to_socket(struct rpc_context *rpc)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
while ((pdu = rpc->outqueue.head) != NULL) {
|
||||
int64_t total;
|
||||
|
||||
|
@ -232,11 +252,13 @@ rpc_write_to_socket(struct rpc_context *rpc)
|
|||
(int)(total - pdu->written), MSG_NOSIGNAL);
|
||||
if (count == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto finished;
|
||||
}
|
||||
rpc_set_error(rpc, "Error when writing to socket :%s"
|
||||
"(%d)", strerror(errno), errno);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
pdu->written += count;
|
||||
|
@ -249,7 +271,8 @@ rpc_write_to_socket(struct rpc_context *rpc)
|
|||
|
||||
if (pdu->flags & PDU_DISCARD_AFTER_SENDING) {
|
||||
rpc_free_pdu(rpc, pdu);
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
hash = rpc_hash_xid(pdu->xid);
|
||||
|
@ -257,7 +280,12 @@ rpc_write_to_socket(struct rpc_context *rpc)
|
|||
rpc->waitpdu_len++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
finished:
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_UDP_SIZE 65536
|
||||
|
@ -300,6 +328,7 @@ rpc_read_from_socket(struct rpc_context *rpc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
again:
|
||||
do {
|
||||
/* Read record marker,
|
||||
* 4 bytes at the beginning of every pdu.
|
||||
|
@ -323,7 +352,7 @@ rpc_read_from_socket(struct rpc_context *rpc)
|
|||
"buffer of %d bytes for "
|
||||
"pdu, errno:%d. Closing "
|
||||
"socket.",
|
||||
pdu_size, errno);
|
||||
(int)pdu_size, errno);
|
||||
return -1;
|
||||
}
|
||||
memcpy(rpc->inbuf, &rpc->rm_buf, 4);
|
||||
|
@ -350,7 +379,7 @@ rpc_read_from_socket(struct rpc_context *rpc)
|
|||
if (rpc->inpos == 4) {
|
||||
/* We have just read the header and there is likely
|
||||
* more data available */
|
||||
continue;
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (rpc->inpos == pdu_size) {
|
||||
|
@ -392,6 +421,9 @@ rpc_timeout_scan(struct rpc_context *rpc)
|
|||
uint64_t t = rpc_current_time();
|
||||
unsigned int i;
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
for (pdu = rpc->outqueue.head; pdu; pdu = next_pdu) {
|
||||
next_pdu = pdu->next;
|
||||
|
||||
|
@ -405,7 +437,7 @@ rpc_timeout_scan(struct rpc_context *rpc)
|
|||
}
|
||||
LIBNFS_LIST_REMOVE(&rpc->outqueue.head, pdu);
|
||||
if (!rpc->outqueue.head) {
|
||||
rpc->outqueue.tail = NULL;
|
||||
rpc->outqueue.tail = NULL; //done
|
||||
}
|
||||
rpc_set_error(rpc, "command timed out");
|
||||
pdu->cb(rpc, RPC_STATUS_TIMEOUT,
|
||||
|
@ -413,8 +445,9 @@ rpc_timeout_scan(struct rpc_context *rpc)
|
|||
rpc_free_pdu(rpc, pdu);
|
||||
}
|
||||
for (i = 0; i < HASHES; i++) {
|
||||
struct rpc_queue *q = &rpc->waitpdu[i];
|
||||
struct rpc_queue *q;
|
||||
|
||||
q = &rpc->waitpdu[i];
|
||||
for (pdu = q->head; pdu; pdu = next_pdu) {
|
||||
next_pdu = pdu->next;
|
||||
|
||||
|
@ -430,12 +463,17 @@ rpc_timeout_scan(struct rpc_context *rpc)
|
|||
if (!q->head) {
|
||||
q->tail = NULL;
|
||||
}
|
||||
// qqq move to a temporary queue and process after
|
||||
// we drop the mutex
|
||||
rpc_set_error(rpc, "command timed out");
|
||||
pdu->cb(rpc, RPC_STATUS_TIMEOUT,
|
||||
NULL, pdu->private_data);
|
||||
rpc_free_pdu(rpc, pdu);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -597,7 +635,7 @@ rpc_connect_sockaddr_async(struct rpc_context *rpc)
|
|||
}
|
||||
|
||||
if (rpc->old_fd) {
|
||||
#if !defined(WIN32)
|
||||
#if !defined(WIN32) && !defined(PS3_PPU) && !defined(PS2_EE)
|
||||
if (dup2(rpc->fd, rpc->old_fd) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -663,6 +701,7 @@ rpc_connect_sockaddr_async(struct rpc_context *rpc)
|
|||
sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
break;
|
||||
#if !defined(PS3_PPU) && !defined(PS2_EE)
|
||||
case AF_INET6:
|
||||
sin6->sin6_port = port;
|
||||
sin6->sin6_family = AF_INET6;
|
||||
|
@ -671,6 +710,7 @@ rpc_connect_sockaddr_async(struct rpc_context *rpc)
|
|||
sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
rc = bind(rpc->fd, (struct sockaddr *)&ss,
|
||||
|
@ -719,6 +759,7 @@ rpc_set_sockaddr(struct rpc_context *rpc, const char *server, int port)
|
|||
sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
break;
|
||||
#if !defined(PS3_PPU) && !defined(PS2_EE)
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *)&rpc->s)->sin6_family = ai->ai_family;
|
||||
((struct sockaddr_in6 *)&rpc->s)->sin6_port = htons(port);
|
||||
|
@ -729,6 +770,7 @@ rpc_set_sockaddr(struct rpc_context *rpc, const char *server, int port)
|
|||
sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
freeaddrinfo(ai);
|
||||
|
||||
|
@ -795,6 +837,7 @@ rpc_disconnect(struct rpc_context *rpc, const char *error)
|
|||
rpc_error_all_pdus(rpc, error);
|
||||
}
|
||||
|
||||
maybe_call_connect_cb(rpc, RPC_STATUS_CANCEL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -850,6 +893,10 @@ rpc_reconnect_requeue(struct rpc_context *rpc)
|
|||
* in flight. Move them all over from the waitpdu queue back to the
|
||||
* out queue.
|
||||
*/
|
||||
printf("reconnect reset waitpdu queues\n");
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
for (i = 0; i < HASHES; i++) {
|
||||
struct rpc_queue *q = &rpc->waitpdu[i];
|
||||
for (pdu = q->head; pdu; pdu = next) {
|
||||
|
@ -861,6 +908,9 @@ rpc_reconnect_requeue(struct rpc_context *rpc)
|
|||
rpc_reset_queue(q);
|
||||
}
|
||||
rpc->waitpdu_len = 0;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
if (rpc->auto_reconnect < 0 || rpc->num_retries > 0) {
|
||||
rpc->num_retries--;
|
||||
|
@ -982,7 +1032,13 @@ rpc_queue_length(struct rpc_context *rpc)
|
|||
i++;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_lock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
i += rpc->waitpdu_len;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
|
||||
#endif /* HAVE_MULTITHREADING */
|
||||
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#endif/*WIN32*/
|
||||
|
|
|
@ -20,6 +20,7 @@ nfs-stamp : nfs.x
|
|||
|
||||
compile_rpc:
|
||||
cat nfs.x | head -29 >libnfs-raw-nfs.h
|
||||
rpcgen -h nfs.x | sed -e "s/#include <rpc\/rpc.h>/#include <nfsc\/libnfs-zdr.h>/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/#define _NFS_H_RPCGEN/#define _NFS_H_RPCGEN\n#include <nfsc\/libnfs-zdr.h>/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
|
||||
rpcgen -h nfs.x | sed -e "s/#include <rpc\/rpc.h>/#include <nfsc\/libnfs-zdr.h>/" -e "s/xdr/zdr/g" -e "s/XDR/ZDR/g" -e "s/#define _NFS_H_RPCGEN/#define _NFS_H_RPCGEN\n#include <nfsc\/libnfs-zdr.h>/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" | head -n -5 >> libnfs-raw-nfs.h
|
||||
cat libnfs-raw-nfs.h.extra >>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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2005,6 +2005,57 @@ extern uint32_t zdr_SETACL3res ();
|
|||
|
||||
#endif /* K&R C */
|
||||
|
||||
#include <nfsc/libnfs.h>
|
||||
|
||||
#if defined(WIN32) && defined(libnfs_EXPORTS)
|
||||
#define EXTERN __declspec( dllexport )
|
||||
#else
|
||||
#ifndef EXTERN
|
||||
#define EXTERN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
u_int ace_count;
|
||||
struct nfsacl_ace *ace;
|
||||
u_int default_ace_count;
|
||||
struct nfsacl_ace *default_ace;
|
||||
} fattr3_acl;
|
||||
|
||||
/*
|
||||
* NFSv3 ACL
|
||||
*/
|
||||
/*
|
||||
* Async nfs3 get acl
|
||||
* 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 fattr3_acl *
|
||||
* -errno : An error occured.
|
||||
* data is the error string.
|
||||
*/
|
||||
EXTERN int nfs3_getacl_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
||||
nfs_cb cb, void *private_data);
|
||||
|
||||
/*
|
||||
* Sync nfs3 get acl
|
||||
* Function returns
|
||||
* 0 : The operation was successful.
|
||||
* -errno : The command failed.
|
||||
*
|
||||
* If the command was successful, the returned data in nfs3acl must be freed
|
||||
* by calling nfs3_acl_free()
|
||||
*/
|
||||
EXTERN int nfs3_getacl(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
||||
fattr3_acl *nfs3acl);
|
||||
|
||||
EXTERN void nfs3_acl_free(fattr3_acl *nfs3acl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
#include <nfsc/libnfs.h>
|
||||
|
||||
#if defined(WIN32) && defined(libnfs_EXPORTS)
|
||||
#define EXTERN __declspec( dllexport )
|
||||
#else
|
||||
#ifndef EXTERN
|
||||
#define EXTERN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
u_int ace_count;
|
||||
struct nfsacl_ace *ace;
|
||||
u_int default_ace_count;
|
||||
struct nfsacl_ace *default_ace;
|
||||
} fattr3_acl;
|
||||
|
||||
/*
|
||||
* NFSv3 ACL
|
||||
*/
|
||||
/*
|
||||
* Async nfs3 get acl
|
||||
* 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 fattr3_acl *
|
||||
* -errno : An error occured.
|
||||
* data is the error string.
|
||||
*/
|
||||
EXTERN int nfs3_getacl_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
||||
nfs_cb cb, void *private_data);
|
||||
|
||||
/*
|
||||
* Sync nfs3 get acl
|
||||
* Function returns
|
||||
* 0 : The operation was successful.
|
||||
* -errno : The command failed.
|
||||
*
|
||||
* If the command was successful, the returned data in nfs3acl must be freed
|
||||
* by calling nfs3_acl_free()
|
||||
*/
|
||||
EXTERN int nfs3_getacl(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
||||
fattr3_acl *nfs3acl);
|
||||
|
||||
EXTERN void nfs3_acl_free(fattr3_acl *nfs3acl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_NFS_H_RPCGEN */
|
|
@ -15,6 +15,10 @@
|
|||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#else
|
||||
|
|
|
@ -96,3 +96,4 @@ int rpc_nfsacl_setacl_async(struct rpc_context *rpc, rpc_cb cb, struct SETACL3ar
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ nfs4-stamp : nfs4.x
|
|||
touch nfs4-stamp
|
||||
|
||||
compile_rpc:
|
||||
cat nfs4.x | head -29 >libnfs-raw-nfs4.h
|
||||
cat nfs4.x | head -16 >libnfs-raw-nfs4.h
|
||||
rpcgen -h nfs4.x | sed \
|
||||
-e "s/#include <rpc\/rpc.h>/#include <nfsc\/libnfs-zdr.h>/" \
|
||||
-e "s/xdr/zdr/g" \
|
||||
|
@ -28,8 +28,9 @@ compile_rpc:
|
|||
-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
|
||||
-e "s/bool_t/uint32_t/g" | head --lines=-5 >>libnfs-raw-nfs4.h
|
||||
cat libnfs-raw-nfs4.h.extra >>libnfs-raw-nfs4.h
|
||||
cat nfs4.x | head -16 >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" \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,49 @@
|
|||
#include <nfsc/libnfs.h>
|
||||
|
||||
#if defined(WIN32) && defined(libnfs_EXPORTS)
|
||||
#define EXTERN __declspec( dllexport )
|
||||
#else
|
||||
#ifndef EXTERN
|
||||
#define EXTERN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NFSv4 ACL
|
||||
*/
|
||||
/*
|
||||
* Async nfs4 get acl
|
||||
* 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 fattr4_acl *
|
||||
* -errno : An error occured.
|
||||
* data is the error string.
|
||||
*/
|
||||
EXTERN int nfs4_getacl_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
||||
nfs_cb cb, void *private_data);
|
||||
|
||||
/*
|
||||
* Sync nfs4 get acl
|
||||
* Function returns
|
||||
* 0 : The operation was successful.
|
||||
* -errno : The command failed.
|
||||
*
|
||||
* If the command was successful, the returned data in nfs4acl must be freed
|
||||
* by calling nfs4_acl_free()
|
||||
*/
|
||||
EXTERN int nfs4_getacl(struct nfs_context *nfs, struct nfsfh *nfsfh,
|
||||
fattr4_acl *nfs4acl);
|
||||
|
||||
EXTERN void nfs4_acl_free(fattr4_acl *nfs4acl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_NFS4_H_RPCGEN */
|
24
nfs4/nfs4.c
24
nfs4/nfs4.c
|
@ -16,6 +16,10 @@
|
|||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef PS2_EE
|
||||
#include "ps2_compat.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <win32/win32_compat.h>
|
||||
#else
|
||||
|
@ -202,14 +206,17 @@ rpc_nfs4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
|
|||
}
|
||||
|
||||
int
|
||||
rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
|
||||
struct COMPOUND4args *args, void *private_data)
|
||||
rpc_nfs4_compound_async2(struct rpc_context *rpc, rpc_cb cb,
|
||||
struct COMPOUND4args *args,
|
||||
void *private_data,
|
||||
size_t alloc_hint)
|
||||
{
|
||||
struct rpc_pdu *pdu;
|
||||
|
||||
pdu = rpc_allocate_pdu(rpc, NFS4_PROGRAM, NFS_V4, NFSPROC4_COMPOUND,
|
||||
pdu = rpc_allocate_pdu2(rpc, NFS4_PROGRAM, NFS_V4, NFSPROC4_COMPOUND,
|
||||
cb, private_data, (zdrproc_t)zdr_COMPOUND4res,
|
||||
sizeof(COMPOUND4res));
|
||||
sizeof(COMPOUND4res),
|
||||
alloc_hint);
|
||||
if (pdu == NULL) {
|
||||
rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for "
|
||||
"NFS4/COMPOUND call");
|
||||
|
@ -230,3 +237,12 @@ rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
|
||||
struct COMPOUND4args *args,
|
||||
void *private_data)
|
||||
{
|
||||
return rpc_nfs4_compound_async2(rpc, cb, args, private_data, 0);
|
||||
}
|
||||
|
|
586
nfs4/nfs4.x
586
nfs4/nfs4.x
|
@ -21,7 +21,7 @@
|
|||
const NFS4_FHSIZE = 128;
|
||||
const NFS4_VERIFIER_SIZE = 8;
|
||||
const NFS4_OPAQUE_LIMIT = 1024;
|
||||
|
||||
const NFS4_SESSIONID_SIZE = 16;
|
||||
/*
|
||||
* File types
|
||||
*/
|
||||
|
@ -107,7 +107,20 @@ enum nfsstat4 {
|
|||
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 */
|
||||
NFS4ERR_CB_PATH_DOWN = 10048,/* callback path down */
|
||||
NFS4ERR_BADIOMODE = 10049,
|
||||
NFS4ERR_BADLAYOUT = 10050,
|
||||
NFS4ERR_BAD_SESSION_DIGEST = 10051,
|
||||
NFS4ERR_BADSESSION = 10052,
|
||||
NFS4ERR_BADSLOT = 10053,
|
||||
NFS4ERR_COMPLETE_ALREADY = 10054,
|
||||
NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
|
||||
NFS4ERR_DELEG_ALREADY_WANTED = 10056,
|
||||
NFS4ERR_BACK_CHAN_BUSY = 10057,
|
||||
NFS4ERR_LAYOUTTRYLATER = 10058,
|
||||
NFS4ERR_LAYOUTUNAVAILABLE = 10059,
|
||||
NFS4ERR_NOMATCHING_LAYOUT = 10060,
|
||||
NFS4ERR_RECALLCONFLICT = 10061
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -118,7 +131,9 @@ typedef uint64_t offset4;
|
|||
typedef uint32_t count4;
|
||||
typedef uint64_t length4;
|
||||
typedef uint64_t clientid4;
|
||||
typedef uint32_t sequenceid4;
|
||||
typedef uint32_t seqid4;
|
||||
typedef uint32_t slotid4;
|
||||
typedef opaque utf8string<>;
|
||||
typedef utf8string utf8str_cis;
|
||||
typedef utf8string utf8str_cs;
|
||||
|
@ -133,6 +148,38 @@ typedef uint32_t qop4;
|
|||
typedef uint32_t mode4;
|
||||
typedef uint64_t changeid4;
|
||||
typedef opaque verifier4[NFS4_VERIFIER_SIZE];
|
||||
typedef opaque sessionid4[NFS4_SESSIONID_SIZE];
|
||||
/*
|
||||
* Authsys_parms
|
||||
*/
|
||||
struct authsys_parms {
|
||||
unsigned int stamp;
|
||||
string machinename<255>;
|
||||
unsigned int uid;
|
||||
unsigned int gid;
|
||||
unsigned int gids<16>;
|
||||
};
|
||||
|
||||
const NFS4_DEVICEID4_SIZE = 16;
|
||||
|
||||
typedef opaque deviceid4[NFS4_DEVICEID4_SIZE];
|
||||
|
||||
enum layouttype4 {
|
||||
LAYOUT4_NFSV4_1_FILES = 0x1,
|
||||
LAYOUT4_OSD2_OBJECTS = 0x2,
|
||||
LAYOUT4_BLOCK_VOLUME = 0x3
|
||||
};
|
||||
|
||||
struct layoutupdate4 {
|
||||
layouttype4 lou_type;
|
||||
opaque lou_body<>;
|
||||
};
|
||||
|
||||
|
||||
struct device_addr4 {
|
||||
layouttype4 da_layout_type;
|
||||
opaque da_addr_body<>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Timeval
|
||||
|
@ -147,6 +194,24 @@ enum time_how4 {
|
|||
SET_TO_CLIENT_TIME4 = 1
|
||||
};
|
||||
|
||||
enum layoutiomode4 {
|
||||
LAYOUTIOMODE4_READ = 1,
|
||||
LAYOUTIOMODE4_RW = 2,
|
||||
LAYOUTIOMODE4_ANY = 3
|
||||
};
|
||||
|
||||
struct layout_content4 {
|
||||
layouttype4 loc_type;
|
||||
opaque loc_body<>;
|
||||
};
|
||||
|
||||
struct layout4 {
|
||||
offset4 lo_offset;
|
||||
length4 lo_length;
|
||||
layoutiomode4 lo_iomode;
|
||||
layout_content4 lo_content;
|
||||
};
|
||||
|
||||
union settime4 switch (time_how4 set_it) {
|
||||
case SET_TO_CLIENT_TIME4:
|
||||
nfstime4 time;
|
||||
|
@ -885,7 +950,10 @@ enum open_claim_type4 {
|
|||
CLAIM_NULL = 0,
|
||||
CLAIM_PREVIOUS = 1,
|
||||
CLAIM_DELEGATE_CUR = 2,
|
||||
CLAIM_DELEGATE_PREV = 3
|
||||
CLAIM_DELEGATE_PREV = 3,
|
||||
CLAIM_FH = 4, /* new to v4.1 */
|
||||
CLAIM_DELEG_CUR_FH = 5, /* new to v4.1 */
|
||||
CLAIM_DELEG_PREV_FH = 6 /* new to v4.1 */
|
||||
};
|
||||
|
||||
struct open_claim_delegate_cur4 {
|
||||
|
@ -1229,19 +1297,13 @@ struct SAVEFH4res {
|
|||
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,
|
||||
|
@ -1254,7 +1316,8 @@ struct rpcsec_gss_info {
|
|||
rpc_gss_svc_t service;
|
||||
};
|
||||
|
||||
/* RPCSEC_GSS has a value of '6' - See RFC 2203 */
|
||||
const RPCSEC_GSS = 6;
|
||||
|
||||
union secinfo4 switch (uint32_t flavor) {
|
||||
case RPCSEC_GSS:
|
||||
rpcsec_gss_info flavor_info;
|
||||
|
@ -1270,7 +1333,6 @@ union SECINFO4res switch (nfsstat4 status) {
|
|||
default:
|
||||
void;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SETATTR: Set attributes
|
||||
|
@ -1372,6 +1434,456 @@ struct RELEASE_LOCKOWNER4res {
|
|||
nfsstat4 status;
|
||||
};
|
||||
|
||||
/*
|
||||
* BACKCHANNEL_CTL
|
||||
*/
|
||||
/*
|
||||
typedef opaque gsshandle4_t<>;
|
||||
|
||||
struct gss_cb_handles4 {
|
||||
rpc_gss_svc_t gcbp_service; RFC 2203
|
||||
gsshandle4_t gcbp_handle_from_server;
|
||||
gsshandle4_t gcbp_handle_from_client;
|
||||
};
|
||||
*/
|
||||
|
||||
union callback_sec_parms4 switch (uint32_t cb_secflavor) {
|
||||
case AUTH_NONE:
|
||||
void;
|
||||
case AUTH_SYS:
|
||||
authsys_parms cbsp_sys_cred; /* RFC 1831 */
|
||||
/*
|
||||
* case RPCSEC_GSS:
|
||||
* gss_cb_handles4 cbsp_gss_handles;
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
struct BACKCHANNEL_CTL4args {
|
||||
uint32_t bca_cb_program;
|
||||
callback_sec_parms4 bca_sec_parms<>;
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
* CREATE_SESSION
|
||||
*/
|
||||
struct channel_attrs4 {
|
||||
count4 ca_headerpadsize;
|
||||
count4 ca_maxrequestsize;
|
||||
count4 ca_maxresponsesize;
|
||||
count4 ca_maxresponsesize_cached;
|
||||
count4 ca_maxoperations;
|
||||
count4 ca_maxrequests;
|
||||
uint32_t ca_rdma_ird<1>;
|
||||
};
|
||||
|
||||
const CREATE_SESSION4_FLAG_PERSIST = 0x00000001;
|
||||
const CREATE_SESSION4_FLAG_CONN_BACK_CHAN = 0x00000002;
|
||||
const CREATE_SESSION4_FLAG_CONN_RDMA = 0x00000004;
|
||||
|
||||
struct CREATE_SESSION4args {
|
||||
clientid4 csa_clientid;
|
||||
sequenceid4 csa_sequence;
|
||||
uint32_t csa_flags;
|
||||
channel_attrs4 csa_fore_chan_attrs;
|
||||
channel_attrs4 csa_back_chan_attrs;
|
||||
uint32_t csa_cb_program;
|
||||
callback_sec_parms4 csa_sec_parms<>;
|
||||
};
|
||||
|
||||
struct CREATE_SESSION4resok {
|
||||
sessionid4 csr_sessionid;
|
||||
sequenceid4 csr_sequence;
|
||||
uint32_t csr_flags;
|
||||
channel_attrs4 csr_fore_chan_attrs;
|
||||
channel_attrs4 csr_back_chan_attrs;
|
||||
};
|
||||
|
||||
union CREATE_SESSION4res switch (nfsstat4 csr_status) {
|
||||
case NFS4_OK:
|
||||
CREATE_SESSION4resok csr_resok4;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* DESTROY_SESSION
|
||||
*/
|
||||
struct DESTROY_SESSION4args {
|
||||
sessionid4 dsa_sessionid;
|
||||
};
|
||||
|
||||
struct DESTROY_SESSION4res {
|
||||
nfsstat4 dsr_status;
|
||||
};
|
||||
|
||||
/*
|
||||
* FREE_STATEID
|
||||
*/
|
||||
struct FREE_STATEID4args {
|
||||
stateid4 fsa_stateid;
|
||||
};
|
||||
|
||||
struct FREE_STATEID4res {
|
||||
nfsstat4 fsr_status;
|
||||
};
|
||||
|
||||
/*
|
||||
* GET_DIR_DELEGATION
|
||||
*/
|
||||
typedef nfstime4 attr_notice4;
|
||||
|
||||
struct GET_DIR_DELEGATION4args {
|
||||
bool gdda_signal_deleg_avail;
|
||||
bitmap4 gdda_notification_types;
|
||||
attr_notice4 gdda_child_attr_delay;
|
||||
attr_notice4 gdda_dir_attr_delay;
|
||||
bitmap4 gdda_child_attributes;
|
||||
bitmap4 gdda_dir_attributes;
|
||||
};
|
||||
|
||||
struct GET_DIR_DELEGATION4resok {
|
||||
verifier4 gddr_cookieverf;
|
||||
stateid4 gddr_stateid;
|
||||
bitmap4 gddr_notification;
|
||||
bitmap4 gddr_child_attributes;
|
||||
bitmap4 gddr_dir_attributes;
|
||||
};
|
||||
|
||||
enum gddrnf4_status {
|
||||
GDD4_OK = 0,
|
||||
GDD4_UNAVAIL = 1
|
||||
};
|
||||
|
||||
union GET_DIR_DELEGATION4res_non_fatal switch (gddrnf4_status gddrnf_status) {
|
||||
case GDD4_OK:
|
||||
GET_DIR_DELEGATION4resok gddrnf_resok4;
|
||||
case GDD4_UNAVAIL:
|
||||
bool gddrnf_will_signal_deleg_avail;
|
||||
};
|
||||
|
||||
union GET_DIR_DELEGATION4res switch (nfsstat4 gddr_status) {
|
||||
case NFS4_OK:
|
||||
GET_DIR_DELEGATION4res_non_fatal gddr_res_non_fatal4;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* GETDEVICEINFO
|
||||
*/
|
||||
struct GETDEVICEINFO4args {
|
||||
deviceid4 gdia_device_id;
|
||||
layouttype4 gdia_layout_type;
|
||||
count4 gdia_maxcount;
|
||||
bitmap4 gdia_notify_types;
|
||||
};
|
||||
|
||||
struct GETDEVICEINFO4resok {
|
||||
device_addr4 gdir_device_addr;
|
||||
bitmap4 gdir_notification;
|
||||
};
|
||||
|
||||
union GETDEVICEINFO4res switch (nfsstat4 gdir_status) {
|
||||
case NFS4_OK:
|
||||
GETDEVICEINFO4resok gdir_resok4;
|
||||
case NFS4ERR_TOOSMALL:
|
||||
count4 gdir_mincount;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* GETDEVICELIST
|
||||
*/
|
||||
struct GETDEVICELIST4args {
|
||||
layouttype4 gdla_layout_type;
|
||||
count4 gdla_maxdevices;
|
||||
nfs_cookie4 gdla_cookie;
|
||||
verifier4 gdla_cookieverf;
|
||||
};
|
||||
|
||||
struct GETDEVICELIST4resok {
|
||||
nfs_cookie4 gdlr_cookie;
|
||||
verifier4 gdlr_cookieverf;
|
||||
deviceid4 gdlr_deviceid_list<>;
|
||||
bool gdlr_eof;
|
||||
};
|
||||
|
||||
union GETDEVICELIST4res switch (nfsstat4 gdlr_status) {
|
||||
case NFS4_OK:
|
||||
GETDEVICELIST4resok gdlr_resok4;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* LAYOUTCOMMIT
|
||||
*/
|
||||
union newtime4 switch (bool nt_timechanged) {
|
||||
case TRUE:
|
||||
nfstime4 nt_time;
|
||||
case FALSE:
|
||||
void;
|
||||
};
|
||||
|
||||
union newoffset4 switch (bool no_newoffset) {
|
||||
case TRUE:
|
||||
offset4 no_offset;
|
||||
case FALSE:
|
||||
void;
|
||||
};
|
||||
|
||||
struct LAYOUTCOMMIT4args {
|
||||
offset4 loca_offset;
|
||||
length4 loca_length;
|
||||
bool loca_reclaim;
|
||||
stateid4 loca_stateid;
|
||||
newoffset4 loca_last_write_offset;
|
||||
newtime4 loca_time_modify;
|
||||
layoutupdate4 loca_layoutupdate;
|
||||
};
|
||||
|
||||
union newsize4 switch (bool ns_sizechanged) {
|
||||
case TRUE:
|
||||
length4 ns_size;
|
||||
case FALSE:
|
||||
void;
|
||||
};
|
||||
|
||||
struct LAYOUTCOMMIT4resok {
|
||||
newsize4 locr_newsize;
|
||||
};
|
||||
|
||||
union LAYOUTCOMMIT4res switch (nfsstat4 locr_status) {
|
||||
case NFS4_OK:
|
||||
LAYOUTCOMMIT4resok locr_resok4;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* LAYOUTGET
|
||||
*/
|
||||
struct LAYOUTGET4args {
|
||||
bool loga_signal_layout_avail;
|
||||
layouttype4 loga_layout_type;
|
||||
layoutiomode4 loga_iomode;
|
||||
offset4 loga_offset;
|
||||
length4 loga_length;
|
||||
length4 loga_minlength;
|
||||
stateid4 loga_stateid;
|
||||
count4 loga_maxcount;
|
||||
};
|
||||
|
||||
struct LAYOUTGET4resok {
|
||||
bool logr_return_on_close;
|
||||
stateid4 logr_stateid;
|
||||
layout4 logr_layout<>;
|
||||
};
|
||||
|
||||
union LAYOUTGET4res switch (nfsstat4 logr_status) {
|
||||
case NFS4_OK:
|
||||
LAYOUTGET4resok logr_resok4;
|
||||
case NFS4ERR_LAYOUTTRYLATER:
|
||||
bool logr_will_signal_layout_avail;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* LAYOUTRETURN
|
||||
*/
|
||||
const LAYOUT4_RET_REC_FILE = 1;
|
||||
const LAYOUT4_RET_REC_FSID = 2;
|
||||
const LAYOUT4_RET_REC_ALL = 3;
|
||||
|
||||
enum layoutreturn_type4 {
|
||||
LAYOUTRETURN4_FILE = LAYOUT4_RET_REC_FILE,
|
||||
LAYOUTRETURN4_FSID = LAYOUT4_RET_REC_FSID,
|
||||
LAYOUTRETURN4_ALL = LAYOUT4_RET_REC_ALL
|
||||
};
|
||||
|
||||
struct layoutreturn_file4 {
|
||||
offset4 lrf_offset;
|
||||
length4 lrf_length;
|
||||
stateid4 lrf_stateid;
|
||||
opaque lrf_body<>;
|
||||
};
|
||||
|
||||
union layoutreturn4 switch(layoutreturn_type4 lr_returntype) {
|
||||
case LAYOUTRETURN4_FILE:
|
||||
layoutreturn_file4 lr_layout;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
struct LAYOUTRETURN4args {
|
||||
bool lora_reclaim;
|
||||
layouttype4 lora_layout_type;
|
||||
layoutiomode4 lora_iomode;
|
||||
layoutreturn4 lora_layoutreturn;
|
||||
};
|
||||
|
||||
union layoutreturn_stateid switch (bool lrs_present) {
|
||||
case TRUE:
|
||||
stateid4 lrs_stateid;
|
||||
case FALSE:
|
||||
void;
|
||||
};
|
||||
|
||||
union LAYOUTRETURN4res switch (nfsstat4 lorr_status) {
|
||||
case NFS4_OK:
|
||||
layoutreturn_stateid lorr_stateid;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* SECINFO_NO_NAME
|
||||
*/
|
||||
enum secinfo_style4 {
|
||||
SECINFO_STYLE4_CURRENT_FH = 0,
|
||||
SECINFO_STYLE4_PARENT = 1
|
||||
};
|
||||
|
||||
typedef secinfo_style4 SECINFO_NO_NAME4args;
|
||||
|
||||
typedef SECINFO4res SECINFO_NO_NAME4res;
|
||||
|
||||
/*
|
||||
* SEQUENCE
|
||||
*/
|
||||
struct SEQUENCE4args {
|
||||
sessionid4 sa_sessionid;
|
||||
sequenceid4 sa_sequenceid;
|
||||
slotid4 sa_slotid;
|
||||
slotid4 sa_highest_slotid;
|
||||
bool sa_cachethis;
|
||||
};
|
||||
|
||||
const SEQ4_STATUS_CB_PATH_DOWN = 0x00000001;
|
||||
const SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING = 0x00000002;
|
||||
const SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED = 0x00000004;
|
||||
const SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED = 0x00000008;
|
||||
const SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED = 0x00000010;
|
||||
const SEQ4_STATUS_ADMIN_STATE_REVOKED = 0x00000020;
|
||||
const SEQ4_STATUS_RECALLABLE_STATE_REVOKED = 0x00000040;
|
||||
const SEQ4_STATUS_LEASE_MOVED = 0x00000080;
|
||||
const SEQ4_STATUS_RESTART_RECLAIM_NEEDED = 0x00000100;
|
||||
const SEQ4_STATUS_CB_PATH_DOWN_SESSION = 0x00000200;
|
||||
const SEQ4_STATUS_BACKCHANNEL_FAULT = 0x00000400;
|
||||
const SEQ4_STATUS_DEVID_CHANGED = 0x00000800;
|
||||
const SEQ4_STATUS_DEVID_DELETED = 0x00001000;
|
||||
|
||||
struct SEQUENCE4resok {
|
||||
sessionid4 sr_sessionid;
|
||||
sequenceid4 sr_sequenceid;
|
||||
slotid4 sr_slotid;
|
||||
slotid4 sr_highest_slotid;
|
||||
slotid4 sr_target_highest_slotid;
|
||||
uint32_t sr_status_flags;
|
||||
};
|
||||
|
||||
union SEQUENCE4res switch (nfsstat4 sr_status) {
|
||||
case NFS4_OK:
|
||||
SEQUENCE4resok sr_resok4;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* SET_SSV
|
||||
*/
|
||||
struct ssa_digest_input4 {
|
||||
SEQUENCE4args sdi_seqargs;
|
||||
};
|
||||
|
||||
struct SET_SSV4args {
|
||||
opaque ssa_ssv<>;
|
||||
opaque ssa_digest<>;
|
||||
};
|
||||
|
||||
struct ssr_digest_input4 {
|
||||
SEQUENCE4res sdi_seqres;
|
||||
};
|
||||
|
||||
struct SET_SSV4resok {
|
||||
opaque ssr_digest<>;
|
||||
};
|
||||
|
||||
union SET_SSV4res switch (nfsstat4 ssr_status) {
|
||||
case NFS4_OK:
|
||||
SET_SSV4resok ssr_resok4;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* TEST_STATEID
|
||||
*/
|
||||
struct TEST_STATEID4args {
|
||||
stateid4 ts_stateids<>;
|
||||
};
|
||||
|
||||
struct TEST_STATEID4resok {
|
||||
nfsstat4 tsr_status_codes<>;
|
||||
};
|
||||
|
||||
union TEST_STATEID4res switch (nfsstat4 tsr_status) {
|
||||
case NFS4_OK:
|
||||
TEST_STATEID4resok tsr_resok4;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* WANT_DELEGATION
|
||||
*/
|
||||
union deleg_claim4 switch (open_claim_type4 dc_claim) {
|
||||
case CLAIM_FH:
|
||||
void;
|
||||
case CLAIM_DELEG_PREV_FH:
|
||||
void;
|
||||
case CLAIM_PREVIOUS:
|
||||
open_delegation_type4 dc_delegate_type;
|
||||
};
|
||||
|
||||
struct WANT_DELEGATION4args {
|
||||
uint32_t wda_want;
|
||||
deleg_claim4 wda_claim;
|
||||
};
|
||||
|
||||
union WANT_DELEGATION4res switch (nfsstat4 wdr_status) {
|
||||
case NFS4_OK:
|
||||
open_delegation4 wdr_resok4;
|
||||
default:
|
||||
void;
|
||||
};
|
||||
|
||||
/*
|
||||
* DESTROY_CLIENTID
|
||||
*/
|
||||
struct DESTROY_CLIENTID4args {
|
||||
clientid4 dca_clientid;
|
||||
};
|
||||
|
||||
struct DESTROY_CLIENTID4res {
|
||||
nfsstat4 dcr_status;
|
||||
};
|
||||
|
||||
/*
|
||||
* RECLAIM_COMPLETE
|
||||
*/
|
||||
struct RECLAIM_COMPLETE4args {
|
||||
bool rca_one_fs;
|
||||
};
|
||||
|
||||
struct RECLAIM_COMPLETE4res {
|
||||
nfsstat4 rcr_status;
|
||||
};
|
||||
|
||||
/*
|
||||
* ILLEGAL: Response for illegal operation numbers
|
||||
*/
|
||||
|
@ -1421,6 +1933,22 @@ enum nfs_opnum4 {
|
|||
OP_VERIFY = 37,
|
||||
OP_WRITE = 38,
|
||||
OP_RELEASE_LOCKOWNER = 39,
|
||||
OP_CREATE_SESSION = 43,
|
||||
OP_DESTROY_SESSION = 44,
|
||||
OP_FREE_STATEID = 45,
|
||||
OP_GET_DIR_DELEGATION = 46,
|
||||
OP_GETDEVICEINFO = 47,
|
||||
OP_GETDEVICELIST = 48,
|
||||
OP_LAYOUTCOMMIT = 49,
|
||||
OP_LAYOUTGET = 50,
|
||||
OP_LAYOUTRETURN = 51,
|
||||
OP_SECINFO_NO_NAME = 52,
|
||||
OP_SEQUENCE = 53,
|
||||
OP_SET_SSV = 54,
|
||||
OP_TEST_STATEID = 55,
|
||||
OP_WANT_DELEGATION = 56,
|
||||
OP_DESTROY_CLIENTID = 57,
|
||||
OP_RECLAIM_COMPLETE = 58,
|
||||
OP_ILLEGAL = 10044
|
||||
};
|
||||
|
||||
|
@ -1455,9 +1983,7 @@ union nfs_argop4 switch (nfs_opnum4 argop) {
|
|||
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
|
||||
|
@ -1466,6 +1992,22 @@ union nfs_argop4 switch (nfs_opnum4 argop) {
|
|||
case OP_WRITE: WRITE4args opwrite;
|
||||
case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4args
|
||||
oprelease_lockowner;
|
||||
case OP_CREATE_SESSION: CREATE_SESSION4args opcreatesession;
|
||||
case OP_DESTROY_SESSION: DESTROY_SESSION4args opdestroysession;
|
||||
case OP_FREE_STATEID: FREE_STATEID4args opfreestateid;
|
||||
case OP_GET_DIR_DELEGATION: GET_DIR_DELEGATION4args opgetdirdelegation;
|
||||
case OP_GETDEVICEINFO: GETDEVICEINFO4args opgetdeviceinfo;
|
||||
case OP_GETDEVICELIST: GETDEVICELIST4args opgetdevicelist;
|
||||
case OP_LAYOUTCOMMIT: LAYOUTCOMMIT4args oplayoutcommit;
|
||||
case OP_LAYOUTGET: LAYOUTGET4args oplayoutget;
|
||||
case OP_LAYOUTRETURN: LAYOUTRETURN4args oplayoutreturn;
|
||||
case OP_SECINFO_NO_NAME: SECINFO_NO_NAME4args opsecinfononame;
|
||||
case OP_SEQUENCE: SEQUENCE4args opsequence;
|
||||
case OP_SET_SSV: SET_SSV4args opsetssv;
|
||||
case OP_TEST_STATEID: TEST_STATEID4args opteststateid;
|
||||
case OP_WANT_DELEGATION: WANT_DELEGATION4args opwantdelegation;
|
||||
case OP_DESTROY_CLIENTID: DESTROY_CLIENTID4args opdestroyclientid;
|
||||
case OP_RECLAIM_COMPLETE: RECLAIM_COMPLETE4args opreclaimcomplete;
|
||||
case OP_ILLEGAL: void;
|
||||
};
|
||||
|
||||
|
@ -1500,9 +2042,7 @@ union nfs_resop4 switch (nfs_opnum4 resop){
|
|||
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
|
||||
|
@ -1511,6 +2051,22 @@ union nfs_resop4 switch (nfs_opnum4 resop){
|
|||
case OP_WRITE: WRITE4res opwrite;
|
||||
case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4res
|
||||
oprelease_lockowner;
|
||||
case OP_CREATE_SESSION: CREATE_SESSION4res opcreatesession;
|
||||
case OP_DESTROY_SESSION: DESTROY_SESSION4res opdestroysession;
|
||||
case OP_FREE_STATEID: FREE_STATEID4res opfreestateid;
|
||||
case OP_GET_DIR_DELEGATION: GET_DIR_DELEGATION4res opgetdirdelegation;
|
||||
case OP_GETDEVICEINFO: GETDEVICEINFO4res opgetdeviceinfo;
|
||||
case OP_GETDEVICELIST: GETDEVICELIST4res opgetdevicelist;
|
||||
case OP_LAYOUTCOMMIT: LAYOUTCOMMIT4res oplayoutcommit;
|
||||
case OP_LAYOUTGET: LAYOUTGET4res oplayoutget;
|
||||
case OP_LAYOUTRETURN: LAYOUTRETURN4res oplayoutreturn;
|
||||
case OP_SECINFO_NO_NAME: SECINFO_NO_NAME4res opsecinfononame;
|
||||
case OP_SEQUENCE: SEQUENCE4res opsequence;
|
||||
case OP_SET_SSV: SET_SSV4res opsetssv;
|
||||
case OP_TEST_STATEID: TEST_STATEID4res opteststateid;
|
||||
case OP_WANT_DELEGATION: WANT_DELEGATION4res opwantdelegation;
|
||||
case OP_DESTROY_CLIENTID: DESTROY_CLIENTID4res opdestroyclientid;
|
||||
case OP_RECLAIM_COMPLETE: RECLAIM_COMPLETE4res opreclaimcomplete;
|
||||
case OP_ILLEGAL: ILLEGAL4res opillegal;
|
||||
};
|
||||
|
||||
|
|
|
@ -113,6 +113,16 @@ Utility programs for LibNFS
|
|||
%{_mandir}/man1/nfs-ls.1.gz
|
||||
|
||||
%changelog
|
||||
* Tue Feb 1 2022 : Version 5.0.1
|
||||
- Fix non-pthread build
|
||||
* Fri Jan 28 2022 : Version 5.0.0
|
||||
- Multithread support for Linux and Windows
|
||||
- Fix NFS4 behavior of chmod/chown/utimes
|
||||
- Add marshalling / unmarshalling of various NFSv4.1 structures (but not 4.1 support)
|
||||
- PS3 support
|
||||
- PS2 EE support
|
||||
- Support escaped characters in the URL
|
||||
- Fix MINGW build
|
||||
* Wed Feb 13 2019 : Version 4.0.0
|
||||
- Fix the versioning in makerpms.sh
|
||||
- Fix some compile issues in the test programs.
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
EE_CFLAGS = -DPS2_EE \
|
||||
-D_U_=/**/ -I../include -I../include/nfsc \
|
||||
-I../mount -I../nfs -I../nfs4 -I../portmap
|
||||
|
||||
EE_LIB = libnfs.a
|
||||
EE_INCS =
|
||||
EE_OBJS = ../lib/init.o ../lib/pdu.o ../lib/socket.o \
|
||||
../lib/nfs_v3.o ../lib/nfs_v4.o \
|
||||
../lib/libnfs.o ../lib/libnfs-sync.o ../lib/libnfs-zdr.o \
|
||||
../mount/mount.o ../mount/libnfs-raw-mount.o \
|
||||
../portmap/portmap.o ../portmap/libnfs-raw-portmap.o \
|
||||
../nfs/nfs.o ../nfs/libnfs-raw-nfs.o \
|
||||
../nfs4/nfs4.o ../nfs4/libnfs-raw-nfs4.o
|
||||
|
||||
all: $(EE_LIB) $(EE_OBJS)
|
||||
|
||||
install: all
|
||||
ifeq ($(PS2SDK),)
|
||||
@echo "$PS2SDK is not set. Can not install libnfs."
|
||||
@exit 1
|
||||
endif
|
||||
@echo Copying...
|
||||
@[ -d $(PS2SDK)/ee/include/nfsc ] || mkdir -p $(PS2SDK)/ee/include/nfsc
|
||||
@cp -frv ../include/nfsc/*.h $(PS2SDK)/ee/include/nfsc
|
||||
@cp -frv ../mount/*.h $(PS2SDK)/ee/include/nfsc
|
||||
@cp -frv ../portmap/*.h $(PS2SDK)/ee/include/nfsc
|
||||
@cp -frv ../nfs/*.h $(PS2SDK)/ee/include/nfsc
|
||||
@cp -frv ../nfs4/*.h $(PS2SDK)/ee/include/nfsc
|
||||
@cp -frv *.a $(PS2SDK)/ee/lib
|
||||
@echo Done!
|
||||
|
||||
clean:
|
||||
rm -rf *.a $(EE_OBJS)
|
||||
|
||||
reset:
|
||||
ps2client reset
|
||||
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
include $(PS2SDK)/samples/Makefile.eeglobal
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
Copyright (C) 2021 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PS2_CONFIG_H__
|
||||
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_MEMORY_H 1
|
||||
#define HAVE_NETDB_H 1
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
#define HAVE_SOCKADDR_LEN 1
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_STDLIB_H 1
|
||||
#define HAVE_STRINGS_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
/* #define HAVE_SYS_SOCKET_H */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_UTIME_H 1
|
||||
|
||||
#endif /* __PS2_CONFIG_H__ */
|
|
@ -0,0 +1,86 @@
|
|||
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
Copyright (C) 2021 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef PS2_EE
|
||||
|
||||
#define NEED_READV
|
||||
#define NEED_WRITEV
|
||||
#define NEED_POLL
|
||||
#define NEED_BE64TOH
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int getaddrinfo(const char *node, const char*service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
struct hostent *host;
|
||||
int i, ip[4];
|
||||
|
||||
sin = malloc(sizeof(struct sockaddr_in));
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_family=AF_INET;
|
||||
|
||||
/* Some error checking would be nice */
|
||||
if (sscanf(node, "%d.%d.%d.%d", ip, ip+1, ip+2, ip+3) == 4) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
((char *)&sin->sin_addr.s_addr)[i] = ip[i];
|
||||
}
|
||||
} else {
|
||||
host = gethostbyname(node);
|
||||
if (host == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (host->h_addrtype != AF_INET) {
|
||||
return -2;
|
||||
}
|
||||
memcpy(&sin->sin_addr.s_addr, host->h_addr, 4);
|
||||
}
|
||||
|
||||
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 freeaddrinfo(struct addrinfo *res)
|
||||
{
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
}
|
||||
|
||||
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
|
||||
char *host, socklen_t hostlen,
|
||||
char *serv, socklen_t servlen, int flags)
|
||||
{
|
||||
/* not implemented yet */
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* PS2_EE */
|
|
@ -0,0 +1,104 @@
|
|||
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
Copyright (C) 2021 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PS2_COMPAT_H_
|
||||
#define _PS2_COMPAT_H_
|
||||
|
||||
#ifdef PS2_EE
|
||||
|
||||
#define NO_SRV_AUTOSCAN
|
||||
#define IPPORT_RESERVED 1024
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/utime.h>
|
||||
#include <ps2ip.h>
|
||||
|
||||
typedef unsigned long int fsfilcnt_t;
|
||||
|
||||
#define getservbyport(a,b) NULL
|
||||
#define major(a) 0
|
||||
#define minor(a) 0
|
||||
#define O_NOFOLLOW 0
|
||||
#define X_OK 1
|
||||
#define W_OK 2
|
||||
#define R_OK 4
|
||||
|
||||
struct statvfs {
|
||||
unsigned long int f_bsize;
|
||||
unsigned long int f_frsize;
|
||||
unsigned long int f_blocks;
|
||||
unsigned long int f_bfree;
|
||||
unsigned long int f_bavail;
|
||||
unsigned long int f_files;
|
||||
unsigned long int f_ffree;
|
||||
unsigned long int f_favail;
|
||||
unsigned long int f_fsid;
|
||||
unsigned long int f_flag;
|
||||
unsigned long int f_namemax;
|
||||
};
|
||||
|
||||
#define getpid() 0
|
||||
#define getuid() 0
|
||||
#define getgid() 0
|
||||
|
||||
#define write(a,b,c) lwip_write(a,b,c)
|
||||
#define read(a,b,c) lwip_read(a,b,c)
|
||||
#define gethostbyname(a) lwip_gethostbyname(a)
|
||||
#define close(a) lwip_close(a)
|
||||
|
||||
#define getlogin_r(a,b) ENXIO
|
||||
|
||||
#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 */
|
||||
|
||||
struct pollfd {
|
||||
int fd;
|
||||
short events;
|
||||
short revents;
|
||||
};
|
||||
|
||||
int poll(struct pollfd *fds, unsigned int nfds, int timo);
|
||||
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
|
||||
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
|
||||
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
|
||||
|
||||
int getaddrinfo(const char *node, const char*service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res);
|
||||
void freeaddrinfo(struct addrinfo *res);
|
||||
|
||||
long long int be64toh(long long int x);
|
||||
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
#define EAI_AGAIN EAGAIN
|
||||
|
||||
/* just pretend they are the same so we compile */
|
||||
#define sockaddr_in6 sockaddr_in
|
||||
|
||||
#endif /* PS2_EE */
|
||||
|
||||
#endif /* _PS2_COMPAT_H_ */
|
|
@ -0,0 +1,103 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(PSL1GHT)),)
|
||||
$(error "Please set PSL1GHT in your environment. export PSL1GHT=<path>")
|
||||
endif
|
||||
|
||||
include $(PSL1GHT)/ppu_rules
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(PLATFORM)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export BASEDIR := $(CURDIR)
|
||||
export DEPS := $(BASEDIR)/deps
|
||||
export LIBS := $(BASEDIR)/lib
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export LIBDIR := $(LIBS)/$(PLATFORM)
|
||||
export DEPSDIR := $(DEPS)/$(PLATFORM)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
TARGET := libnfs
|
||||
BUILD := build-ppu
|
||||
SOURCE := lib mount portmap nfs nfs4 nsm rquota nlm ps3_ppu
|
||||
INCLUDE := include include/nfsc ps3_ppu nfs nfs4 mount portmap
|
||||
DATA := data
|
||||
LIBS :=
|
||||
|
||||
MACHDEP := -DPS3_PPU=1 -DHAVE_CONFIG_H -D_U_=" "
|
||||
|
||||
CFLAGS += -O2 -Wall -mcpu=cell $(MACHDEP) -fno-strict-aliasing $(INCLUDES)
|
||||
|
||||
LD := ppu-ld
|
||||
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export VPATH := $(foreach dir,$(SOURCE),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
export BUILDDIR := $(CURDIR)/$(BUILD)
|
||||
export DEPSDIR := $(BUILDDIR)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CXXFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.S)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bin)))
|
||||
|
||||
|
||||
export OFILES := $(CFILES:.c=.o) \
|
||||
$(CXXFILES:.cpp=.o) \
|
||||
$(SFILES:.S=.o) \
|
||||
$(BINFILES:.bin=.bin.o)
|
||||
|
||||
export BINFILES := $(BINFILES:.bin=.bin.h)
|
||||
|
||||
export INCLUDES = $(foreach dir,$(INCLUDE),-I$(CURDIR)/$(dir)) \
|
||||
-I$(CURDIR)/$(BUILD) -I$(PSL1GHT)/ppu/include -I$(PORTLIBS)/include
|
||||
|
||||
.PHONY: $(BUILD) install clean
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/ps3_ppu/Makefile.PS3_PPU
|
||||
|
||||
install: $(BUILD)
|
||||
@echo Copying...
|
||||
@[ -d $(PORTLIBS)/include/nfsc ] || mkdir -p $(PORTLIBS)/include/nfsc
|
||||
@cp -frv include/nfsc/libnfs.h $(PORTLIBS)/include/nfsc
|
||||
@cp -frv include/nfsc/libnfs-raw.h $(PORTLIBS)/include/nfsc
|
||||
@cp -frv include/nfsc/libnfs-zdr.h $(PORTLIBS)/include/nfsc
|
||||
@cp -frv mount/libnfs-raw-mount.h $(PORTLIBS)/include/nfsc
|
||||
@cp -frv nlm/libnfs-raw-nlm.h $(PORTLIBS)/include/nfsc
|
||||
@cp -frv nfs/libnfs-raw-nfs.h $(PORTLIBS)/include/nfsc
|
||||
@cp -frv portmap/libnfs-raw-portmap.h $(PORTLIBS)/include/nfsc
|
||||
@cp -frv rquota/libnfs-raw-rquota.h $(PORTLIBS)/include/nfsc
|
||||
@cp -frv *.a $(PORTLIBS)/lib
|
||||
@echo Done!
|
||||
|
||||
clean:
|
||||
@echo Clean...
|
||||
@rm -rf $(BUILD) $(OUTPUT).elf $(OUTPUT).self $(OUTPUT).a
|
||||
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
$(OUTPUT).a: $(OFILES)
|
||||
$(OFILES): $(BINFILES)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
endif
|
|
@ -0,0 +1,49 @@
|
|||
/* config.h. Generated from config.h.in by configure. */
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#define HAVE_NETDB_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Whether sockaddr struct has sa_len */
|
||||
#define HAVE_SOCKADDR_LEN 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the <utime.h> header file. */
|
||||
#define HAVE_UTIME_H 1
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
Copyright (C) 2013 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "ps3_compat.h"
|
||||
|
||||
int nfs_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));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfs_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 nfs_freeaddrinfo(struct addrinfo *res)
|
||||
{
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Copyright (C) 2020 by Damian Parrino <www.bucanero.com.ar>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PS3_COMPAT_H
|
||||
#define PS3_COMPAT_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <netdb.h>
|
||||
#include <net/socket.h>
|
||||
#include <net/poll.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define getnameinfo nfs_getnameinfo
|
||||
#define getaddrinfo nfs_getaddrinfo
|
||||
#define freeaddrinfo nfs_freeaddrinfo
|
||||
|
||||
int nfs_getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||
char *host, size_t hostlen,
|
||||
char *serv, size_t servlen, int flags);
|
||||
int nfs_getaddrinfo(const char *node, const char*service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res);
|
||||
void nfs_freeaddrinfo(struct addrinfo *res);
|
||||
|
||||
#define IFNAMSIZ 16
|
||||
|
||||
/* just pretend they are the same so we compile */
|
||||
#define sockaddr_in6 sockaddr_in
|
||||
|
||||
#define IPPORT_RESERVED 1024
|
||||
#define MSG_NOSIGNAL 0x20000
|
||||
#define O_NOFOLLOW 0400000
|
||||
#define MINORBITS 20
|
||||
#define MINORMASK ((1U << MINORBITS) - 1)
|
||||
|
||||
#define major(dev) ((unsigned int) ((dev) >> MINORBITS))
|
||||
#define minor(dev) ((unsigned int) ((dev) & MINORMASK))
|
||||
|
||||
#define IFF_UP 0x1 /* interface is up */
|
||||
#define IFF_BROADCAST 0x2 /* broadcast address valid */
|
||||
#define IFF_DEBUG 0x4 /* turn on debugging */
|
||||
#define IFF_LOOPBACK 0x8 /* is a loopback net */
|
||||
|
||||
|
||||
struct ifmap {
|
||||
unsigned long mem_start;
|
||||
unsigned long mem_end;
|
||||
unsigned short base_addr;
|
||||
unsigned char irq;
|
||||
unsigned char dma;
|
||||
unsigned char port;
|
||||
/* 3 bytes spare */
|
||||
};
|
||||
|
||||
struct ifreq {
|
||||
char ifr_name[IFNAMSIZ]; /* Interface name */
|
||||
union {
|
||||
struct sockaddr ifr_addr;
|
||||
struct sockaddr ifr_dstaddr;
|
||||
struct sockaddr ifr_broadaddr;
|
||||
struct sockaddr ifr_netmask;
|
||||
struct sockaddr ifr_hwaddr;
|
||||
short ifr_flags;
|
||||
int ifr_ifindex;
|
||||
int ifr_metric;
|
||||
int ifr_mtu;
|
||||
struct ifmap ifr_map;
|
||||
char ifr_slave[IFNAMSIZ];
|
||||
char ifr_newname[IFNAMSIZ];
|
||||
char *ifr_data;
|
||||
};
|
||||
};
|
||||
|
||||
struct ifconf {
|
||||
int ifc_len; /* size of buffer */
|
||||
union {
|
||||
char *ifc_buf; /* buffer address */
|
||||
struct ifreq *ifc_req; /* array of structures */
|
||||
};
|
||||
};
|
||||
|
||||
typedef uint32_t fsblkcnt_t;
|
||||
typedef uint32_t fsfilcnt_t;
|
||||
|
||||
struct statvfs {
|
||||
unsigned long f_bsize;
|
||||
unsigned long f_frsize;
|
||||
fsblkcnt_t f_blocks;
|
||||
fsblkcnt_t f_bfree;
|
||||
fsblkcnt_t f_bavail;
|
||||
fsfilcnt_t f_files;
|
||||
fsfilcnt_t f_ffree;
|
||||
fsfilcnt_t f_favail;
|
||||
unsigned long f_fsid;
|
||||
unsigned long f_flag;
|
||||
unsigned long f_namemax;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
find_library(DL_LIBRARY dl)
|
||||
|
||||
set(SOURCES prog_access
|
||||
set(TEST_PROGS prog_access
|
||||
prog_access2
|
||||
prog_chmod
|
||||
prog_chown
|
||||
|
@ -30,16 +30,14 @@ set(SOURCES prog_access
|
|||
prog_unlink
|
||||
prog_utimes)
|
||||
|
||||
foreach(TARGET ${SOURCES})
|
||||
foreach(TARGET ${TEST_PROGS})
|
||||
add_executable(${TARGET} ${TARGET}.c)
|
||||
target_link_libraries(${TARGET} ${CORE_LIBRARIES})
|
||||
add_dependencies(${TARGET} nfs)
|
||||
target_link_libraries(${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)
|
||||
target_link_libraries(ld_timeout nfs ${DL_LIBRARY})
|
||||
|
||||
file(GLOB TESTS test_*.sh)
|
||||
|
||||
|
@ -51,5 +49,3 @@ foreach(TEST ${TESTS})
|
|||
COMMAND ${TEST}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endforeach()
|
||||
|
||||
add_definitions("-D_U_=__attribute__((unused))")
|
||||
|
|
|
@ -6,7 +6,7 @@ echo "NFSv${VERS} Basic chmod tests."
|
|||
|
||||
start_share
|
||||
|
||||
dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null
|
||||
dd if=/dev/zero of=${TESTDIR}/testfile count=1 bs=32768 2>/dev/null
|
||||
|
||||
echo -n "test chmod(0600) ... "
|
||||
./prog_chmod "${TESTURL}/?version=${VERS}" "." /testfile 0600 || failure
|
||||
|
@ -32,6 +32,31 @@ echo -n "Verifying the mode is 0755 ... "
|
|||
grep "nfs_mode:100755" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
mkdir ${TESTDIR}/testdir
|
||||
|
||||
echo -n "test chmod(0600) on dir ... "
|
||||
./prog_chmod "${TESTURL}/?version=${VERS}" "." /testdir 0600 || failure
|
||||
success
|
||||
|
||||
echo -n "Stat the dir ... "
|
||||
./prog_stat "${TESTURL}/?version=${VERS}" "." testdir > "${TESTDIR}/output" || failure
|
||||
success
|
||||
|
||||
echo -n "Verifying the mode is 0600 on dir ... "
|
||||
grep "nfs_mode:40600" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
echo -n "test chmod(0755) on dir ... "
|
||||
./prog_chmod "${TESTURL}/?version=${VERS}" "." /testdir 0755 || failure
|
||||
success
|
||||
|
||||
echo -n "Stat the dir ... "
|
||||
./prog_stat "${TESTURL}/?version={VERS}" "." testdir > "${TESTDIR}/output" || failure
|
||||
success
|
||||
|
||||
echo -n "Verifying the mode is 0755 on dir ... "
|
||||
grep "nfs_mode:40755" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
stop_share
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ echo "NFSv${VERS} Basic chown tests."
|
|||
|
||||
start_share
|
||||
|
||||
dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null
|
||||
dd if=/dev/zero of=${TESTDIR}/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
|
||||
|
@ -40,6 +40,39 @@ echo -n "Verifying the gid is 3000 ... "
|
|||
grep "nfs_gid:3000" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
mkdir ${TESTDIR}/testdir
|
||||
|
||||
echo -n "test chown(1000, 2000) on dir ... "
|
||||
./prog_chown "${TESTURL}/?uid=0&version=${VERS}" "." /testdir 1000 2000 || failure
|
||||
success
|
||||
|
||||
echo -n "Stat the dir ... "
|
||||
./prog_stat "${TESTURL}/?version=${VERS}" "." testdir > "${TESTDIR}/output" || failure
|
||||
success
|
||||
|
||||
echo -n "Verifying the uid is 1000 on dir ... "
|
||||
grep "nfs_uid:1000" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
echo -n "Verifying the gid is 2000 on dir ... "
|
||||
grep "nfs_gid:2000" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
echo -n "test chown(2000, 3000) on dir ... "
|
||||
./prog_chown "${TESTURL}/?uid=0&version=${VERS}" "." /testdir 2000 3000 || failure
|
||||
success
|
||||
|
||||
echo -n "Stat the dir ... "
|
||||
./prog_stat "${TESTURL}/?version=${VERS}" "." testdir > "${TESTDIR}/output" || failure
|
||||
success
|
||||
|
||||
echo -n "Verifying the uid is 2000 on dir ... "
|
||||
grep "nfs_uid:2000" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
echo -n "Verifying the gid is 3000 on dir ... "
|
||||
grep "nfs_gid:3000" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
stop_share
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ echo "NFSv${VERS} Basic nfs_utimes() tests."
|
|||
|
||||
start_share
|
||||
|
||||
dd if=/dev/zero of=testdata/testfile count=1 bs=32768 2>/dev/null
|
||||
dd if=/dev/zero of=${TESTDIR}/testfile count=1 bs=32768 2>/dev/null
|
||||
chmod 644 "${TESTDIR}/testfile"
|
||||
|
||||
echo -n "test nfs_utimes() ... "
|
||||
|
@ -25,6 +25,25 @@ echo -n "test nfs_mtime ... "
|
|||
grep "nfs_mtime:23456" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
mkdir ${TESTDIR}/testdir
|
||||
chmod 644 "${TESTDIR}/testdir"
|
||||
|
||||
echo -n "test nfs_utimes() on dir ... "
|
||||
./prog_utimes "${TESTURL}/?version=${VERS}" "." /testdir 12345 23456 || failure
|
||||
success
|
||||
|
||||
echo -n "test nfs_stat64() on dir ... "
|
||||
./prog_stat "${TESTURL}/?version=${VERS}" "." /testdir > "${TESTDIR}/output" || failure
|
||||
success
|
||||
|
||||
echo -n "test nfs_atime on dir ... "
|
||||
grep "nfs_atime:12345" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
echo -n "test nfs_mtime on dir ... "
|
||||
grep "nfs_mtime:23456" "${TESTDIR}/output" >/dev/null || failure
|
||||
success
|
||||
|
||||
|
||||
stop_share
|
||||
|
||||
|
|
|
@ -16,10 +16,6 @@ for IDX in `seq 1 100`; do
|
|||
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
|
||||
|
|
|
@ -6,6 +6,7 @@ echo "test we can build libnfs as an rpm"
|
|||
|
||||
[ -f "/etc/redhat-release" ] || {
|
||||
echo "SKIPPED. This is not a red-hat based system"
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo -n "try building rpm packages ... "
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
list(APPEND CORE_LIBRARIES ${SOCKET_LIBRARY})
|
||||
|
||||
set(SOURCES nfs-cat
|
||||
nfs-ls)
|
||||
set(UTILITIES nfs-cat nfs-ls)
|
||||
|
||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
|
||||
list(APPEND SOURCES nfs-cp)
|
||||
list(APPEND UTILITIES nfs-cp nfs-stat)
|
||||
endif()
|
||||
|
||||
foreach(TARGET ${SOURCES})
|
||||
foreach(TARGET ${UTILITIES})
|
||||
add_executable(${TARGET} ${TARGET}.c)
|
||||
target_link_libraries(${TARGET} ${CORE_LIBRARIES})
|
||||
add_dependencies(${TARGET} nfs)
|
||||
target_link_libraries(${TARGET} nfs nfs_mount)
|
||||
endforeach()
|
||||
|
||||
add_definitions("-D_U_=__attribute__((unused))")
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
bin_PROGRAMS = nfs-cat nfs-ls
|
||||
|
||||
if HAVE_PTHREAD
|
||||
LIBS += -lpthread
|
||||
endif
|
||||
|
||||
if !HAVE_WIN32
|
||||
bin_PROGRAMS += nfs-cp
|
||||
bin_PROGRAMS += nfs-cp nfs-stat
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
|
@ -16,3 +20,4 @@ COMMON_LIBS = ../lib/libnfs.la $(LIBSOCKET)
|
|||
nfs_cat_LDADD = $(COMMON_LIBS)
|
||||
nfs_ls_LDADD = $(COMMON_LIBS)
|
||||
nfs_cp_LDADD = $(COMMON_LIBS)
|
||||
nfs_stat_LDADD = $(COMMON_LIBS)
|
||||
|
|
|
@ -165,6 +165,9 @@ int main(int argc, char *argv[])
|
|||
struct client client;
|
||||
struct statvfs stvfs;
|
||||
struct nfs_url *url = NULL;
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
int mt_started = 0;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
|
||||
|
@ -232,7 +235,6 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
nfs_destroy_url(url);
|
||||
}
|
||||
|
||||
url = nfs_parse_url_dir(nfs, argv[argc - 1]);
|
||||
if (url == NULL) {
|
||||
fprintf(stderr, "%s\n", nfs_get_error(nfs));
|
||||
|
@ -248,6 +250,18 @@ int main(int argc, char *argv[])
|
|||
goto finished;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
/*
|
||||
* Before we can use multithreading we must initialize and
|
||||
* start the service thread.
|
||||
*/
|
||||
if (nfs_mt_service_thread_start(nfs)) {
|
||||
printf("failed to start service thread\n");
|
||||
exit(10);
|
||||
}
|
||||
mt_started = 1;
|
||||
#endif
|
||||
|
||||
process_dir(nfs, "", 16);
|
||||
|
||||
if (summary) {
|
||||
|
@ -261,6 +275,13 @@ int main(int argc, char *argv[])
|
|||
|
||||
ret = 0;
|
||||
finished:
|
||||
#ifdef HAVE_MULTITHREADING
|
||||
if (mt_started) {
|
||||
printf("closing service thread\n");
|
||||
nfs_mt_service_thread_stop(nfs);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret > 0) {
|
||||
print_usage();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2021
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <win32/win32_compat.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
WSADATA wsaData;
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#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-stat <file>\n");
|
||||
fprintf(stderr, "<file> stat an nfs file.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
char *get_file_type(int mode)
|
||||
{
|
||||
switch (mode & S_IFMT) {
|
||||
#ifndef WIN32
|
||||
case S_IFLNK: return "symbolic link";
|
||||
#endif
|
||||
case S_IFDIR: return "directory";
|
||||
case S_IFCHR: return "character device";
|
||||
case S_IFBLK: return "block device";
|
||||
default: return "regular file";
|
||||
}
|
||||
}
|
||||
|
||||
char uidbuf[16];
|
||||
char gidbuf[16];
|
||||
|
||||
#ifdef WIN32
|
||||
char *uid_to_name(int uid)
|
||||
{
|
||||
sprintf(uidbuf, "%d", uid);
|
||||
return uidbuf;
|
||||
}
|
||||
char *gid_to_name(int gid)
|
||||
{
|
||||
sprintf(gidbuf, "%d", gid);
|
||||
return gidbuf;
|
||||
}
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
char *uid_to_name(int uid)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
pw = getpwuid(uid);
|
||||
if (pw) {
|
||||
return pw->pw_name;
|
||||
} else {
|
||||
sprintf(uidbuf, "%d", uid);
|
||||
return uidbuf;
|
||||
}
|
||||
}
|
||||
char *gid_to_name(int gid)
|
||||
{
|
||||
struct group *gr;
|
||||
|
||||
gr = getgrgid(gid);
|
||||
if (gr) {
|
||||
return gr->gr_name;
|
||||
} else {
|
||||
sprintf(gidbuf, "%d", gid);
|
||||
return gidbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
char access_bits[11];
|
||||
char *get_access_bits(int mode)
|
||||
{
|
||||
switch (mode & S_IFMT) {
|
||||
#ifndef WIN32
|
||||
case S_IFLNK: access_bits[0] = 'l'; break;
|
||||
#endif
|
||||
case S_IFREG: access_bits[0] = '-'; break;
|
||||
case S_IFDIR: access_bits[0] = 'd'; break;
|
||||
case S_IFCHR: access_bits[0] = 'c'; break;
|
||||
case S_IFBLK: access_bits[0] = 'b'; break;
|
||||
default: access_bits[0] = '*';
|
||||
}
|
||||
access_bits[1] = "-r"[!!(mode & S_IRUSR)];
|
||||
access_bits[2] = "-w"[!!(mode & S_IWUSR)];
|
||||
access_bits[3] = "-xSs"[ !!(mode & S_IXUSR)
|
||||
#ifndef WIN32
|
||||
+ 2*!!(mode & S_ISUID)
|
||||
#endif
|
||||
];
|
||||
access_bits[4] = "-r"[!!(mode & S_IRGRP)];
|
||||
access_bits[5] = "-w"[!!(mode & S_IWGRP)];
|
||||
access_bits[6] = "-xSs"[ !!(mode & S_IXGRP)
|
||||
#ifndef WIN32
|
||||
+ 2*!!(mode & S_ISGID)
|
||||
#endif
|
||||
];
|
||||
access_bits[7] = "-r"[!!(mode & S_IROTH)];
|
||||
access_bits[8] = "-w"[!!(mode & S_IWOTH)];
|
||||
access_bits[9] = "-xTt"[ !!(mode & S_IXOTH)
|
||||
#ifndef WIN32
|
||||
+ 2*!!(mode & S_ISVTX)
|
||||
#endif
|
||||
];
|
||||
return access_bits;
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
printf(" File:%s\n", argv[1]);
|
||||
printf(" Size: %-16dBlocks: %-11d IO Block: %d %s\n",
|
||||
st.nfs_size, st.nfs_blocks, st.nfs_blksize,
|
||||
get_file_type(st.nfs_mode));
|
||||
printf("Inode:%-12dLinks %d\n",
|
||||
st.nfs_ino, st.nfs_nlink);
|
||||
printf("Access: (%04o/%s) Uid: ( %d/%s) Gid: ( %d/%s)\n",
|
||||
st.nfs_mode & 07777, get_access_bits(st.nfs_mode),
|
||||
st.nfs_uid, uid_to_name(st.nfs_uid),
|
||||
st.nfs_gid, gid_to_name(st.nfs_gid));
|
||||
|
||||
printf("Access: %s", ctime(&st.nfs_atime));
|
||||
printf("Modify: %s", ctime(&st.nfs_mtime));
|
||||
printf("Change: %s", ctime(&st.nfs_ctime));
|
||||
free_file_context(nf);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
set(SOURCES win32_compat.c)
|
||||
set(HEADERS win32_compat.h
|
||||
set(HEADERS ../include/win32/win32_compat.h
|
||||
win32_errnowrapper.h)
|
||||
|
||||
core_add_library(win32)
|
||||
|
|
|
@ -28,23 +28,27 @@
|
|||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
@ -111,7 +115,7 @@
|
|||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_U_=;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>HAVE_MULTITHREADING;WIN32;NDEBUG;_WINDOWS;_USRDLL;_U_=;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\nfs4;..\..\portmap;..\..\lib</AdditionalIncludeDirectories>
|
||||
<CompileAs>Default</CompileAs>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
|
@ -185,6 +189,7 @@
|
|||
<ClCompile Include="..\..\lib\libnfs-sync.c" />
|
||||
<ClCompile Include="..\..\lib\libnfs-zdr.c" />
|
||||
<ClCompile Include="..\..\lib\libnfs.c" />
|
||||
<ClCompile Include="..\..\lib\multithreading.c" />
|
||||
<ClCompile Include="..\..\lib\nfs_v3.c" />
|
||||
<ClCompile Include="..\..\lib\nfs_v4.c" />
|
||||
<ClCompile Include="..\..\lib\pdu.c" />
|
||||
|
@ -207,6 +212,7 @@
|
|||
<ClCompile Include="..\win32_compat.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\libnfs-multithreading.h" />
|
||||
<ClInclude Include="..\..\include\nfsc\libnfs-zdr.h" />
|
||||
<ClInclude Include="..\..\mount\libnfs-raw-mount.h" />
|
||||
<ClInclude Include="..\..\nfs\libnfs-raw-nfs.h" />
|
||||
|
|
|
@ -83,6 +83,9 @@
|
|||
<ClCompile Include="..\..\nsm\nsm.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\lib\multithreading.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\nfs\libnfs-raw-nfs.h">
|
||||
|
@ -115,6 +118,9 @@
|
|||
<ClInclude Include="..\..\nlm\libnfs-raw-nlm.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\libnfs-multithreading.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\lib\libnfs-win32.def" />
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<ProjectOutputs>
|
||||
<ProjectOutput>
|
||||
<FullPath>C:\Users\User\source\repos\sahlberg\libnfs\win32\libnfs\x64\Debug\libnfs.dll</FullPath>
|
||||
</ProjectOutput>
|
||||
</ProjectOutputs>
|
||||
<ContentFiles />
|
||||
<SatelliteDlls />
|
||||
<NonRecipeFileRefs />
|
||||
</Project>
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
|
@ -28,23 +28,27 @@
|
|||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
@ -68,7 +72,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<LibraryPath>..\libnfs\Debug;..\..\bin;$(LibraryPath)</LibraryPath>
|
||||
<LibraryPath>..\libnfs\x64\Debug;..\libnfs\Debug;..\..\bin;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
|
@ -104,7 +108,7 @@
|
|||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
|
@ -28,23 +28,27 @@
|
|||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
@ -68,7 +72,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<LibraryPath>..\libnfs\Debug;..\..\bin;$(LibraryPath)</LibraryPath>
|
||||
<LibraryPath>..\libnfs\x64\Debug;..\libnfs\Debug;..\..\bin;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
|
@ -104,7 +108,7 @@
|
|||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\portmap</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommandArguments>nfs://10.10.10.11/data/SNAP-4</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,54 @@
|
|||
#include <winver.h>
|
||||
|
||||
#define VER_FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
|
||||
#define VER_FILEVERSION_STR "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.0\0"
|
||||
|
||||
#define VER_PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
|
||||
#define VER_PRODUCTVERSION_STR "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.0\0"
|
||||
|
||||
#define VER_PRIVATEBUILD 0
|
||||
#define VER_PRERELEASE 0
|
||||
|
||||
#ifndef DEBUG
|
||||
#define VER_DEBUG 0
|
||||
#else
|
||||
#define VER_DEBUG VS_FF_DEBUG
|
||||
#endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG)
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "https://github.com/sahlberg/libnfs"
|
||||
VALUE "FileDescription", "LIBNFS is a client library for accessing NFS shares over a network."
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", "libnfs.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2019"
|
||||
VALUE "OriginalFilename", "libnfs.dll"
|
||||
VALUE "ProductName", "libnfs"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
END
|
||||
END
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
/* The following line should only be modified for localized versions. */
|
||||
/* It consists of any number of WORD,WORD pairs, with each pair */
|
||||
/* describing a language,codepage combination supported by the file. */
|
||||
/* */
|
||||
/* For example, a file might have values "0x409,1252" indicating that it */
|
||||
/* supports English language (0x409) in the Windows ANSI codepage (1252). */
|
||||
|
||||
VALUE "Translation", 0x409, 1252
|
||||
|
||||
END
|
||||
END
|
|
@ -50,7 +50,7 @@ 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;
|
||||
size_t strLen = strlen(src) + 1;
|
||||
#ifdef UNICODE
|
||||
wchar_t *srcNonConst = (wchar_t *)malloc(strLen*sizeof(wchar_t));
|
||||
memset(srcNonConst, 0, strLen);
|
||||
|
@ -132,7 +132,7 @@ int win32_poll(struct pollfd *fds, unsigned int nfds, int timo)
|
|||
{
|
||||
for (i = 0; i < nfds; ++i)
|
||||
{
|
||||
int fd = fds[i].fd;
|
||||
SOCKET 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))
|
||||
|
@ -197,6 +197,23 @@ int win32_gettimeofday(struct timeval *tv, struct timezone *tz)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
char* strndup(const char* s, size_t n)
|
||||
{
|
||||
size_t len;
|
||||
for(len=0; len<n && s[len]; len++);
|
||||
len += 1;
|
||||
if(!len)
|
||||
return 0;
|
||||
char* copy = malloc(len);
|
||||
if(!copy)
|
||||
return 0;
|
||||
memcpy(copy, s, len-1);
|
||||
copy[len-1] = 0;
|
||||
return copy;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue