Compare commits

..

114 Commits

Author SHA1 Message Date
Vitaliy Filippov 5a991e1fcb Do not try to ZDR_DECODE bytes into a preallocated buffer (it also segfaults) 2022-02-12 14:09:40 +03:00
Vitaliy Filippov 338e176320 Fix rpc_read_from_socket (no idea how it worked before) 2022-02-12 13:57:31 +03:00
Ronnie Sahlberg 1703d4479d
Merge pull request #374 from vitalif/master
Add an opaque pointer argument to service_proc
2022-02-06 11:37:42 +10:00
Vitaliy Filippov 45430b3c38 Add an opaque pointer argument to service_proc
Without this argument it's impossible to pass an object instance to procedure
callbacks which basically forces users to either use global variables or to
write additional boilerplate code and find object instances from rpc_context
pointer values.
2022-02-06 02:29:39 +03:00
Ronnie Sahlberg 4785ab7eae multithreading/ptread: gettid() is not available in all versions
gettid() is not guaranteed to be universally available
so replace this with calling the syscall directly for
building on Linux with Multithreading enabled.

Windows already use a native call for this so it should be unaffected
but other unix-like systems with pthread support will need to have
a replacement function here as well.
This is todo for later for non-linux pthread platforms.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-02-03 17:26:26 +10:00
Ronnie Sahlberg 2772c70be6 New version 5.0.1
Fixes non-pthread build

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-02-01 03:31:37 +10:00
Ronnie Sahlberg 32349ab58b update README.multithreading
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-29 14:23:06 +10:00
Ronnie Sahlberg beaf4cd769 update README.multithreading
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-29 14:16:17 +10:00
Ronnie Sahlberg c33e0c3825 configure.ac: fix typo for ENABLE_PTHREAD
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-29 13:30:51 +10:00
Ronnie Sahlberg 382905495f
Merge pull request #372 from heitbaum/5.0.0-fixes
fix multithreading mutex
2022-01-29 09:40:14 +10:00
heitbaum fe62199737 utils/nfs-ls: dont use nfs_mt_service_thread_ if not built with HAVE_MULTITHREADING 2022-01-28 23:38:04 +00:00
heitbaum 680ceb8d2c nfsv4: fix nfs4_op_release_lockowner defined but not used 2022-01-28 23:33:07 +00:00
heitbaum 7b7648e0d8 nfsv3: fix multithreading mutex 2022-01-28 23:28:54 +00:00
heitbaum 26133258fd nfsv4: fix multithreading mutex 2022-01-28 23:21:34 +00:00
Ronnie Sahlberg a48f019e05 New 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

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-28 10:50:38 +10:00
Ronnie Sahlberg 29b4cea00f multithreading: make nfs_get_error() work for multithreaded applications
This mostly consists of creating one slave nfs_context  for each nfs
thread to track the error-string.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-28 10:38:32 +10:00
Ronnie Sahlberg f85c21755e nfs4: Use RELEASE_LOCKOWNER when we close a file
We create a new lock_owner for every open(), to reduce pressure on the
servers lock_owner cache  we can tell it that this lock_owner will not
be used again and it can drop it from the cache.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-05 16:41:34 +10:00
Ronnie Sahlberg 0550a5c83f nfs4 multithreading: create a new lock_owner for every single open()
This allows us to perform unlimited concurrent opens as we are longer
bound by rfc3530  8.1.5 which limits to only one active OPEN command
per lock_owner

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-05 16:18:11 +10:00
Ronnie Sahlberg 61e5863e46 nfsv4: fix multithreading for nfsv4
Some multi-stage operations in nfs v4 can not be interleaved
so add mutex to prevent them from running concurrently.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-05 13:10:16 +10:00
Ronnie Sahlberg 4ca1e05f4e rpcgen: fix compilation of nfs header file
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-05 13:10:06 +10:00
Ronnie Sahlberg 1716b14104 Write PDUs straight to the wire when the queue is empty
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2022-01-05 13:10:00 +10:00
Ronnie Sahlberg 630a80c056 WIN32: add multithreading support for windows 2022-01-02 13:02:31 +10:00
Ronnie Sahlberg 1648cd8393 remove strndup call
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-12-31 11:53:33 +10:00
Ronnie Sahlberg efa9085cfa add support for nfsv3 getacl
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-12-31 11:42:48 +10:00
Ronnie Sahlberg c851f458a0 multithreading: fix race for waking blocked worker threads
We must make sure that we prepare and process all the returned data
before we wake the thread that is waiting for the i/o to complete
or else we will have a race between waking the thread and copying
the returned data in the service thread.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-12-31 08:28:20 +10:00
Ronnie Sahlberg 20b39fd251 PS2_EE: update to compile on latest ps2 sdk
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-10-15 18:14:18 +10:00
Ronnie Sahlberg 52c7bd7bc5 multithreading: return default error string when multithreading is
enabled

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-10-14 16:31:42 +10:00
Ronnie Sahlberg f55637619e initial pthread support
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-10-14 16:31:26 +10:00
Ronnie Sahlberg 81f4609076
Merge pull request #365 from vitalif/master
Don't try to ZDR_DECODE strings into a pre-existing pointer
2021-10-11 21:39:24 +10:00
Vitaliy Filippov d1999dc956 Don't try to ZDR_DECODE strings into a pre-existing pointer
Otherwise it segfaults inside any string decoding inside rpc_process_call()
as it doesn't zero the allocated memory, so libnfs_zdr_string() may receive
non-zero *strp which is very easy to reproduce by writing a simple NFS server
example using libnfs :-)
2021-10-11 00:55:14 +03:00
Ronnie Sahlberg 4fa3b79569
Merge pull request #364 from Daniel-Abrecht/strndup
Fix mingw build: add strndup implementation to win32_compat.c
2021-10-04 16:43:21 +10:00
Daniel Abrecht 939814826f Fix mingw build: add strndup implementation to win32_compat.c 2021-10-03 12:51:42 +00:00
Ronnie Sahlberg b1fbe322be
Merge pull request #363 from rhynec/master
Fix PS3 Build - Include nfs4 files in compilation.
2021-10-03 06:12:29 +10:00
rhynec f6a3b0147d
Fix PS3 Build - Include nfs4 files in compilation.
Compilation failed due to changes introduced in cdb377532a. This is a test patch to see if compilation succeeds with this minor change.
2021-10-02 12:32:42 -05:00
Ronnie Sahlberg f965ec74cf ps2ee: PS2 EE support
Initial support for building a library for PS2 EmotionEngine

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-09-17 07:27:44 +10:00
Ronnie Sahlberg f88cca547d nfsv4: fix inode in readdir and nulltermination of readlink
Reported-by: Hemambara Kurma <hemambara.kurma@rubrik.com>
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-09-08 10:27:57 +10:00
Ronnie Sahlberg fca28fe112 url: add support for using escaped characters in the url.
We need to allow users to specify escaped characters as part of the 'path'
field of a URL.
For example, '?' is used to separate the part and the optional list of
arguments.
IF 'path' contains a '?' character then that must be escaped as %3F.
So that libnfs will be able to tell it apart from the '?' separator.

I.e.
nfs://127.0.0.1/my?path/?version=4
must be escaped as
nfs://127.0.0.1/my%3Fpath/?version=4
before passed to any of the URL parsing functions.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-09-01 08:17:23 +10:00
Ronnie Sahlberg 820dc73e32 nfsv3: fix crash when performing very large reads
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-08-11 06:12:06 +10:00
Ronnie Sahlberg 965b1914ef Allow setting max read/write size from the api
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-08-10 16:29:42 +10:00
Ronnie Sahlberg af90dbfbcf nfs4: update the makefile to do the c++ tweaks automatically
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-07-20 19:07:36 +10:00
Ronnie Sahlberg d1494d41de nfs4: tweak the raw headerfile for c++
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-07-20 18:16:41 +10:00
Ronnie Sahlberg 752cb4134d url: add support for server:port syntax in the url
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-07-18 07:46:09 +10:00
Ronnie Sahlberg cdb377532a acl: add support and helpers to read nfsv4 acls
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-07-17 20:11:56 +10:00
Ronnie Sahlberg 1cdc8657de nfs-io: stat, print sStT bits properly
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-07-17 20:11:46 +10:00
Ronnie Sahlberg be437aa102 utils: add a nfs-stat utility
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2021-07-17 20:11:37 +10:00
Ronnie Sahlberg a7c6637980
Merge pull request #336 from Daniel-Abrecht/master
Define u_int in libnfs-zdr.h for mingw again
2020-11-28 06:58:55 +10:00
Daniel Abrecht 4ae2f12b74 Define u_int in libnfs-zdr.h for mingw again
The typedef for u_int was removed in 172f46756e,
assuming that sys/types.h defines it. This doesn't seam to be the case on mingw.
2020-11-27 20:43:43 +01:00
Ronnie Sahlberg 9a10e17800
Merge pull request #330 from bucanero/master
sys/time.h include clean-up (PS3 PPU)
2020-08-18 11:38:20 +10:00
Damian 901d4a0040 sys/time.h include clean-up (PS3 PPU) 2020-08-17 21:14:30 -03:00
Ronnie Sahlberg bbb9c337b5
Merge pull request #329 from bucanero/master
Rename to avoid linking issues
2020-08-18 07:22:14 +10:00
Damian Parrino 5f74b69624 Rename to avoid linking issues 2020-08-17 11:15:07 -03:00
Ronnie Sahlberg da61d648e6
Merge pull request #328 from bucanero/master
PlayStation 3 port
2020-08-16 04:02:18 +10:00
Damian 0df1d4beac include clean-up 2020-08-15 11:35:55 -03:00
Damián Parrino ef0056cd13
Update README 2020-08-15 11:31:11 -03:00
Damian 1bafddb264 Include clean-up 2020-08-15 11:28:04 -03:00
Damian c14a5acb51 Porting to PS3 2020-08-14 19:30:00 -03:00
Damian c7ad0762d8 Porting library to PS3 (psl1ght) 2020-08-14 11:47:39 -03:00
Ronnie Sahlberg ef0ca03565
Merge pull request #326 from asomers/u_int
Don't define u_int
2020-08-01 07:19:41 +10:00
Ronnie Sahlberg 8cf8c620f3
Merge pull request #325 from asomers/gitignore
Remove .c and .h from .gitignore
2020-08-01 07:18:09 +10:00
Alan Somers 172f46756e Don't define u_int
It's usually defined by the platform in types.h or sys/types.h.
The compiler complains if libnfs redefines it.
2020-07-26 15:13:13 -06:00
Alan Somers 2b3e8f450b Remove .c and .h from .gitignore
I think these were accidentally included in revision
6c437065d3
2020-07-26 15:12:42 -06:00
Ronnie Sahlberg cf47ea7e6a
Merge pull request #324 from adamyi/master
Fix seekdir
2020-06-23 08:35:35 +10:00
Adam Yi dfa85d4c36 Fix seekdir
The previous implementation doesn't actually update dir->current but
resets dir->current to dir->entries
2020-06-23 02:11:33 +10:00
Ronnie Sahlberg 17f882fbdb tests: disable test 0101
Modern versions of portmapper/mount daemon no longer respond to
broadcast rpc so nfs server discovery no longer works.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-09 13:44:49 +10:00
Ronnie Sahlberg c5d022b638 nfsv4.1 Add SECINFO[_NO_NAME] operations
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:42:16 +10:00
Ronnie Sahlberg da2a3dd9d3 nfsv4.1 Add RECLAIM_COMPLETE operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:29:17 +10:00
Ronnie Sahlberg ff73bb6cc3 nfsv4.1 Add DESTROY_CLIENTID operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:26:42 +10:00
Ronnie Sahlberg de3d1e5f3f nfsv4.1 Add WANT_DELEGATION operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:24:09 +10:00
Ronnie Sahlberg d690031049 nfsv4.1 Add TEST_STATEID operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:18:26 +10:00
Ronnie Sahlberg 523df1eee4 nfsv4.1 Add SET_SSV operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:16:01 +10:00
Ronnie Sahlberg 52f905291c nfsv4.1 Add SEQUENCE operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:12:19 +10:00
Ronnie Sahlberg a45799ca50 nfsv4.1 Add LAYOUTRETURN operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:07:14 +10:00
Ronnie Sahlberg 61d235ae44 nfsv4.1 Add LAYOUTGET operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 14:03:11 +10:00
Ronnie Sahlberg f7b6bef8ef nfsv4.1 Add LAYOUTCOMMIT operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 13:49:33 +10:00
Ronnie Sahlberg af97775bfc nfsv4.1: Add GETDEVICELIST operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 13:43:39 +10:00
Ronnie Sahlberg 0b4c428ed3 nfsv4.1: Add GETDEVICEINFO operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 13:41:01 +10:00
Ronnie Sahlberg b994dd08a3 nfsv4.1 Add GET_DIR_DELEGATION operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 13:20:00 +10:00
Ronnie Sahlberg a18aff5e7a nfsv4.1 Add FREE_STATEID operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 13:14:21 +10:00
Ronnie Sahlberg 0971e9531f nfsv4.1 Add DESTROY_CONTEXT operation
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 12:45:23 +10:00
Ronnie Sahlberg 03a47809cb nfs4.1: add marshalling of CREATE_SESSION command
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 12:34:22 +10:00
Ronnie Sahlberg be084815fa Update nfsv4 makefile to match new size of dot-x header boilerplate
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-08 12:29:02 +10:00
Ronnie Sahlberg edce6654a3 fix return value for mount_getexports
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-05 06:58:42 +10:00
Ronnie Sahlberg 4f1925c280
Merge pull request #323 from peak3d/timeout
Implement mount_getexports_timeout
2020-06-05 06:56:57 +10:00
peak3d 74ac9b5e11 Implement mount_getexports_timeout 2020-06-04 16:42:48 +02:00
Ronnie Sahlberg 3fbec953e6 mount: add a 2 second timeout for getting the export list.
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2020-06-03 19:02:36 +10:00
Ronnie Sahlberg 46c8a3006a
Merge pull request #312 from AlwinEsch/fix-cmake
fix libnfs cmake build as static
2020-05-20 07:35:49 +10:00
Ronnie Sahlberg f79745d281
Merge pull request #319 from dmeister/large_write
Allocate larger buffer for write operations in NFS4
2020-05-20 07:32:57 +10:00
Ronnie Sahlberg 4dd823b4a1
Merge pull request #318 from dmeister/chown
Fix NFS4 behavior of chmod/chown/utimes
2020-05-20 07:29:19 +10:00
Dirk Meister 483be177fe Allocate larger buffer for write operations in NFS4
The NFS4 pwrite operations contains a memory corruption if a write
is large than 4KB. The reason is that the buffer allocated within
nfs4_compund_async has a size of 4K and it does not account
for the size of the write buffer. To fix this the patch
padds a rpc_allocate_ndu2 function which an additional parameter
as an extra hint for the allocation.
2020-05-18 20:57:06 -07:00
Dirk Meister 1336b5280e Fix NFS4 behavior of chmod/chown/utimes
This patch fixes various issues around chmod/chown/utimes:
- The chmod/chown/utimes approach uses open_async_internal, which only works
  for files. This patch uses lookup_path so that chmod/chown is also
  possible on directories.
- Implements SET_TO_SERVER for utimes

I never succeeded in getting all tests passing even without
these changes. Nor did I succeed in getting the CMake compilation to
work. Sorry. The patch includes extra unit tests for these calls.
We use the libary as part of a test harness to test an NFS server
implementation, so I am reasonably confident that the changes work.
They are also manually tested against the Linux Kernel NFS Server.
2020-05-18 20:50:01 -07:00
Ronnie Sahlberg 12b56b8f52
Merge pull request #316 from DetlefGolze/master
Update libnfs-zdr.c
2020-05-06 18:55:20 +10:00
DetlefGolze b9c85afc4f
Update libnfs-zdr.c
libnfs_zdr_array() needs to determine element count before calculating size to allocate.
2020-05-06 10:51:39 +02:00
Alwin Esch b2fd0fe140 fix libnfs cmake build as static
Before was by them as static all other parts not included, as they also
static libraries.

This change to create them as objects where then also included in a static and only `nfs.lib` is present.

Brought before on install by Windows:
```
  Performing install step for 'nfs'
  Microsoft (R)-Build-Engine, Version 15.9.21+g9802d43bc3 für .NET Framework
  Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

    nfs_mount.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\mount\Release\nfs_mount.lib
    nfs_nfs.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\nfs\Release\nfs_nfs.lib
    nfs_nfs4.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\nfs4\Release\nfs_nfs4.lib
    nfs_nlm.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\nlm\Release\nfs_nlm.lib
    nfs_nsm.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\nsm\Release\nfs_nsm.lib
    nfs_portmap.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\portmap\Release\nfs_portmap.lib
    nfs_rquota.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\rquota\Release\nfs_rquota.lib
    nfs_win32.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\win32\Release\nfs_win32.lib
    nfs.vcxproj -> D:\Dev\Kodi64-UWP\vfs.nfs\build\build\nfs\src\nfs-build\lib\Release\nfs.lib
    -- Install configuration: "Release"
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/cmake/libnfs/libnfs-config.cmake
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/cmake/libnfs/libnfs-config-release.cmake
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/cmake/libnfs/FindNFS.cmake
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/cmake/libnfs/libnfs-config-version.cmake
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/pkgconfig/libnfs.pc
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs-raw.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs-zdr.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs.h.orig
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs-raw-mount.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs-raw-nfs.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs-raw-nlm.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs-raw-nsm.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs-raw-portmap.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/include/nfsc/libnfs-raw-rquota.h
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs_win32.lib
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs_mount.lib
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs_nfs.lib
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs_nfs4.lib
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs_nlm.lib
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs_nsm.lib
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs_portmap.lib
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs_rquota.lib
    -- Installing: D:/Dev/Kodi64-UWP/vfs.nfs/build/build/depends/lib/nfs.lib
```
2020-02-25 00:12:10 +00:00
Ronnie Sahlberg 394b185486 Try to invoke the connect callback if we shutdown while connect is in progress
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2019-12-17 08:50:23 +10:00
Ronnie Sahlberg 548fa961a8 Return "" instead of NULL for empty errors in nfs_get_error()
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2019-12-16 13:21:27 +10:00
Ronnie Sahlberg 33a5d08b05 Update to INSTALL
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2019-12-10 16:47:39 +10:00
Ronnie Sahlberg 4c20a3f8eb Add INSTALL file
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2019-12-10 16:45:27 +10:00
Volker Lendecke 338837f6de Simplify range check in libnfs_zdr_array
Signed-off-by: Volker Lendecke <vl@samba.org>
2019-11-19 14:15:33 +10:00
Ronnie Sahlberg a7b9994971
Merge pull request #300 from crusader-mike/master
fix for find_package from downstream clients
2019-10-22 23:10:56 +10:00
crusader-mike 4b12b5e005 fixed compilation of utils 2019-10-11 13:29:52 -05:00
crusader-mike 70801203e2 fixed cmake files to support package export 2019-10-11 13:12:02 -05:00
Ronnie Sahlberg ac60feabf0
Merge pull request #297 from crusader-mike/master
fixing cmake build on windows
2019-10-10 08:27:55 +10:00
crusader-mike 9d5427bbd4 fixed few MSVC warnings; fixed missing exports 2019-10-09 17:08:10 -05:00
Ronnie Sahlberg e4fa3b5bcb make LGTM.com happy and squash a false warning
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2019-09-27 20:48:58 -07:00
Ronnie Sahlberg c635cae6f6 remove obsolete FIXME comment
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2019-09-27 20:48:49 -07:00
crusader-mike 4da7bb4fec Windows: dll (built with cmake) will contain proper file version info 2019-09-13 12:46:19 -05:00
crusader-mike 3cd06883e0 cmake fix for Linux 2019-09-12 15:17:47 -05:00
crusader-mike 6564abaa1f fixed CMake build on windows, few trivial fixes 2019-09-12 15:07:35 -05:00
Ronnie Sahlberg 4de9fb8ff8
Merge pull request #296 from plieven/vc
add LIBNFS_FEATURE_UMOUNT macro
2019-09-03 07:18:19 +10:00
Peter Lieven 68faa72c85 add LIBNFS_FEATURE_UMOUNT macro
Signed-off-by: Peter Lieven <pl@kamp.de>
2019-09-02 15:49:26 +02:00
Ronnie Sahlberg ca939ba918
Merge pull request #283 from rbalint/master
Really skip test building rpm package in not rpm-based systems
2019-05-08 21:32:03 +10:00
Volker Lendecke 4bd145ba44 Prevent integer overflow in rpc_process_pdu
Signed-off-by: Volker Lendecke <vl@samba.org>
2019-03-11 11:26:04 +10:00
Volker Lendecke dfca3e447d Replace explicit memset by calloc
Signed-off-by: Volker Lendecke <vl@samba.org>
2019-03-11 11:25:37 +10:00
Balint Reczey d214e3376b Really skip test building rpm package in not rpm-based systems 2019-01-07 17:37:01 +07:00
77 changed files with 7495 additions and 833 deletions

17
.gitignore vendored
View File

@ -1,6 +1,4 @@
.* .*
*.h
*.c
*.in *.in
*.la *.la
*.a *.a
@ -39,3 +37,18 @@ stamp-h1
libnfs.pc libnfs.pc
!libnfs.pc.in !libnfs.pc.in
build 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

View File

@ -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 Changes since 3.0.0
Fix the versioning in makerpms.sh Fix the versioning in makerpms.sh

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.2)
project(libnfs project(libnfs
LANGUAGES C LANGUAGES C
VERSION 2.0.0) VERSION 5.0.1)
set(SOVERSION 11.0.0 CACHE STRING "" FORCE) set(SOVERSION 11.0.0 CACHE STRING "" FORCE)
@ -29,21 +29,42 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}
include include
include/nfsc) include/nfsc)
set(CORE_LIBRARIES nfs) # list of system libs (sockets/etc) to be linked on this system
set(core_DEPENDS "" CACHE STRING "" FORCE) 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) 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) add_subdirectory(win32)
elseif(CMAKE_SYSTEM_NAME STREQUAL Solaris) elseif(CMAKE_SYSTEM_NAME STREQUAL Solaris)
add_definitions("-D_U_=__attribute__((unused))")
find_library(SOCKET_LIBRARY socket) find_library(SOCKET_LIBRARY socket)
find_library(NSL_LIBRARY nsl) 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) elseif(CMAKE_SYSTEM_NAME STREQUAL aros)
add_definitions("-D_U_=__attribute__((unused))")
add_definitions(-DAROS) add_definitions(-DAROS)
add_subdirectory(aros) add_subdirectory(aros)
else()
add_definitions("-D_U_=__attribute__((unused))")
endif() 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) if(ENABLE_DOCUMENTATION)
add_subdirectory(doc) add_subdirectory(doc)
endif() endif()
@ -61,23 +82,35 @@ if(ENABLE_UTILS)
add_subdirectory(utils) add_subdirectory(utils)
endif() endif()
add_subdirectory(mount) # this will create build-tree-specific config file (so downstream client can use this specific build without having to install package)
add_subdirectory(nfs) export(EXPORT libnfs
add_subdirectory(nfs4) NAMESPACE libnfs::
add_subdirectory(nlm) FILE "${CMAKE_CURRENT_BINARY_DIR}/libnfs-config.cmake")
add_subdirectory(nsm)
add_subdirectory(portmap)
add_subdirectory(rquota)
add_subdirectory(lib)
# 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) include(CMakePackageConfigHelpers)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/libnfs-config-version.cmake write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/libnfs-config-version.cmake
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion) 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 configure_file(cmake/libnfs.pc.cmake
${CMAKE_CURRENT_BINARY_DIR}/libnfs.pc @ONLY) ${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 install(DIRECTORY include/nfsc
DESTINATION ${INSTALL_INC_DIR}) DESTINATION ${INSTALL_INC_DIR})
@ -88,10 +121,3 @@ install(FILES mount/libnfs-raw-mount.h
portmap/libnfs-raw-portmap.h portmap/libnfs-raw-portmap.h
rquota/libnfs-raw-rquota.h rquota/libnfs-raw-rquota.h
DESTINATION ${INSTALL_INC_DIR}/nfsc) 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})

9
INSTALL Normal file
View File

@ -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
View File

@ -40,7 +40,17 @@ URL-FORMAT:
Libnfs uses RFC2224 style URLs extended with some minor libnfs extensions. Libnfs uses RFC2224 style URLs extended with some minor libnfs extensions.
The basic syntax of these URLs is : 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 : Arguments supported by libnfs are :
tcp-syncnt=<int> : Number of SYNs to send during the session establish 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) - 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) 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' 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 LD_PRELOAD

100
README.multithreading Normal file
View File

@ -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.

View File

@ -5,11 +5,11 @@
# SOURCES the sources of the library # SOURCES the sources of the library
# HEADERS the headers of the library (only for IDE support) # HEADERS the headers of the library (only for IDE support)
# On return: # 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) function(core_add_library name)
set(name core_${name}) set(name nfs_${name})
set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_library(${name} STATIC ${SOURCES} ${HEADERS}) add_library(${name} OBJECT ${SOURCES} ${HEADERS})
target_include_directories(${name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(${name} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
set(core_DEPENDS ${name} ${core_DEPENDS} CACHE STRING "" FORCE) set(CORE_LIBRARIES "${name};${CORE_LIBRARIES}" CACHE INTERNAL "")
endfunction() endfunction()

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.50) 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]) AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
AC_CANONICAL_HOST AC_CANONICAL_HOST
@ -70,6 +70,26 @@ fi
AC_SUBST(MAYBE_EXAMPLES) 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_MSG_CHECKING(whether SO_BINDTODEVICE is available)
AC_TRY_COMPILE([#include <net/if.h>], [ AC_TRY_COMPILE([#include <net/if.h>], [
int i = SO_BINDTODEVICE; int i = SO_BINDTODEVICE;

View File

@ -1,11 +1,10 @@
find_library(TALLOC_LIBRARY talloc) find_library(TALLOC_LIBRARY talloc)
find_library(TALLOC_EVENT_LIBRARY tevent) find_library(TALLOC_EVENT_LIBRARY tevent)
find_library(EVENT_LIBARY event) 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-raw
nfsclient-sync nfsclient-sync
nfsclient-bcast nfsclient-bcast
@ -15,20 +14,17 @@ set(SOURCES nfsclient-async
portmap-client) portmap-client)
if(HAVE_TALLOC_TEVENT) if(HAVE_TALLOC_TEVENT)
list(APPEND SOURCES nfs4-cat-talloc) list(APPEND EXAMPLES nfs4-cat-talloc)
list(APPEND CORE_LIBRARIES ${TALLOC_EVENT_LIBRARY} ${TALLOC_LIBRARY}) list(APPEND EXTRA_LIBRARIES ${TALLOC_EVENT_LIBRARY} ${TALLOC_LIBRARY})
endif() endif()
if(EVENT_LIBARY) if(EVENT_LIBARY)
list(APPEND SOURCES nfs4-cat list(APPEND EXAMPLES nfs4-cat
portmap-server) portmap-server)
list(APPEND CORE_LIBRARIES ${EVENT_LIBARY}) list(APPEND EXTRA_LIBRARIES ${EVENT_LIBARY})
endif() endif()
foreach(TARGET ${SOURCES}) foreach(TARGET ${EXAMPLES})
add_executable(${TARGET} ${TARGET}.c) add_executable(${TARGET} ${TARGET}.c)
target_link_libraries(${TARGET} ${CORE_LIBRARIES}) target_link_libraries(${TARGET} nfs ${EXTRA_LIBRARIES})
add_dependencies(${TARGET} nfs)
endforeach() endforeach()
add_definitions("-D_U_=__attribute__((unused))")

View File

@ -4,6 +4,11 @@ if HAVE_TALLOC_TEVENT
noinst_PROGRAMS += nfs4-cat-talloc noinst_PROGRAMS += nfs4-cat-talloc
endif endif
if HAVE_PTHREAD
LIBS += -lpthread
noinst_PROGRAMS += nfs-pthreads-example nfs-pthreads-fstat
endif
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-I$(abs_top_srcdir)/include \ -I$(abs_top_srcdir)/include \
-I$(abs_top_srcdir)/include/nfsc \ -I$(abs_top_srcdir)/include/nfsc \
@ -28,3 +33,5 @@ nfs4_cat_LDADD = $(COMMON_LIBS) -levent
nfs4_cat_talloc_LDADD = $(COMMON_LIBS) -ltevent -ltalloc nfs4_cat_talloc_LDADD = $(COMMON_LIBS) -ltevent -ltalloc
portmap_client_LDADD = $(COMMON_LIBS) portmap_client_LDADD = $(COMMON_LIBS)
portmap_server_LDADD = $(COMMON_LIBS) -levent portmap_server_LDADD = $(COMMON_LIBS) -levent
nfs_pthreads_example_LDADD = $(COMMON_LIBS)
nfs_pthreads_fstat_LDADD = $(COMMON_LIBS)

View File

@ -35,6 +35,7 @@ WSADATA wsaData;
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
#ifndef AROS #ifndef AROS
#include <sys/statvfs.h> #include <sys/statvfs.h>
@ -51,13 +52,36 @@ WSADATA wsaData;
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include "libnfs.h" #include "../include/nfsc/libnfs.h"
#include "libnfs-raw.h" #include "../include/nfsc/libnfs-raw.h"
#include "libnfs-raw-mount.h" #include "../mount/libnfs-raw-mount.h"
#include "../nfs/libnfs-raw-nfs.h"
#include "../nfs4/libnfs-raw-nfs4.h"
void print_usage(void) 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[]) int main(int argc, char *argv[])
@ -66,6 +90,9 @@ int main(int argc, char *argv[])
struct nfs_context *nfs = NULL; struct nfs_context *nfs = NULL;
struct nfsfh *nfsfh = NULL; struct nfsfh *nfsfh = NULL;
struct nfs_url *url = NULL; struct nfs_url *url = NULL;
fattr4_acl acl4;
fattr3_acl acl3;
int i;
#ifdef WIN32 #ifdef WIN32
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
@ -110,6 +137,26 @@ int main(int argc, char *argv[])
ret = nfs_rmdir(nfs, url->file); ret = nfs_rmdir(nfs, url->file);
} else if (!strncmp(argv[1], "trunc", 5)) { } else if (!strncmp(argv[1], "trunc", 5)) {
ret = nfs_truncate(nfs, url->file, 0); ret = nfs_truncate(nfs, url->file, 0);
} else if (!strncmp(argv[1], "touch", 5)) {
struct timeval times[2];
gettimeofday(&times[0], NULL);
gettimeofday(&times[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)) { } else if (!strncmp(argv[1], "stat", 4)) {
struct nfs_stat_64 st; struct nfs_stat_64 st;
ret = nfs_stat64(nfs, url->file, &st); ret = nfs_stat64(nfs, url->file, &st);
@ -136,24 +183,70 @@ int main(int argc, char *argv[])
printf("%c%c%c", printf("%c%c%c",
"-r"[!!(st.nfs_mode & S_IRUSR)], "-r"[!!(st.nfs_mode & S_IRUSR)],
"-w"[!!(st.nfs_mode & S_IWUSR)], "-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", printf("%c%c%c",
"-r"[!!(st.nfs_mode & S_IRGRP)], "-r"[!!(st.nfs_mode & S_IRGRP)],
"-w"[!!(st.nfs_mode & S_IWGRP)], "-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", printf("%c%c%c",
"-r"[!!(st.nfs_mode & S_IROTH)], "-r"[!!(st.nfs_mode & S_IROTH)],
"-w"[!!(st.nfs_mode & S_IWOTH)], "-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(" %2d", (int)st.nfs_nlink);
printf(" %5d", (int)st.nfs_uid); printf(" %5d", (int)st.nfs_uid);
printf(" %5d", (int)st.nfs_gid); 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"); 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 { } else {
goto finished; goto finished;
} }

View File

@ -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;
}

View File

@ -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;
}

View File

@ -27,8 +27,8 @@
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
WSADATA wsaData; WSADATA wsaData;
#endif #endif
#define SERVER "10.1.1.27" #define SERVER "10.10.10.11"
#define EXPORT "/shared" #define EXPORT "/data/SNAP-4"
#ifdef HAVE_POLL_H #ifdef HAVE_POLL_H
#include <poll.h> #include <poll.h>

View File

@ -36,11 +36,24 @@ WSADATA wsaData;
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#ifdef HAVE_NETDB_H
#include <netdb.h> #include <netdb.h>
#endif
#include <stdio.h> #include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h> #include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h> #include <string.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif
#include <time.h> #include <time.h>
#include "libnfs.h" #include "libnfs.h"
#include "libnfs-raw.h" #include "libnfs-raw.h"

View File

@ -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_ */

View File

@ -27,7 +27,7 @@
#include <net/if.h> #include <net/if.h>
#endif #endif
#ifndef WIN32 #if !defined(WIN32) && !defined(PS2_EE)
#include <sys/socket.h> /* struct sockaddr_storage */ #include <sys/socket.h> /* struct sockaddr_storage */
#endif #endif
@ -35,6 +35,15 @@
#define IFNAMSIZ 255 #define IFNAMSIZ 255
#endif #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 "libnfs-zdr.h"
#include "../nfs/libnfs-raw-nfs.h" #include "../nfs/libnfs-raw-nfs.h"
#include "../nfs4/libnfs-raw-nfs4.h" #include "../nfs4/libnfs-raw-nfs4.h"
@ -50,7 +59,7 @@ extern "C" {
#define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif #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 * RFC 2553: protocol-independent placeholder for socket addresses
*/ */
@ -123,6 +132,9 @@ struct rpc_context {
struct sockaddr_storage udp_src; struct sockaddr_storage udp_src;
struct rpc_queue waitpdu[HASHES]; struct rpc_queue waitpdu[HASHES];
uint32_t waitpdu_len; uint32_t waitpdu_len;
#ifdef HAVE_MULTITHREADING
libnfs_mutex_t rpc_mutex;
#endif /* HAVE_MULTITHREADING */
uint32_t inpos; uint32_t inpos;
char rm_buf[4]; char rm_buf[4];
@ -205,12 +217,16 @@ void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)
#endif #endif
; ;
#if defined(PS2_EE)
#define RPC_LOG(rpc, level, format, ...) ;
#else
#define RPC_LOG(rpc, level, format, ...) \ #define RPC_LOG(rpc, level, format, ...) \
do { \ do { \
if (level <= rpc->debug) { \ if (level <= rpc->debug) { \
fprintf(stderr, "libnfs:%d " format "\n", level, ## __VA_ARGS__); \ fprintf(stderr, "libnfs:%d " format "\n", level, ## __VA_ARGS__); \
} \ } \
} while (0) } while (0)
#endif
const char *nfs_get_server(struct nfs_context *nfs); const char *nfs_get_server(struct nfs_context *nfs);
const char *nfs_get_export(struct nfs_context *nfs); const char *nfs_get_export(struct nfs_context *nfs);
@ -271,22 +287,19 @@ struct nfs_fh {
char *val; char *val;
}; };
struct nfs_context { struct nfs_context_internal {
struct rpc_context *rpc;
char *server; char *server;
char *export; char *export;
char *cwd;
struct nfs_fh rootfh; struct nfs_fh rootfh;
uint64_t readmax; uint64_t readmax;
uint64_t writemax; uint64_t writemax;
char *cwd;
int dircache_enabled;
int auto_reconnect; int auto_reconnect;
int dircache_enabled;
struct nfsdir *dircache; struct nfsdir *dircache;
uint16_t mask; uint16_t mask;
int auto_traverse_mounts; int auto_traverse_mounts;
struct nested_mounts *nested_mounts; struct nested_mounts *nested_mounts;
int version; int version;
int nfsport; int nfsport;
int mountport; int mountport;
@ -296,10 +309,35 @@ struct nfs_context {
char *client_name; char *client_name;
uint64_t clientid; uint64_t clientid;
verifier4 setclientid_confirm; verifier4 setclientid_confirm;
uint32_t seqid; uint32_t open_counter;
int has_lock_owner; 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, typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_attr *attr,
struct nfs_cb_data *data); struct nfs_cb_data *data);
@ -384,7 +422,9 @@ struct nfsfh {
/* NFSv4 */ /* NFSv4 */
struct stateid stateid; struct stateid stateid;
uint32_t lock_owner;
/* locking */ /* locking */
uint32_t open_seqid;
uint32_t lock_seqid; uint32_t lock_seqid;
struct stateid lock_stateid; 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, uint64_t count, const void *buf, nfs_cb cb,
void *private_data); void *private_data);
int rpc_write_to_socket(struct rpc_context *rpc);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -2271,6 +2271,28 @@ struct COMPOUND4args;
EXTERN int rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb, EXTERN int rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
struct COMPOUND4args *args, struct COMPOUND4args *args,
void *private_data); 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 * Call <generic>/NULL

View File

@ -34,6 +34,7 @@
#define CADDR_T_DEFINED #define CADDR_T_DEFINED
typedef char *caddr_t; typedef char *caddr_t;
#endif #endif
#include <winsock2.h>
#endif #endif
#include <stdio.h> #include <stdio.h>
@ -92,7 +93,9 @@ struct ZDR {
typedef struct ZDR ZDR; typedef struct ZDR ZDR;
#ifdef __MINGW32__
typedef uint32_t u_int; typedef uint32_t u_int;
#endif
typedef uint32_t enum_t; typedef uint32_t enum_t;
typedef uint32_t bool_t; typedef uint32_t bool_t;
@ -100,6 +103,7 @@ typedef uint32_t (*zdrproc_t) (ZDR *, void *,...);
#define AUTH_NONE 0 #define AUTH_NONE 0
#define AUTH_NULL 0 #define AUTH_NULL 0
#define AUTH_SYS 1
#define AUTH_UNIX 1 #define AUTH_UNIX 1
struct opaque_auth { struct opaque_auth {

View File

@ -23,8 +23,12 @@
#ifndef _LIBNFS_H_ #ifndef _LIBNFS_H_
#define _LIBNFS_H_ #define _LIBNFS_H_
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#include <stdint.h> #include <stdint.h>
#if defined(__ANDROID__) || defined(AROS) \ #if defined(__ANDROID__) || defined(AROS) || defined(__PPU__) \
|| ( defined(__APPLE__) && defined(__MACH__) ) || ( defined(__APPLE__) && defined(__MACH__) )
#include <sys/time.h> #include <sys/time.h>
#else #else
@ -38,6 +42,9 @@ extern "C" {
#define LIBNFS_FEATURE_READAHEAD #define LIBNFS_FEATURE_READAHEAD
#define LIBNFS_FEATURE_PAGECACHE #define LIBNFS_FEATURE_PAGECACHE
#define LIBNFS_FEATURE_DEBUG #define LIBNFS_FEATURE_DEBUG
#define LIBNFS_FEATURE_UMOUNT
#define LIBNFS_FEATURE_MULTITHREADING
#define NFS_BLKSIZE 4096 #define NFS_BLKSIZE 4096
#define NFS_PAGECACHE_DEFAULT_TTL 5 #define NFS_PAGECACHE_DEFAULT_TTL 5
@ -50,7 +57,7 @@ struct nfs_url {
char *file; char *file;
}; };
#if defined(WIN32) #if defined(WIN32) && defined(libnfs_EXPORTS)
#define EXTERN __declspec( dllexport ) #define EXTERN __declspec( dllexport )
#else #else
#ifndef EXTERN #ifndef EXTERN
@ -244,15 +251,25 @@ EXTERN void nfs_destroy_url(struct nfs_url *url);
struct nfsfh; 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); 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); 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 * MODIFY CONNECT PARAMETERS
*/ */
@ -273,6 +290,12 @@ EXTERN void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries);
* NFS_V4 * NFS_V4
*/ */
EXTERN int nfs_set_version(struct nfs_context *nfs, int version); 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 * 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); 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); 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); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -33,6 +33,7 @@ THE SOFTWARE.
#include <io.h> #include <io.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <time.h> #include <time.h>
#include <stddef.h> // For size_t type
typedef unsigned long fsblkcnt_t; typedef unsigned long fsblkcnt_t;
typedef unsigned long fsfilcnt_t; typedef unsigned long fsfilcnt_t;
@ -133,7 +134,7 @@ struct pollfd {
/* Wrapper macros to call misc. functions win32 is missing */ /* Wrapper macros to call misc. functions win32 is missing */
#define poll(x, y, z) win32_poll(x, y, z) #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 inet_pton(x,y,z) win32_inet_pton(x,y,z)
#define open(x, y, z) _open(x, y, z) #define open(x, y, z) _open(x, y, z)
#ifndef lseek #ifndef lseek
@ -151,4 +152,8 @@ int win32_gettimeofday(struct timeval *tv, struct timezone *tz);
#define DllExport #define DllExport
#ifdef __MINGW32__
char* strndup(const char *s, size_t n);
#endif
#endif//win32_COMPAT_H_ #endif//win32_COMPAT_H_

View File

@ -2,21 +2,26 @@ set(SOURCES init.c
libnfs.c libnfs.c
libnfs-sync.c libnfs-sync.c
libnfs-zdr.c libnfs-zdr.c
multithreading.c
nfs_v3.c nfs_v3.c
nfs_v4.c nfs_v4.c
pdu.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}) add_library(nfs ${SOURCES})
target_link_libraries(nfs PUBLIC ${core_DEPENDS}) target_link_libraries(nfs PRIVATE ${CORE_LIBRARIES} PUBLIC ${SYSTEM_LIBRARIES})
target_include_directories(nfs PUBLIC ../include)
set_target_properties(nfs PROPERTIES set_target_properties(nfs PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION ${SOVERSION}) 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 RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib) LIBRARY DESTINATION lib)

View File

@ -19,13 +19,14 @@ libnfs_la_SOURCES = \
libnfs.c \ libnfs.c \
libnfs-sync.c \ libnfs-sync.c \
libnfs-zdr.c \ libnfs-zdr.c \
multithreading.c \
nfs_v3.c \ nfs_v3.c \
nfs_v4.c \ nfs_v4.c \
pdu.c \ pdu.c \
socket.c \ socket.c \
../win32/win32_compat.c ../win32/win32_compat.c
SOCURRENT=13 SOCURRENT=14
SOREVISION=0 SOREVISION=0
SOAGE=0 SOAGE=0
libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE) libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE)

View File

@ -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> Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
@ -22,6 +23,14 @@
#include "aros_compat.h" #include "aros_compat.h"
#endif #endif
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef PS3_PPU
#include "ps3_compat.h"
#endif
#ifdef WIN32 #ifdef WIN32
#include <win32/win32_compat.h> #include <win32/win32_compat.h>
#endif #endif
@ -76,6 +85,10 @@ struct rpc_context *rpc_init_context(void)
rpc->magic = RPC_CONTEXT_MAGIC; rpc->magic = RPC_CONTEXT_MAGIC;
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_init(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
rpc->auth = authunix_create_default(); rpc->auth = authunix_create_default();
if (rpc->auth == NULL) { if (rpc->auth == NULL) {
free(rpc); 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 // Add PID to rpc->xid for easier debugging, making sure to cast
// pid to 32-bit type to avoid invalid left-shifts. // 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; salt += 0x01000000;
rpc->fd = -1; rpc->fd = -1;
rpc->tcp_syncnt = RPC_PARAM_UNDEFINED; rpc->tcp_syncnt = RPC_PARAM_UNDEFINED;
rpc->pagecache_ttl = NFS_PAGECACHE_DEFAULT_TTL; rpc->pagecache_ttl = NFS_PAGECACHE_DEFAULT_TTL;
#if defined(WIN32) || defined(ANDROID) #if defined(WIN32) || defined(ANDROID) || defined(PS3_PPU)
rpc->uid = 65534; rpc->uid = 65534;
rpc->gid = 65534; rpc->gid = 65534;
#else #else
rpc->uid = getuid(); rpc->uid = getuid();
rpc->gid = getgid(); rpc->gid = getgid();
#endif #endif
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
rpc_reset_queue(&rpc->outqueue); rpc_reset_queue(&rpc->outqueue);
for (i = 0; i < HASHES; i++) for (i = 0; i < HASHES; i++)
rpc_reset_queue(&rpc->waitpdu[i]); rpc_reset_queue(&rpc->waitpdu[i]);
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
/* Default is no timeout */ /* Default is no timeout */
rpc->timeout = -1; 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->is_udp = rpc_is_udp_socket(rpc);
rpc_reset_queue(&rpc->outqueue); rpc_reset_queue(&rpc->outqueue);
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_init(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
return rpc; 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, ...) void rpc_set_error(struct rpc_context *rpc, const char *error_string, ...)
{ {
va_list ap; va_list ap;
char *old_error_string = rpc->error_string; char *old_error_string;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
old_error_string = rpc->error_string;
va_start(ap, error_string); va_start(ap, error_string);
rpc->error_string = malloc(1024); rpc->error_string = malloc(1024);
vsnprintf(rpc->error_string, 1024, error_string, ap); 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) { if (old_error_string != NULL) {
free(old_error_string); 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) char *rpc_get_error(struct rpc_context *rpc)
{ {
assert(rpc->magic == RPC_CONTEXT_MAGIC); 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) 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. * pdus when called.
*/ */
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
outqueue = rpc->outqueue; outqueue = rpc->outqueue;
rpc_reset_queue(&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); pdu->cb(rpc, status, (void *) error, pdu->private_data);
rpc_free_pdu(rpc, pdu); rpc_free_pdu(rpc, pdu);
} }
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
for (i = 0; i < HASHES; i++) { 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]); rpc_reset_queue(&rpc->waitpdu[i]);
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
while((pdu = waitqueue.head) != NULL) { while((pdu = waitqueue.head) != NULL) {
waitqueue.head = pdu->next; waitqueue.head = pdu->next;
pdu->next = NULL; 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); 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) 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->inbuf = NULL;
rpc->magic = 0; rpc->magic = 0;
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_destroy(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
free(rpc); free(rpc);
} }

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,8 @@ nfs_close_async
nfs_closedir nfs_closedir
nfs_creat nfs_creat
nfs_creat_async nfs_creat_async
nfs_create
nfs_create_async
nfs_destroy_context nfs_destroy_context
nfs_fchmod nfs_fchmod
nfs_fchmod_async nfs_fchmod_async
@ -26,6 +28,8 @@ nfs_fcntl
nfs_fcntl_async nfs_fcntl_async
nfs_fstat nfs_fstat
nfs_fstat_async nfs_fstat_async
nfs_fstat64
nfs_fstat64_async
nfs_fsync nfs_fsync
nfs_fsync_async nfs_fsync_async
nfs_ftruncate nfs_ftruncate
@ -35,6 +39,7 @@ nfs_get_fd
nfs_get_readmax nfs_get_readmax
nfs_get_writemax nfs_get_writemax
nfs_getcwd nfs_getcwd
nfs_get_version
nfs_get_timeout nfs_get_timeout
nfs_init_context nfs_init_context
nfs_link nfs_link
@ -51,6 +56,8 @@ nfs_mknod
nfs_mknod_async nfs_mknod_async
nfs_mount nfs_mount
nfs_mount_async nfs_mount_async
nfs_mt_service_thread_start
nfs_mt_service_thread_stop
nfs_open nfs_open
nfs_open_async nfs_open_async
nfs_open2 nfs_open2
@ -85,10 +92,12 @@ nfs_set_gid
nfs_set_pagecache nfs_set_pagecache
nfs_set_pagecache_ttl nfs_set_pagecache_ttl
nfs_set_readahead nfs_set_readahead
nfs_set_readmax
nfs_set_tcp_syncnt nfs_set_tcp_syncnt
nfs_set_timeout nfs_set_timeout
nfs_set_uid nfs_set_uid
nfs_set_version nfs_set_version
nfs_set_writemax
nfs_stat nfs_stat
nfs_stat_async nfs_stat_async
nfs_stat64 nfs_stat64
@ -116,8 +125,13 @@ nfsstat3_to_errno
nfsstat3_to_str nfsstat3_to_str
nfsstat4_to_errno nfsstat4_to_errno
nfsstat4_to_str nfsstat4_to_str
nfs3_getacl
nfs3_getacl_async
nfs4_set_client_name nfs4_set_client_name
nfs4_set_verifier nfs4_set_verifier
nfs4_acl_free
nfs4_getacl
nfs4_getacl_async
win32_poll win32_poll
rpc_connect_async rpc_connect_async
rpc_connect_port_async rpc_connect_port_async

View File

@ -33,6 +33,14 @@
#include "aros_compat.h" #include "aros_compat.h"
#endif #endif
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef PS3_PPU
#include "ps3_compat.h"
#endif
#ifdef HAVE_ARPA_INET_H #ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@ -185,11 +193,7 @@ bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize
} }
return TRUE; return TRUE;
case ZDR_DECODE: case ZDR_DECODE:
if (*bufp != NULL) {
memcpy(*bufp, &zdrs->buf[zdrs->pos], *size);
} else {
*bufp = &zdrs->buf[zdrs->pos]; *bufp = &zdrs->buf[zdrs->pos];
}
zdrs->pos += *size; zdrs->pos += *size;
zdrs->pos = (zdrs->pos + 3) & ~3; zdrs->pos = (zdrs->pos + 3) & ~3;
return TRUE; return TRUE;
@ -313,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) bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc)
{ {
int i; int i;
uint32_t s;
if (!libnfs_zdr_u_int(zdrs, size)) { if (!libnfs_zdr_u_int(zdrs, size)) {
return FALSE; return FALSE;
} }
if (*size > UINT32_MAX/elsize) {
return FALSE;
}
s = *size * elsize;
if (zdrs->x_op == ZDR_DECODE) { if (zdrs->x_op == ZDR_DECODE) {
*arrp = zdr_malloc(zdrs, *size * elsize); *arrp = zdr_malloc(zdrs, s);
if (*arrp == NULL) { if (*arrp == NULL) {
return FALSE; return FALSE;
} }
memset(*arrp, 0, *size * elsize); memset(*arrp, 0, s);
} }
for (i = 0; i < (int)*size; i++) { for (i = 0; i < (int)*size; i++) {
@ -585,7 +595,7 @@ struct AUTH *libnfs_authunix_create(const char *host, uint32_t uid, uint32_t gid
struct AUTH *libnfs_authunix_create_default(void) struct AUTH *libnfs_authunix_create_default(void)
{ {
#ifdef WIN32 #if defined(WIN32) || defined(PS3_PPU)
return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL); return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL);
#else #else
return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL); return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL);

File diff suppressed because it is too large Load Diff

282
lib/multithreading.c Normal file
View File

@ -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 */

View File

@ -30,6 +30,14 @@
#include "aros_compat.h" #include "aros_compat.h"
#endif #endif
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef PS3_PPU
#include "ps3_compat.h"
#endif
#ifdef WIN32 #ifdef WIN32
#include <win32/win32_compat.h> #include <win32/win32_compat.h>
#endif #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 /* Handle absolute paths, ensuring that the path lies within the
* export. */ * export. */
if (path[0] == '/') { if (path[0] == '/') {
if (strstr(path, nfs->export) == path) { if (strstr(path, nfs_get_export(nfs)) == path) {
char *ptr = path + strlen(nfs->export); char *ptr = path + strlen(nfs_get_export(nfs));
if (*ptr == '/') { if (*ptr == '/') {
newpath = strdup(ptr); newpath = strdup(ptr);
} else if (*ptr == '\0') { } 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; 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; return;
nomem: 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 /* This function will always invoke the callback and cleanup
* for failures. So no need to check the return value. * 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 */ /* 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 = "."; path = ".";
} }
data = malloc(sizeof(struct nfs_cb_data)); data = calloc(1, sizeof(struct nfs_cb_data));
if (data == NULL) { if (data == NULL) {
nfs_set_error(nfs, "Out of memory: failed to allocate " nfs_set_error(nfs, "Out of memory: failed to allocate "
"nfs_cb_data structure"); "nfs_cb_data structure");
@ -479,7 +487,6 @@ nfs3_lookuppath_async(struct nfs_context *nfs, const char *path, int no_follow,
} }
return -1; return -1;
} }
memset(data, 0, sizeof(struct nfs_cb_data));
data->nfs = nfs; data->nfs = nfs;
data->cb = cb; data->cb = cb;
data->continue_cb = continue_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] == '/') { if (path[0] == '/') {
data->saved_path = strdup(path); data->saved_path = strdup(path);
} else { } 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) { if (data->saved_path == NULL) {
nfs_set_error(nfs, "Out of memory: failed to " nfs_set_error(nfs, "Out of memory: failed to "
"allocate path string"); "allocate path string");
free_nfs_cb_data(data); free_nfs_cb_data(data);
return -1; 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) { 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; data->path = data->saved_path;
fh = &nfs->rootfh; fh = &nfs->nfsi->rootfh;
if (data->path[0]) { if (data->path[0]) {
struct nested_mounts *mnt; 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; size_t max_match_len = 0;
/* Do we need to switch to a different nested export ? */ /* 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) if (strlen(mnt->path) < max_match_len)
continue; continue;
if (strncmp(mnt->path, data->saved_path, 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; return;
} }
if (!nfs->nested_mounts) if (!nfs->nfsi->nested_mounts)
goto finished; goto finished;
/* nested mount traversals are best-effort only, so any /* 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)); memset(ma, 0, sizeof(struct mount_attr_cb));
ma->data = data; 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 mount_attr_item_cb *ma_item;
struct GETATTR3args args; 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) { if (res->status != NFS3_OK) {
nfs_set_error(nfs, "NFS: FSINFO of %s failed with %s(%d)", 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)); nfsstat3_to_errno(res->status));
data->cb(nfsstat3_to_errno(res->status), nfs, data->cb(nfsstat3_to_errno(res->status), nfs,
nfs_get_error(nfs), data->private_data); 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; return;
} }
nfs->readmax = res->FSINFO3res_u.resok.rtmax; nfs->nfsi->readmax = res->FSINFO3res_u.resok.rtmax;
nfs->writemax = res->FSINFO3res_u.resok.wtmax; nfs->nfsi->writemax = res->FSINFO3res_u.resok.wtmax;
/* The server supports sizes up to rtmax and wtmax, so it is legal /* The server supports sizes up to rtmax and wtmax, so it is legal
* to use smaller transfers sizes. * to use smaller transfers sizes.
*/ */
if (nfs->readmax > NFS_MAX_XFER_SIZE) if (nfs->nfsi->readmax > NFS_MAX_XFER_SIZE)
nfs->readmax = NFS_MAX_XFER_SIZE; nfs->nfsi->readmax = NFS_MAX_XFER_SIZE;
else if (nfs->readmax < NFSMAXDATA2) { else if (nfs->nfsi->readmax < NFSMAXDATA2) {
nfs_set_error(nfs, "server max rsize of %" PRIu64, 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); data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data);
free_nfs_cb_data(data); free_nfs_cb_data(data);
return; return;
} }
if (nfs->writemax > NFS_MAX_XFER_SIZE) if (nfs->nfsi->writemax > NFS_MAX_XFER_SIZE)
nfs->writemax = NFS_MAX_XFER_SIZE; nfs->nfsi->writemax = NFS_MAX_XFER_SIZE;
else if (nfs->writemax < NFSMAXDATA2) { else if (nfs->nfsi->writemax < NFSMAXDATA2) {
nfs_set_error(nfs, "server max wsize of %" PRIu64, 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); data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data);
free_nfs_cb_data(data); free_nfs_cb_data(data);
return; return;
} }
memset(&args, 0, sizeof(GETATTR3args)); memset(&args, 0, sizeof(GETATTR3args));
args.object.data.data_len = nfs->rootfh.len; args.object.data.data_len = nfs->nfsi->rootfh.len;
args.object.data.data_val = nfs->rootfh.val; args.object.data.data_val = nfs->nfsi->rootfh.val;
if (rpc_nfs3_getattr_async(rpc, nfs3_mount_7_cb, &args, data) != 0) { if (rpc_nfs3_getattr_async(rpc, nfs3_mount_7_cb, &args, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); 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 /* NFS TCP: As we are connected now we can pass on the auto-reconnect
* settings to the RPC layer. * 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_len = nfs->nfsi->rootfh.len;
args.fsroot.data.data_val = nfs->rootfh.val; args.fsroot.data.data_val = nfs->nfsi->rootfh.val;
if (rpc_nfs3_fsinfo_async(rpc, nfs3_mount_6_cb, &args, data) != 0) { if (rpc_nfs3_fsinfo_async(rpc, nfs3_mount_6_cb, &args, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); 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; mnt->path = md_item_cb->path;
md_item_cb->path = NULL; md_item_cb->path = NULL;
LIBNFS_LIST_ADD(&nfs->nested_mounts, mnt); LIBNFS_LIST_ADD(&nfs->nfsi->nested_mounts, mnt);
finished: finished:
free(md_item_cb->path); free(md_item_cb->path);
@ -854,8 +861,9 @@ finished:
return; return;
} }
if (nfs->nfsport) { if (nfs->nfsi->nfsport) {
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport, if (rpc_connect_port_async(nfs->rpc, nfs_get_server(nfs),
nfs->nfsi->nfsport,
NFS_PROGRAM, NFS_V3, NFS_PROGRAM, NFS_V3,
nfs3_mount_5_cb, data) != 0) { nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_set_error(nfs, "%s: %s", __FUNCTION__,
@ -869,7 +877,8 @@ finished:
return; 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_V3, nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); 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 /* Iterate over all exports and check if there are any mounts nested
* below the current mount. * below the current mount.
*/ */
len = strlen(nfs->export); len = strlen(nfs_get_export(nfs));
if (!len) { if (!len) {
data->cb(-EFAULT, nfs, "Export is empty", data->private_data); data->cb(-EFAULT, nfs, "Export is empty", data->private_data);
free_nfs_cb_data(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) { while (res) {
struct mount_discovery_item_cb *md_item_cb; 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; res = res->ex_next;
continue; 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)); memset(md_item_cb, 0, sizeof(*md_item_cb));
md_item_cb->path = strdup(res->ex_dir + len 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) { if (md_item_cb->path == NULL) {
free(md_item_cb); free(md_item_cb);
continue; continue;
@ -976,8 +985,9 @@ nfs3_mount_3_cb(struct rpc_context *rpc, int status, void *command_data,
*/ */
rpc_disconnect(rpc, "normal disconnect"); rpc_disconnect(rpc, "normal disconnect");
if (nfs->nfsport) { if (nfs->nfsi->nfsport) {
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport, if (rpc_connect_port_async(nfs->rpc, nfs_get_server(nfs),
nfs->nfsi->nfsport,
NFS_PROGRAM, NFS_V3, NFS_PROGRAM, NFS_V3,
nfs3_mount_5_cb, data) != 0) { nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, 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; 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_V3, nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); 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; return;
} }
nfs->rootfh.len = res->mountres3_u.mountinfo.fhandle.fhandle3_len; nfs->nfsi->rootfh.len = res->mountres3_u.mountinfo.fhandle.fhandle3_len;
nfs->rootfh.val = malloc(nfs->rootfh.len); nfs->nfsi->rootfh.val = malloc(nfs->nfsi->rootfh.len);
if (nfs->rootfh.val == NULL) { if (nfs->nfsi->rootfh.val == NULL) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
free_nfs_cb_data(data); free_nfs_cb_data(data);
return; return;
} }
memcpy(nfs->rootfh.val, memcpy(nfs->nfsi->rootfh.val,
res->mountres3_u.mountinfo.fhandle.fhandle3_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) { if (rpc_mount3_export_async(rpc, nfs3_mount_3_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_set_error(nfs, "%s: %s", __FUNCTION__,
nfs_get_error(nfs)); 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"); rpc_disconnect(rpc, "normal disconnect");
if (nfs->nfsport) { if (nfs->nfsi->nfsport) {
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport, if (rpc_connect_port_async(nfs->rpc, nfs_get_server(nfs),
nfs->nfsi->nfsport,
NFS_PROGRAM, NFS_V3, NFS_PROGRAM, NFS_V3,
nfs3_mount_5_cb, data) != 0) { nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, 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; 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_V3, nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); 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; 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) { data) != 0) {
nfs_set_error(nfs, "%s: %s.", __FUNCTION__, nfs_get_error(nfs)); nfs_set_error(nfs, "%s: %s.", __FUNCTION__, nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); 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)); memset(data, 0, sizeof(struct nfs_cb_data));
new_server = strdup(server); new_server = strdup(server);
new_export = strdup(export); new_export = strdup(export);
if (nfs->server != NULL) { if (nfs->nfsi->server != NULL) {
free(nfs->server); free(nfs->nfsi->server);
} }
nfs->server = new_server; nfs->nfsi->server = new_server;
if (nfs->export != NULL) { if (nfs->nfsi->export != NULL) {
free(nfs->export); free(nfs->nfsi->export);
} }
nfs->export = new_export; nfs->nfsi->export = new_export;
data->nfs = nfs; data->nfs = nfs;
data->cb = cb; data->cb = cb;
data->private_data = private_data; data->private_data = private_data;
if (nfs->mountport) { if (nfs->nfsi->mountport) {
if (rpc_connect_port_async(nfs->rpc, server, nfs->mountport, if (rpc_connect_port_async(nfs->rpc, server, nfs->nfsi->mountport,
MOUNT_PROGRAM, MOUNT_V3, MOUNT_PROGRAM, MOUNT_V3,
nfs3_mount_1_cb, data) != 0) { nfs3_mount_1_cb, data) != 0) {
nfs_set_error(nfs, "Failed to start connection. %s", 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; 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) { data) != 0) {
nfs_set_error(nfs, "%s: %s.", __FUNCTION__, nfs_get_error(nfs)); nfs_set_error(nfs, "%s: %s.", __FUNCTION__, nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); 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"); rpc_disconnect(nfs->rpc, "umount");
if (nfs->mountport) { if (nfs->nfsi->mountport) {
if (rpc_connect_port_async(nfs->rpc, nfs->server, if (rpc_connect_port_async(nfs->rpc, nfs_get_server(nfs),
nfs->mountport, nfs->nfsi->mountport,
MOUNT_PROGRAM, MOUNT_V3, MOUNT_PROGRAM, MOUNT_V3,
nfs3_umount_1_cb, data) != 0) { nfs3_umount_1_cb, data) != 0) {
nfs_set_error(nfs, "Failed to start connection. %s", 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; 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, MOUNT_PROGRAM, MOUNT_V3,
nfs3_umount_1_cb, data) != 0) { nfs3_umount_1_cb, data) != 0) {
nfs_set_error(nfs, "Failed to start connection. %s", 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; splen = 0;
/* No name attributes. Is it a nested mount then?*/ /* 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)) if (strncmp(data->saved_path, mnt->path, splen))
continue; continue;
if (mnt->path[splen] != '/') if (mnt->path[splen] != '/')
@ -3987,6 +4000,98 @@ nfs3_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
return 0; 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 static void
nfs3_stat_1_cb(struct rpc_context *rpc, int status, void *command_data, nfs3_stat_1_cb(struct rpc_context *rpc, int status, void *command_data,
void *private_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->buffer = res->READ3res_u.resok.data.data_val;
data->not_my_buffer = 1; data->not_my_buffer = 1;
} else if (count <= mdata->count) { } 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 */ /* copy data into reassembly buffer */
memcpy(&data->buffer[mdata->offset - data->offset], res->READ3res_u.resok.data.data_val, count); memcpy(&data->buffer[mdata->offset - data->offset], res->READ3res_u.resok.data.data_val, count);
} else { } else {
@ -4738,7 +4850,7 @@ nfs3_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh,
data->private_data = private_data; data->private_data = private_data;
data->nfsfh = nfsfh; data->nfsfh = nfsfh;
data->org_offset = offset; data->org_offset = offset;
data->org_count = (count3)count; data->org_count = count;
data->update_pos = update_pos; data->update_pos = update_pos;
assert(data->num_calls == 0); assert(data->num_calls == 0);
@ -4871,8 +4983,15 @@ nfs3_chdir_continue_internal(struct nfs_context *nfs,
struct nfs_cb_data *data) struct nfs_cb_data *data)
{ {
/* steal saved_path */ /* steal saved_path */
free(nfs->cwd); #ifdef HAVE_MULTITHREADING
nfs->cwd = data->saved_path; 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->saved_path = NULL;
data->cb(0, nfs, NULL, data->private_data); data->cb(0, nfs, NULL, data->private_data);

View File

@ -30,6 +30,14 @@
#include "aros_compat.h" #include "aros_compat.h"
#endif #endif
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef PS3_PPU
#include "ps3_compat.h"
#endif
#ifdef WIN32 #ifdef WIN32
#include <win32/win32_compat.h> #include <win32/win32_compat.h>
#endif #endif
@ -95,6 +103,7 @@
#include "slist.h" #include "slist.h"
#include "libnfs.h" #include "libnfs.h"
#include "libnfs-raw.h" #include "libnfs-raw.h"
#include "libnfs-raw-nfs4.h"
#include "libnfs-private.h" #include "libnfs-private.h"
#ifndef discard_const #ifndef discard_const
@ -143,6 +152,7 @@ struct nfs4_cb_data {
*/ */
#define LOOKUP_FLAG_NO_FOLLOW 0x0001 #define LOOKUP_FLAG_NO_FOLLOW 0x0001
#define LOOKUP_FLAG_IS_STATVFS64 0x0002 #define LOOKUP_FLAG_IS_STATVFS64 0x0002
#define MUTEX_HELD 0x0004
int flags; int flags;
/* Internal callback for open-with-continuation use */ /* Internal callback for open-with-continuation use */
@ -152,6 +162,9 @@ struct nfs4_cb_data {
nfs_cb cb; nfs_cb cb;
void *private_data; void *private_data;
/* Used to track lock_owner during open() */
uint32_t lock_owner;
/* internal callback */ /* internal callback */
rpc_cb continue_cb; rpc_cb continue_cb;
@ -189,6 +202,10 @@ static uint32_t statvfs_attributes[2] = {
1 << (FATTR4_SPACE_TOTAL - 32)) 1 << (FATTR4_SPACE_TOTAL - 32))
}; };
static uint32_t getacl_attributes[1] = {
(1 << FATTR4_ACL )
};
static int static int
nfs4_open_async_internal(struct nfs_context *nfs, struct nfs4_cb_data *data, nfs4_open_async_internal(struct nfs_context *nfs, struct nfs4_cb_data *data,
int flags, int mode); int flags, int mode);
@ -206,9 +223,9 @@ nfs4_resolve_path(struct nfs_context *nfs, const char *path)
if (path[0] == '/') { if (path[0] == '/') {
new_path = strdup(path); new_path = strdup(path);
} else { } else {
new_path = malloc(strlen(path) + strlen(nfs->cwd) + 2); new_path = malloc(strlen(path) + strlen(nfs->nfsi->cwd) + 2);
if (new_path != NULL) { 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) { if (new_path == NULL) {
@ -397,7 +414,8 @@ nfs_pntoh64(const uint32_t *buf)
{ {
uint64_t val; uint64_t val;
val = ntohl(*(uint32_t *)(void *)buf++); val = ntohl(*(uint32_t *)(void *)buf);
buf++;
val <<= 32; val <<= 32;
val |= ntohl(*(uint32_t *)(void *)buf); val |= ntohl(*(uint32_t *)(void *)buf);
@ -625,6 +643,23 @@ nfs4_op_commit(struct nfs_context *nfs, nfs_argop4 *op)
return 1; 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 static int
nfs4_op_close(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh) 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; op[i].argop = OP_CLOSE;
clargs = &op[i++].nfs_argop4_u.opclose; clargs = &op[i++].nfs_argop4_u.opclose;
clargs->seqid = nfs->seqid; clargs->seqid = fh->open_seqid;
clargs->open_stateid.seqid = fh->stateid.seqid; clargs->open_stateid.seqid = fh->stateid.seqid;
memcpy(clargs->open_stateid.other, fh->stateid.other, 12); memcpy(clargs->open_stateid.other, fh->stateid.other, 12);
#ifdef HAVE_MULTITHREADING
i += nfs4_op_release_lockowner(nfs, &op[i], fh);
#endif
return i; return i;
} }
@ -686,8 +725,7 @@ nfs4_op_setclientid(struct nfs_context *nfs, nfs_argop4 *op, verifier4 verifier,
} }
static int static int
nfs4_op_open_confirm(struct nfs_context *nfs, nfs_argop4 *op, uint32_t seqid, nfs4_op_open_confirm(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh)
struct nfsfh *fh)
{ {
OPEN_CONFIRM4args *ocargs; 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 = &op[0].nfs_argop4_u.opopen_confirm;
ocargs->open_stateid.seqid = fh->stateid.seqid; ocargs->open_stateid.seqid = fh->stateid.seqid;
memcpy(&ocargs->open_stateid.other, fh->stateid.other, 12); memcpy(&ocargs->open_stateid.other, fh->stateid.other, 12);
ocargs->seqid = seqid; ocargs->seqid = fh->open_seqid;
return 1; return 1;
} }
@ -732,8 +770,10 @@ nfs4_op_chmod(struct nfs_context *nfs, nfs_argop4 *op, struct nfsfh *fh,
op[0].argop = OP_SETATTR; op[0].argop = OP_SETATTR;
saargs = &op[0].nfs_argop4_u.opsetattr; saargs = &op[0].nfs_argop4_u.opsetattr;
if (fh) {
saargs->stateid.seqid = fh->stateid.seqid; saargs->stateid.seqid = fh->stateid.seqid;
memcpy(saargs->stateid.other, fh->stateid.other, 12); memcpy(saargs->stateid.other, fh->stateid.other, 12);
}
saargs->obj_attributes.attrmask.bitmap4_len = 2; saargs->obj_attributes.attrmask.bitmap4_len = 2;
saargs->obj_attributes.attrmask.bitmap4_val = mask; 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; op[0].argop = OP_SETATTR;
saargs = &op[0].nfs_argop4_u.opsetattr; saargs = &op[0].nfs_argop4_u.opsetattr;
if (fh) {
saargs->stateid.seqid = fh->stateid.seqid; saargs->stateid.seqid = fh->stateid.seqid;
memcpy(saargs->stateid.other, fh->stateid.other, 12); memcpy(saargs->stateid.other, fh->stateid.other, 12);
}
saargs->obj_attributes.attrmask.bitmap4_len = 2; saargs->obj_attributes.attrmask.bitmap4_len = 2;
saargs->obj_attributes.attrmask.bitmap4_val = mask; 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; op[0].argop = OP_SETATTR;
saargs = &op[0].nfs_argop4_u.opsetattr; saargs = &op[0].nfs_argop4_u.opsetattr;
if (fh) {
saargs->stateid.seqid = fh->stateid.seqid; saargs->stateid.seqid = fh->stateid.seqid;
memcpy(saargs->stateid.other, fh->stateid.other, 12); memcpy(saargs->stateid.other, fh->stateid.other, 12);
}
saargs->obj_attributes.attrmask.bitmap4_len = 2; saargs->obj_attributes.attrmask.bitmap4_len = 2;
saargs->obj_attributes.attrmask.bitmap4_val = mask; 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->offset = offset;
largs->length = length; largs->length = length;
if (nfs->has_lock_owner) { if (nfs->nfsi->has_lock_owner) {
largs->locker.new_lock_owner = 0; largs->locker.new_lock_owner = 0;
largs->locker.locker4_u.lock_owner.lock_stateid.seqid = largs->locker.locker4_u.lock_owner.lock_stateid.seqid =
fh->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 { } else {
largs->locker.new_lock_owner = 1; largs->locker.new_lock_owner = 1;
largs->locker.locker4_u.open_owner.open_seqid = largs->locker.locker4_u.open_owner.open_seqid =
nfs->seqid; fh->open_seqid;
largs->locker.locker4_u.open_owner.open_stateid.seqid = largs->locker.locker4_u.open_owner.open_stateid.seqid =
fh->stateid.seqid; fh->stateid.seqid;
memcpy(largs->locker.locker4_u.open_owner.open_stateid.other, memcpy(largs->locker.locker4_u.open_owner.open_stateid.other,
fh->stateid.other, 12); fh->stateid.other, 12);
largs->locker.locker4_u.open_owner.lock_owner.clientid = 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 = 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 = 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 = largs->locker.locker4_u.open_owner.lock_seqid =
fh->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->offset = offset;
ltargs->length = length; ltargs->length = length;
ltargs->owner.clientid = nfs->clientid; ltargs->owner.clientid = nfs->nfsi->clientid;
ltargs->owner.owner.owner_len = strlen(nfs->client_name); ltargs->owner.owner.owner_len = strlen(nfs->nfsi->client_name);
ltargs->owner.owner.owner_val = nfs->client_name; ltargs->owner.owner.owner_val = nfs->nfsi->client_name;
return 1; return 1;
} }
@ -1091,11 +1135,11 @@ nfs4_allocate_op(struct nfs_context *nfs, nfs_argop4 **op,
} }
i = 0; i = 0;
if (nfs->rootfh.len) { if (nfs->nfsi->rootfh.len) {
struct nfsfh fh; struct nfsfh fh;
fh.fh.len = nfs->rootfh.len; fh.fh.len = nfs->nfsi->rootfh.len;
fh.fh.val = nfs->rootfh.val; fh.fh.val = nfs->nfsi->rootfh.val;
i += nfs4_op_putfh(nfs, &(*op)[i], &fh); i += nfs4_op_putfh(nfs, &(*op)[i], &fh);
} else { } else {
i += nfs4_op_putrootfh(nfs, &(*op)[i]); 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; 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) { if (tmp == NULL) {
nfs_set_error(nfs, "Out of memory duplicating path."); nfs_set_error(nfs, "Out of memory duplicating path.");
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), 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; 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(path);
free(data->path); free(data->path);
data->path = tmp; 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; gfhresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4;
nfs->rootfh.len = gfhresok->object.nfs_fh4_len; nfs->nfsi->rootfh.len = gfhresok->object.nfs_fh4_len;
nfs->rootfh.val = malloc(nfs->rootfh.len); nfs->nfsi->rootfh.val = malloc(nfs->nfsi->rootfh.len);
if (nfs->rootfh.val == NULL) { if (nfs->nfsi->rootfh.val == NULL) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs)); nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
free_nfs4_cb_data(data); free_nfs4_cb_data(data);
return; return;
} }
memcpy(nfs->rootfh.val, memcpy(nfs->nfsi->rootfh.val,
gfhresok->object.nfs_fh4_val, gfhresok->object.nfs_fh4_val,
nfs->rootfh.len); nfs->nfsi->rootfh.len);
data->cb(0, nfs, NULL, data->private_data); 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; scidresok = &res->resarray.resarray_val[0].nfs_resop4_u.opsetclientid.SETCLIENTID4res_u.resok4;
nfs->clientid = scidresok->clientid; nfs->nfsi->clientid = scidresok->clientid;
memcpy(nfs->setclientid_confirm, memcpy(nfs->nfsi->setclientid_confirm,
scidresok->setclientid_confirm, scidresok->setclientid_confirm,
NFS4_VERIFIER_SIZE); NFS4_VERIFIER_SIZE);
memset(op, 0, sizeof(op)); memset(op, 0, sizeof(op));
i = nfs4_op_setclientid_confirm(nfs, &op[0], nfs->clientid, i = nfs4_op_setclientid_confirm(nfs, &op[0], nfs->nfsi->clientid,
nfs->setclientid_confirm); nfs->nfsi->setclientid_confirm);
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.argarray.argarray_len = i; 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)); 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)); memset(&args, 0, sizeof(args));
args.argarray.argarray_len = i; args.argarray.argarray_len = i;
@ -1589,8 +1635,8 @@ nfs4_mount_async(struct nfs_context *nfs, const char *server,
int port; int port;
new_server = strdup(server); new_server = strdup(server);
free(nfs->server); free(nfs->nfsi->server);
nfs->server = new_server; nfs->nfsi->server = new_server;
new_export = strdup(export); new_export = strdup(export);
if (nfs_normalize_path(nfs, new_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); free(new_export);
return -1; return -1;
} }
free(nfs->export); free(nfs->nfsi->export);
nfs->export = new_export; nfs->nfsi->export = new_export;
data = malloc(sizeof(*data)); data = malloc(sizeof(*data));
@ -1616,7 +1662,7 @@ nfs4_mount_async(struct nfs_context *nfs, const char *server,
data->private_data = private_data; data->private_data = private_data;
data->path = strdup(new_export); 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, if (rpc_connect_port_async(nfs->rpc, server, port,
NFS4_PROGRAM, NFS_V4, NFS4_PROGRAM, NFS_V4,
nfs4_mount_1_cb, data) != 0) { 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. */ /* Ok, all good. Lets steal the path string. */
free(nfs->cwd); #ifdef HAVE_MULTITHREADING
nfs->cwd = data->path; 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->path = NULL;
data->cb(0, nfs, NULL, data->private_data); data->cb(0, nfs, NULL, data->private_data);
@ -1895,7 +1948,7 @@ nfs4_rmdir_async(struct nfs_context *nfs, const char *path,
} }
static void 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 */ /* RFC3530 8.1.5 */
switch (status) { switch (status) {
@ -1908,7 +1961,7 @@ nfs_increment_seqid(struct nfs_context *nfs, uint32_t status)
case NFS4ERR_NOFILEHANDLE: case NFS4ERR_NOFILEHANDLE:
break; break;
default: 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; COMPOUND4res *res = command_data;
OPEN_CONFIRM4resok *ocresok; OPEN_CONFIRM4resok *ocresok;
int i; int i;
struct nfsfh *fh; struct nfsfh *fh = data->filler.blob0.val;
assert(rpc->magic == RPC_CONTEXT_MAGIC); assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (res) { if (res) {
nfs_increment_seqid(nfs, res->status); nfs_increment_seqid(fh, res->status);
} }
if (check_nfs4_error(nfs, status, data, res, "OPEN_CONFIRM")) { 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); assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (res) {
nfs_increment_seqid(nfs, res->status);
}
if (check_nfs4_error(nfs, status, data, res, "OPEN")) { if (check_nfs4_error(nfs, status, data, res, "OPEN")) {
return; return;
} }
@ -2101,6 +2150,8 @@ nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data,
return; return;
} }
memcpy(fh->fh.val, gresok->object.nfs_fh4_val, fh->fh.len); 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) { if (data->filler.flags & O_SYNC) {
fh->is_sync = 1; 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)); memset(op, 0, sizeof(op));
i = nfs4_op_putfh(nfs, &op[0], fh); 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)); memset(&args, 0, sizeof(args));
args.argarray.argarray_len = i; 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; oargs = &op[i++].nfs_argop4_u.opopen;
memset(oargs, 0, sizeof(*oargs)); memset(oargs, 0, sizeof(*oargs));
oargs->seqid = nfs->seqid;
if (access_mask & ACCESS4_READ) { if (access_mask & ACCESS4_READ) {
oargs->share_access |= OPEN4_SHARE_ACCESS_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_access |= OPEN4_SHARE_ACCESS_WRITE;
} }
oargs->share_deny = OPEN4_SHARE_DENY_NONE; oargs->share_deny = OPEN4_SHARE_DENY_NONE;
oargs->owner.clientid = nfs->clientid; oargs->owner.clientid = nfs->nfsi->clientid;
oargs->owner.owner.owner_len = strlen(nfs->client_name); oargs->owner.owner.owner_len = 4;
oargs->owner.owner.owner_val = nfs->client_name; oargs->owner.owner.owner_val = (char *)&data->lock_owner;
oargs->seqid = 0;
if (data->filler.flags & O_CREAT) { if (data->filler.flags & O_CREAT) {
createhow4 *ch; createhow4 *ch;
fattr4 *fa; 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; rlresok = &res->resarray.resarray_val[i].nfs_resop4_u.opreadlink.READLINK4res_u.resok4;
path = malloc(2 + strlen(data->path) + path = malloc(2 + strlen(data->path) +
strlen(rlresok->link.utf8string_val)); rlresok->link.utf8string_len);
if (path == NULL) { if (path == NULL) {
nfs_set_error(nfs, "Out of memory. Failed to allocate " nfs_set_error(nfs, "Out of memory. Failed to allocate "
"path"); "path");
@ -2280,8 +2331,8 @@ nfs4_open_readlink_cb(struct rpc_context *rpc, int status, void *command_data,
free_nfs4_cb_data(data); free_nfs4_cb_data(data);
return; 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); free(data->path);
@ -2300,6 +2351,14 @@ nfs4_open_readlink_cb(struct rpc_context *rpc, int status, void *command_data,
data_split_path(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.func = nfs4_populate_open;
data->filler.max_op = 3; 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; 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.func = nfs4_populate_open;
data->filler.max_op = 3; data->filler.max_op = 3;
data->filler.flags = flags; 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; struct nfs4_cb_data *data;
uint32_t m; uint32_t m;
int ret;
data = init_cb_data_split_path(nfs, path); data = init_cb_data_split_path(nfs, path);
if (data == NULL) { 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)); 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 int
@ -2520,6 +2588,86 @@ nfs4_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
return 0; 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 static void
nfs4_close_cb(struct rpc_context *rpc, int status, void *command_data, nfs4_close_cb(struct rpc_context *rpc, int status, void *command_data,
void *private_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 nfs4_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs; struct nfs_context *nfs = data->nfs;
COMPOUND4res *res = command_data; COMPOUND4res *res = command_data;
struct nfsfh *nfsfh = data->filler.blob0.val;
assert(rpc->magic == RPC_CONTEXT_MAGIC); assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (res) { if (res) {
nfs_increment_seqid(nfs, res->status); nfs_increment_seqid(nfsfh, res->status);
} }
if (check_nfs4_error(nfs, status, data, res, "CLOSE")) { 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) void *private_data)
{ {
COMPOUND4args args; COMPOUND4args args;
nfs_argop4 op[3]; nfs_argop4 op[4];
struct nfs4_cb_data *data; struct nfs4_cb_data *data;
int i; int i;
@ -2730,6 +2879,7 @@ nfs4_readlink_cb(struct rpc_context *rpc, int status, void *command_data,
struct nfs_context *nfs = data->nfs; struct nfs_context *nfs = data->nfs;
COMPOUND4res *res = command_data; COMPOUND4res *res = command_data;
READLINK4resok *rlresok; READLINK4resok *rlresok;
char* target;
int i; int i;
assert(rpc->magic == RPC_CONTEXT_MAGIC); 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; 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); 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_len = i;
args.argarray.argarray_val = op; args.argarray.argarray_val = op;
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_pwrite_cb, &args, if (rpc_nfs4_compound_async2(nfs->rpc, nfs4_pwrite_cb, &args,
data) != 0) { data, count) != 0) {
nfs_set_error(nfs, "PWRITE "
"failed: %s", rpc_get_error(nfs->rpc));
free_nfs4_cb_data(data); free_nfs4_cb_data(data);
return -1; return -EIO;
} }
return 0; 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.len = (int)count;
data->filler.blob1.free = NULL; data->filler.blob1.free = NULL;
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_write_append_cb, if (rpc_nfs4_compound_async2(nfs->rpc, nfs4_write_append_cb,
&args, data) != 0) { &args, data, count) != 0) {
nfs_set_error(nfs, "PWRITE "
"failed: %s", rpc_get_error(nfs->rpc));
free_nfs4_cb_data(data); free_nfs4_cb_data(data);
return -1; return -EIO;
} }
return 0; return 0;
@ -3474,6 +3637,7 @@ nfs4_parse_readdir(struct nfs_context *nfs, struct nfs4_cb_data *data,
return; return;
} }
nfsdirent->inode = st.nfs_ino;
nfsdirent->mode = (uint32_t)st.nfs_mode; nfsdirent->mode = (uint32_t)st.nfs_mode;
switch (st.nfs_mode & S_IFMT) { switch (st.nfs_mode & S_IFMT) {
case S_IFREG: 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 nfs4_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs; struct nfs_context *nfs = data->nfs;
COMPOUND4res *res = command_data; COMPOUND4res *res = command_data;
struct nfsfh *fh = data->filler.blob0.val;
assert(rpc->magic == RPC_CONTEXT_MAGIC); assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (res) { if (res) {
nfs_increment_seqid(nfs, res->status); nfs_increment_seqid(fh, res->status);
} }
if (check_nfs4_error(nfs, status, data, res, "CLOSE")) { 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; 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; fh->lock_stateid.seqid = lresok->lock_stateid.seqid;
memcpy(fh->lock_stateid.other, lresok->lock_stateid.other, 12); memcpy(fh->lock_stateid.other, lresok->lock_stateid.other, 12);
break; 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; 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; fh->lock_stateid.seqid = lresok->lock_stateid.seqid;
memcpy(fh->lock_stateid.other, memcpy(fh->lock_stateid.other,
lresok->lock_stateid.other, 12); 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; data->flags |= LOOKUP_FLAG_IS_STATVFS64;
} }
fh.fh.len = nfs->rootfh.len; fh.fh.len = nfs->nfsi->rootfh.len;
fh.fh.val = nfs->rootfh.val; fh.fh.val = nfs->nfsi->rootfh.val;
i = nfs4_op_putfh(nfs, &op[0], &fh); i = nfs4_op_putfh(nfs, &op[0], &fh);
i += nfs4_op_getattr(nfs, &op[i], statvfs_attributes, 2); 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 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) void *private_data)
{ {
struct nfs4_cb_data *data = private_data; struct nfs4_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs; struct nfs_context *nfs = data->nfs;
struct nfsfh *fh = data->filler.blob0.val;
COMPOUND4res *res = command_data; 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; return;
} }
i = nfs4_op_putfh(nfs, &op[0], fh); data->cb(0, nfs, NULL, data->private_data);
i += nfs4_op_chmod(nfs, &op[i], fh, data->filler.blob3.val);
i += nfs4_op_close(nfs, &op[i], fh);
memset(&args, 0, sizeof(args));
args.argarray.argarray_len = i;
args.argarray.argarray_val = op;
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_close_cb, &args,
data) != 0) {
/* Not much we can do but leak one fd on the server :( */
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
free_nfs4_cb_data(data); 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 int
@ -4621,14 +4775,15 @@ nfs4_chmod_async_internal(struct nfs_context *nfs, const char *path,
struct nfs4_cb_data *data; struct nfs4_cb_data *data;
uint32_t m; uint32_t m;
data = init_cb_data_split_path(nfs, path); data = init_cb_data_full_path(nfs, path);
if (data == NULL) { if (data == NULL) {
return -1; return -1;
} }
data->cb = cb; data->cb = cb;
data->private_data = private_data; 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) { if (no_follow) {
data->flags |= LOOKUP_FLAG_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); m = htonl(mode);
memcpy(data->filler.blob3.val, &m, sizeof(uint32_t)); 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; return -1;
} }
@ -4754,37 +4909,26 @@ nfs4_create_chown_buffer(struct nfs_context *nfs, struct nfs4_cb_data *data,
} }
static void 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) void *private_data)
{ {
struct nfs4_cb_data *data = private_data; struct nfs4_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs; struct nfs_context *nfs = data->nfs;
struct nfsfh *fh = data->filler.blob0.val;
COMPOUND4res *res = command_data; 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, "OPEN")) {
return; return;
} }
i = nfs4_op_putfh(nfs, &op[0], fh); data->cb(0, nfs, NULL, data->private_data);
i += nfs4_op_chown(nfs, &op[i], fh, data->filler.blob3.val,
data->filler.blob3.len);
i += nfs4_op_close(nfs, &op[i], fh);
memset(&args, 0, sizeof(args));
args.argarray.argarray_len = i;
args.argarray.argarray_val = op;
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_close_cb, &args,
data) != 0) {
/* Not much we can do but leak one fd on the server :( */
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
free_nfs4_cb_data(data); 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 int
@ -4801,7 +4945,8 @@ nfs4_chown_async_internal(struct nfs_context *nfs, const char *path,
data->cb = cb; data->cb = cb;
data->private_data = private_data; 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) { if (no_follow) {
data->flags |= LOOKUP_FLAG_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; 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; return -1;
} }
@ -4976,37 +5121,28 @@ nfs4_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
} }
static void 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) void *private_data)
{ {
struct nfs4_cb_data *data = private_data; struct nfs4_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs; struct nfs_context *nfs = data->nfs;
struct nfsfh *fh = data->filler.blob0.val;
COMPOUND4res *res = command_data; 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; return;
} }
i = nfs4_op_putfh(nfs, &op[0], fh); data->cb(0, nfs, NULL, data->private_data);
i += nfs4_op_utimes(nfs, &op[i], fh, data->filler.blob3.val,
data->filler.blob3.len);
i += nfs4_op_close(nfs, &op[i], fh);
memset(&args, 0, sizeof(args));
args.argarray.argarray_len = i;
args.argarray.argarray_val = op;
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_close_cb, &args,
data) != 0) {
/* Not much we can do but leak one fd on the server :( */
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
free_nfs4_cb_data(data); 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 int
@ -5019,14 +5155,15 @@ nfs4_utimes_async_internal(struct nfs_context *nfs, const char *path,
uint32_t u32; uint32_t u32;
uint64_t u64; uint64_t u64;
data = init_cb_data_split_path(nfs, path); data = init_cb_data_full_path(nfs, path);
if (data == NULL) { if (data == NULL) {
return -1; return -1;
} }
data->cb = cb; data->cb = cb;
data->private_data = private_data; 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) { if (no_follow) {
data->flags |= LOOKUP_FLAG_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"); nfs_set_error(nfs, "Out of memory");
return -1; return -1;
} }
memset(buf, 0, data->filler.blob3.len);
data->filler.blob3.free = free; data->filler.blob3.free = free;
if (times != NULL) {
/* atime */ /* atime */
u32 = htonl(SET_TO_CLIENT_TIME4); u32 = htonl(SET_TO_CLIENT_TIME4);
memcpy(buf, &u32, sizeof(uint32_t)); 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)); memcpy(buf + 4, &u64, sizeof(uint64_t));
u32 = htonl(times[1].tv_usec * 1000); u32 = htonl(times[1].tv_usec * 1000);
memcpy(buf + 12, &u32, sizeof(uint32_t)); 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; return -1;
} }
@ -5067,6 +5216,10 @@ int
nfs4_utime_async(struct nfs_context *nfs, const char *path, nfs4_utime_async(struct nfs_context *nfs, const char *path,
struct utimbuf *times, nfs_cb cb, void *private_data) 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]; struct timeval new_times[2];
new_times[0].tv_sec = times->actime; new_times[0].tv_sec = times->actime;

View File

@ -23,6 +23,14 @@
#include "aros_compat.h" #include "aros_compat.h"
#endif #endif
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef PS3_PPU
#include "ps3_compat.h"
#endif
#ifdef WIN32 #ifdef WIN32
#include <win32/win32_compat.h> #include <win32/win32_compat.h>
#endif #endif
@ -152,7 +160,13 @@ struct rpc_pdu *rpc_allocate_pdu2(struct rpc_context *rpc, int program, int vers
return NULL; return NULL;
} }
memset(pdu, 0, pdu_size); memset(pdu, 0, pdu_size);
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
pdu->xid = rpc->xid++; pdu->xid = rpc->xid++;
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
pdu->cb = cb; pdu->cb = cb;
pdu->private_data = private_data; pdu->private_data = private_data;
pdu->zdr_decode_fn = zdr_decode_fn; 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) 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; 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 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); 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); 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_enqueue(&rpc->waitpdu[hash], pdu);
rpc->waitpdu_len++; rpc->waitpdu_len++;
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
return 0; return 0;
} }
@ -266,7 +293,18 @@ int rpc_queue_pdu(struct rpc_context *rpc, struct rpc_pdu *pdu)
zdr_int(&pdu->zdr, &recordmarker); zdr_int(&pdu->zdr, &recordmarker);
pdu->outdata.size = size; pdu->outdata.size = size;
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
rpc_enqueue(&rpc->outqueue, pdu); 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; return 0;
} }
@ -440,7 +478,8 @@ static int rpc_process_call(struct rpc_context *rpc, ZDR *zdr)
if (endpoint == NULL) { if (endpoint == NULL) {
rpc_set_error(rpc, "No endpoint found for CALL " rpc_set_error(rpc, "No endpoint found for CALL "
"program:0x%08x version:%d\n", "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) { if (!found_program) {
return rpc_send_error_reply(rpc, &call, PROG_UNAVAIL, return rpc_send_error_reply(rpc, &call, PROG_UNAVAIL,
0, 0); 0, 0);
@ -470,7 +509,8 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
struct rpc_pdu *pdu, *prev_pdu; struct rpc_pdu *pdu, *prev_pdu;
struct rpc_queue *q; struct rpc_queue *q;
ZDR zdr; ZDR zdr;
int pos, recordmarker = 0; int pos;
int32_t recordmarker = 0;
unsigned int hash; unsigned int hash;
uint32_t xid; uint32_t xid;
char *reasbuf = NULL; char *reasbuf = NULL;
@ -505,6 +545,11 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
zdr_destroy(&zdr); zdr_destroy(&zdr);
for (fragment = rpc->fragments; fragment; fragment = fragment->next) { for (fragment = rpc->fragments; fragment; fragment = fragment->next) {
total += fragment->size; total += fragment->size;
if (total < fragment->size) {
rpc_set_error(rpc, "Fragments too large");
rpc_free_all_fragments(rpc);
return -1;
}
} }
reasbuf = malloc(total); reasbuf = malloc(total);
@ -535,7 +580,7 @@ int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size)
} }
pos = zdr_getpos(&zdr); 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"); rpc_set_error(rpc, "zdr_int reading xid failed");
zdr_destroy(&zdr); zdr_destroy(&zdr);
if (reasbuf != NULL) { 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 */ /* Look up the transaction in a hash table of our requests */
hash = rpc_hash_xid(xid); hash = rpc_hash_xid(xid);
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
q = &rpc->waitpdu[hash]; q = &rpc->waitpdu[hash];
/* Follow the hash chain. Linear traverse singly-linked list, /* 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; prev_pdu->next = pdu->next;
rpc->waitpdu_len--; rpc->waitpdu_len--;
} }
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
if (rpc_process_reply(rpc, pdu, &zdr) != 0) { if (rpc_process_reply(rpc, pdu, &zdr) != 0) {
rpc_set_error(rpc, "rpc_procdess_reply failed"); 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; return 0;
} }
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
zdr_destroy(&zdr); zdr_destroy(&zdr);
if (reasbuf != NULL) { if (reasbuf != NULL) {

View File

@ -23,6 +23,14 @@
#include "aros_compat.h" #include "aros_compat.h"
#endif #endif
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef PS3_PPU
#include "ps3_compat.h"
#endif
#ifdef WIN32 #ifdef WIN32
#include <win32/win32_compat.h> #include <win32/win32_compat.h>
#endif #endif
@ -87,7 +95,7 @@
#endif #endif
#ifndef MSG_NOSIGNAL #ifndef MSG_NOSIGNAL
#if (defined(__APPLE__) && defined(__MACH__)) #if (defined(__APPLE__) && defined(__MACH__)) || defined(PS2_EE)
#define MSG_NOSIGNAL 0 #define MSG_NOSIGNAL 0
#endif #endif
#endif #endif
@ -122,17 +130,19 @@ set_nonblocking(int fd)
#else #else
v = fcntl(fd, F_GETFL, 0); v = fcntl(fd, F_GETFL, 0);
v = fcntl(fd, F_SETFL, v | O_NONBLOCK); v = fcntl(fd, F_SETFL, v | O_NONBLOCK);
#endif //FIXME #endif
return v; return v;
} }
static void static void
set_nolinger(int fd) set_nolinger(int fd)
{ {
#if !defined(PS2_EE)
struct linger lng; struct linger lng;
lng.l_onoff = 1; lng.l_onoff = 1;
lng.l_linger = 0; lng.l_linger = 0;
setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&lng, sizeof(lng)); setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&lng, sizeof(lng));
#endif
} }
static int static int
@ -204,17 +214,24 @@ rpc_which_events(struct rpc_context *rpc)
return POLLIN; return POLLIN;
} }
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
if (rpc_has_queue(&rpc->outqueue)) { if (rpc_has_queue(&rpc->outqueue)) {
events |= POLLOUT; events |= POLLOUT;
} }
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
return events; return events;
} }
static int int
rpc_write_to_socket(struct rpc_context *rpc) rpc_write_to_socket(struct rpc_context *rpc)
{ {
int32_t count; int32_t count;
struct rpc_pdu *pdu; struct rpc_pdu *pdu;
int ret = 0;
assert(rpc->magic == RPC_CONTEXT_MAGIC); assert(rpc->magic == RPC_CONTEXT_MAGIC);
@ -223,6 +240,9 @@ rpc_write_to_socket(struct rpc_context *rpc)
return -1; return -1;
} }
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
while ((pdu = rpc->outqueue.head) != NULL) { while ((pdu = rpc->outqueue.head) != NULL) {
int64_t total; int64_t total;
@ -232,11 +252,13 @@ rpc_write_to_socket(struct rpc_context *rpc)
(int)(total - pdu->written), MSG_NOSIGNAL); (int)(total - pdu->written), MSG_NOSIGNAL);
if (count == -1) { if (count == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) { if (errno == EAGAIN || errno == EWOULDBLOCK) {
return 0; ret = 0;
goto finished;
} }
rpc_set_error(rpc, "Error when writing to socket :%s" rpc_set_error(rpc, "Error when writing to socket :%s"
"(%d)", strerror(errno), errno); "(%d)", strerror(errno), errno);
return -1; ret = -1;
goto finished;
} }
pdu->written += count; pdu->written += count;
@ -249,7 +271,8 @@ rpc_write_to_socket(struct rpc_context *rpc)
if (pdu->flags & PDU_DISCARD_AFTER_SENDING) { if (pdu->flags & PDU_DISCARD_AFTER_SENDING) {
rpc_free_pdu(rpc, pdu); rpc_free_pdu(rpc, pdu);
return 0; ret = 0;
goto finished;
} }
hash = rpc_hash_xid(pdu->xid); hash = rpc_hash_xid(pdu->xid);
@ -257,7 +280,12 @@ rpc_write_to_socket(struct rpc_context *rpc)
rpc->waitpdu_len++; 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 #define MAX_UDP_SIZE 65536
@ -300,6 +328,7 @@ rpc_read_from_socket(struct rpc_context *rpc)
return 0; return 0;
} }
again:
do { do {
/* Read record marker, /* Read record marker,
* 4 bytes at the beginning of every pdu. * 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 " "buffer of %d bytes for "
"pdu, errno:%d. Closing " "pdu, errno:%d. Closing "
"socket.", "socket.",
pdu_size, errno); (int)pdu_size, errno);
return -1; return -1;
} }
memcpy(rpc->inbuf, &rpc->rm_buf, 4); memcpy(rpc->inbuf, &rpc->rm_buf, 4);
@ -350,7 +379,7 @@ rpc_read_from_socket(struct rpc_context *rpc)
if (rpc->inpos == 4) { if (rpc->inpos == 4) {
/* We have just read the header and there is likely /* We have just read the header and there is likely
* more data available */ * more data available */
continue; goto again;
} }
if (rpc->inpos == pdu_size) { if (rpc->inpos == pdu_size) {
@ -392,6 +421,9 @@ rpc_timeout_scan(struct rpc_context *rpc)
uint64_t t = rpc_current_time(); uint64_t t = rpc_current_time();
unsigned int i; 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) { for (pdu = rpc->outqueue.head; pdu; pdu = next_pdu) {
next_pdu = pdu->next; next_pdu = pdu->next;
@ -405,7 +437,7 @@ rpc_timeout_scan(struct rpc_context *rpc)
} }
LIBNFS_LIST_REMOVE(&rpc->outqueue.head, pdu); LIBNFS_LIST_REMOVE(&rpc->outqueue.head, pdu);
if (!rpc->outqueue.head) { if (!rpc->outqueue.head) {
rpc->outqueue.tail = NULL; rpc->outqueue.tail = NULL; //done
} }
rpc_set_error(rpc, "command timed out"); rpc_set_error(rpc, "command timed out");
pdu->cb(rpc, RPC_STATUS_TIMEOUT, pdu->cb(rpc, RPC_STATUS_TIMEOUT,
@ -413,8 +445,9 @@ rpc_timeout_scan(struct rpc_context *rpc)
rpc_free_pdu(rpc, pdu); rpc_free_pdu(rpc, pdu);
} }
for (i = 0; i < HASHES; i++) { 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) { for (pdu = q->head; pdu; pdu = next_pdu) {
next_pdu = pdu->next; next_pdu = pdu->next;
@ -430,12 +463,17 @@ rpc_timeout_scan(struct rpc_context *rpc)
if (!q->head) { if (!q->head) {
q->tail = NULL; q->tail = NULL;
} }
// qqq move to a temporary queue and process after
// we drop the mutex
rpc_set_error(rpc, "command timed out"); rpc_set_error(rpc, "command timed out");
pdu->cb(rpc, RPC_STATUS_TIMEOUT, pdu->cb(rpc, RPC_STATUS_TIMEOUT,
NULL, pdu->private_data); NULL, pdu->private_data);
rpc_free_pdu(rpc, pdu); rpc_free_pdu(rpc, pdu);
} }
} }
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
} }
int int
@ -597,7 +635,7 @@ rpc_connect_sockaddr_async(struct rpc_context *rpc)
} }
if (rpc->old_fd) { if (rpc->old_fd) {
#if !defined(WIN32) #if !defined(WIN32) && !defined(PS3_PPU) && !defined(PS2_EE)
if (dup2(rpc->fd, rpc->old_fd) == -1) { if (dup2(rpc->fd, rpc->old_fd) == -1) {
return -1; return -1;
} }
@ -663,6 +701,7 @@ rpc_connect_sockaddr_async(struct rpc_context *rpc)
sizeof(struct sockaddr_in); sizeof(struct sockaddr_in);
#endif #endif
break; break;
#if !defined(PS3_PPU) && !defined(PS2_EE)
case AF_INET6: case AF_INET6:
sin6->sin6_port = port; sin6->sin6_port = port;
sin6->sin6_family = AF_INET6; sin6->sin6_family = AF_INET6;
@ -671,6 +710,7 @@ rpc_connect_sockaddr_async(struct rpc_context *rpc)
sizeof(struct sockaddr_in6); sizeof(struct sockaddr_in6);
#endif #endif
break; break;
#endif
} }
rc = bind(rpc->fd, (struct sockaddr *)&ss, 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); sizeof(struct sockaddr_in);
#endif #endif
break; break;
#if !defined(PS3_PPU) && !defined(PS2_EE)
case AF_INET6: case AF_INET6:
((struct sockaddr_in6 *)&rpc->s)->sin6_family = ai->ai_family; ((struct sockaddr_in6 *)&rpc->s)->sin6_family = ai->ai_family;
((struct sockaddr_in6 *)&rpc->s)->sin6_port = htons(port); ((struct sockaddr_in6 *)&rpc->s)->sin6_port = htons(port);
@ -729,6 +770,7 @@ rpc_set_sockaddr(struct rpc_context *rpc, const char *server, int port)
sizeof(struct sockaddr_in6); sizeof(struct sockaddr_in6);
#endif #endif
break; break;
#endif
} }
freeaddrinfo(ai); freeaddrinfo(ai);
@ -795,6 +837,7 @@ rpc_disconnect(struct rpc_context *rpc, const char *error)
rpc_error_all_pdus(rpc, error); rpc_error_all_pdus(rpc, error);
} }
maybe_call_connect_cb(rpc, RPC_STATUS_CANCEL);
return 0; 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 * in flight. Move them all over from the waitpdu queue back to the
* out queue. * 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++) { for (i = 0; i < HASHES; i++) {
struct rpc_queue *q = &rpc->waitpdu[i]; struct rpc_queue *q = &rpc->waitpdu[i];
for (pdu = q->head; pdu; pdu = next) { for (pdu = q->head; pdu; pdu = next) {
@ -861,6 +908,9 @@ rpc_reconnect_requeue(struct rpc_context *rpc)
rpc_reset_queue(q); rpc_reset_queue(q);
} }
rpc->waitpdu_len = 0; 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) { if (rpc->auto_reconnect < 0 || rpc->num_retries > 0) {
rpc->num_retries--; rpc->num_retries--;
@ -982,7 +1032,13 @@ rpc_queue_length(struct rpc_context *rpc)
i++; i++;
} }
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_lock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
i += rpc->waitpdu_len; i += rpc->waitpdu_len;
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_unlock(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
return i; return i;
} }

View File

@ -15,6 +15,10 @@
along with this program; if not, see <http://www.gnu.org/licenses/>. along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef WIN32 #ifdef WIN32
#include <win32/win32_compat.h> #include <win32/win32_compat.h>
#endif/*WIN32*/ #endif/*WIN32*/

View File

@ -20,6 +20,7 @@ nfs-stamp : nfs.x
compile_rpc: compile_rpc:
cat nfs.x | head -29 >libnfs-raw-nfs.h 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 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 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

View File

@ -2005,6 +2005,57 @@ extern uint32_t zdr_SETACL3res ();
#endif /* K&R C */ #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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -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 */

View File

@ -15,6 +15,10 @@
along with this program; if not, see <http://www.gnu.org/licenses/>. along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef WIN32 #ifdef WIN32
#include <win32/win32_compat.h> #include <win32/win32_compat.h>
#else #else

View File

@ -96,3 +96,4 @@ int rpc_nfsacl_setacl_async(struct rpc_context *rpc, rpc_cb cb, struct SETACL3ar
return 0; return 0;
} }

View File

@ -19,7 +19,7 @@ nfs4-stamp : nfs4.x
touch nfs4-stamp touch nfs4-stamp
compile_rpc: 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 \ rpcgen -h nfs4.x | sed \
-e "s/#include <rpc\/rpc.h>/#include <nfsc\/libnfs-zdr.h>/" \ -e "s/#include <rpc\/rpc.h>/#include <nfsc\/libnfs-zdr.h>/" \
-e "s/xdr/zdr/g" \ -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/#define NFS3_COOKIEVERFSIZE 8/#define NFS3_COOKIEVERFSIZE 8\n\n/g" \
-e "s/ CLIENT / void /g" \ -e "s/ CLIENT / void /g" \
-e "s/SVCXPRT /void /g" \ -e "s/SVCXPRT /void /g" \
-e "s/bool_t/uint32_t/g" >> libnfs-raw-nfs4.h -e "s/bool_t/uint32_t/g" | head --lines=-5 >>libnfs-raw-nfs4.h
cat nfs4.x | head -29 >libnfs-raw-nfs4.c cat libnfs-raw-nfs4.h.extra >>libnfs-raw-nfs4.h
cat nfs4.x | head -16 >libnfs-raw-nfs4.c
rpcgen -c nfs4.x | sed \ rpcgen -c nfs4.x | sed \
-e "s/#include \".*nfs4.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nfs4.h\"/" \ -e "s/#include \".*nfs4.h\"/#include \"libnfs-xdr.h\"\n#include \"libnfs-raw-nfs4.h\"/" \
-e "s/xdr/zdr/g" \ -e "s/xdr/zdr/g" \

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -16,6 +16,10 @@
along with this program; if not, see <http://www.gnu.org/licenses/>. along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef PS2_EE
#include "ps2_compat.h"
#endif
#ifdef WIN32 #ifdef WIN32
#include <win32/win32_compat.h> #include <win32/win32_compat.h>
#else #else
@ -202,14 +206,17 @@ rpc_nfs4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
} }
int int
rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb, rpc_nfs4_compound_async2(struct rpc_context *rpc, rpc_cb cb,
struct COMPOUND4args *args, void *private_data) struct COMPOUND4args *args,
void *private_data,
size_t alloc_hint)
{ {
struct rpc_pdu *pdu; 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, cb, private_data, (zdrproc_t)zdr_COMPOUND4res,
sizeof(COMPOUND4res)); sizeof(COMPOUND4res),
alloc_hint);
if (pdu == NULL) { if (pdu == NULL) {
rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for " rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for "
"NFS4/COMPOUND call"); "NFS4/COMPOUND call");
@ -230,3 +237,12 @@ rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
return 0; 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);
}

View File

@ -21,7 +21,7 @@
const NFS4_FHSIZE = 128; const NFS4_FHSIZE = 128;
const NFS4_VERIFIER_SIZE = 8; const NFS4_VERIFIER_SIZE = 8;
const NFS4_OPAQUE_LIMIT = 1024; const NFS4_OPAQUE_LIMIT = 1024;
const NFS4_SESSIONID_SIZE = 16;
/* /*
* File types * File types
*/ */
@ -107,7 +107,20 @@ enum nfsstat4 {
NFS4ERR_DEADLOCK = 10045,/* file locking deadlock */ NFS4ERR_DEADLOCK = 10045,/* file locking deadlock */
NFS4ERR_FILE_OPEN = 10046,/* open file blocks op. */ NFS4ERR_FILE_OPEN = 10046,/* open file blocks op. */
NFS4ERR_ADMIN_REVOKED = 10047,/* lockowner state revoked */ 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 uint32_t count4;
typedef uint64_t length4; typedef uint64_t length4;
typedef uint64_t clientid4; typedef uint64_t clientid4;
typedef uint32_t sequenceid4;
typedef uint32_t seqid4; typedef uint32_t seqid4;
typedef uint32_t slotid4;
typedef opaque utf8string<>; typedef opaque utf8string<>;
typedef utf8string utf8str_cis; typedef utf8string utf8str_cis;
typedef utf8string utf8str_cs; typedef utf8string utf8str_cs;
@ -133,6 +148,38 @@ typedef uint32_t qop4;
typedef uint32_t mode4; typedef uint32_t mode4;
typedef uint64_t changeid4; typedef uint64_t changeid4;
typedef opaque verifier4[NFS4_VERIFIER_SIZE]; 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 * Timeval
@ -147,6 +194,24 @@ enum time_how4 {
SET_TO_CLIENT_TIME4 = 1 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) { union settime4 switch (time_how4 set_it) {
case SET_TO_CLIENT_TIME4: case SET_TO_CLIENT_TIME4:
nfstime4 time; nfstime4 time;
@ -885,7 +950,10 @@ enum open_claim_type4 {
CLAIM_NULL = 0, CLAIM_NULL = 0,
CLAIM_PREVIOUS = 1, CLAIM_PREVIOUS = 1,
CLAIM_DELEGATE_CUR = 2, 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 { struct open_claim_delegate_cur4 {
@ -1229,19 +1297,13 @@ struct SAVEFH4res {
nfsstat4 status; nfsstat4 status;
}; };
#if 0
/* /*
* SECINFO: Obtain Available Security Mechanisms * SECINFO: Obtain Available Security Mechanisms
*/ */
struct SECINFO4args { struct SECINFO4args {
/* CURRENT_FH: directory */
component4 name; component4 name;
}; };
/*
* From RFC 2203
*/
enum rpc_gss_svc_t { enum rpc_gss_svc_t {
RPC_GSS_SVC_NONE = 1, RPC_GSS_SVC_NONE = 1,
RPC_GSS_SVC_INTEGRITY = 2, RPC_GSS_SVC_INTEGRITY = 2,
@ -1254,7 +1316,8 @@ struct rpcsec_gss_info {
rpc_gss_svc_t service; 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) { union secinfo4 switch (uint32_t flavor) {
case RPCSEC_GSS: case RPCSEC_GSS:
rpcsec_gss_info flavor_info; rpcsec_gss_info flavor_info;
@ -1270,7 +1333,6 @@ union SECINFO4res switch (nfsstat4 status) {
default: default:
void; void;
}; };
#endif
/* /*
* SETATTR: Set attributes * SETATTR: Set attributes
@ -1372,6 +1434,456 @@ struct RELEASE_LOCKOWNER4res {
nfsstat4 status; 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 * ILLEGAL: Response for illegal operation numbers
*/ */
@ -1421,6 +1933,22 @@ enum nfs_opnum4 {
OP_VERIFY = 37, OP_VERIFY = 37,
OP_WRITE = 38, OP_WRITE = 38,
OP_RELEASE_LOCKOWNER = 39, 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 OP_ILLEGAL = 10044
}; };
@ -1455,9 +1983,7 @@ union nfs_argop4 switch (nfs_opnum4 argop) {
case OP_RENEW: RENEW4args oprenew; case OP_RENEW: RENEW4args oprenew;
case OP_RESTOREFH: void; case OP_RESTOREFH: void;
case OP_SAVEFH: void; case OP_SAVEFH: void;
#if 0
case OP_SECINFO: SECINFO4args opsecinfo; case OP_SECINFO: SECINFO4args opsecinfo;
#endif
case OP_SETATTR: SETATTR4args opsetattr; case OP_SETATTR: SETATTR4args opsetattr;
case OP_SETCLIENTID: SETCLIENTID4args opsetclientid; case OP_SETCLIENTID: SETCLIENTID4args opsetclientid;
case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4args case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4args
@ -1466,6 +1992,22 @@ union nfs_argop4 switch (nfs_opnum4 argop) {
case OP_WRITE: WRITE4args opwrite; case OP_WRITE: WRITE4args opwrite;
case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4args case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4args
oprelease_lockowner; 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; case OP_ILLEGAL: void;
}; };
@ -1500,9 +2042,7 @@ union nfs_resop4 switch (nfs_opnum4 resop){
case OP_RENEW: RENEW4res oprenew; case OP_RENEW: RENEW4res oprenew;
case OP_RESTOREFH: RESTOREFH4res oprestorefh; case OP_RESTOREFH: RESTOREFH4res oprestorefh;
case OP_SAVEFH: SAVEFH4res opsavefh; case OP_SAVEFH: SAVEFH4res opsavefh;
#if 0
case OP_SECINFO: SECINFO4res opsecinfo; case OP_SECINFO: SECINFO4res opsecinfo;
#endif
case OP_SETATTR: SETATTR4res opsetattr; case OP_SETATTR: SETATTR4res opsetattr;
case OP_SETCLIENTID: SETCLIENTID4res opsetclientid; case OP_SETCLIENTID: SETCLIENTID4res opsetclientid;
case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4res case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4res
@ -1511,6 +2051,22 @@ union nfs_resop4 switch (nfs_opnum4 resop){
case OP_WRITE: WRITE4res opwrite; case OP_WRITE: WRITE4res opwrite;
case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4res case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4res
oprelease_lockowner; 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; case OP_ILLEGAL: ILLEGAL4res opillegal;
}; };

View File

@ -113,6 +113,16 @@ Utility programs for LibNFS
%{_mandir}/man1/nfs-ls.1.gz %{_mandir}/man1/nfs-ls.1.gz
%changelog %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 * Wed Feb 13 2019 : Version 4.0.0
- Fix the versioning in makerpms.sh - Fix the versioning in makerpms.sh
- Fix some compile issues in the test programs. - Fix some compile issues in the test programs.

40
ps2_ee/Makefile.PS2_EE Normal file
View File

@ -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

38
ps2_ee/config.h Normal file
View File

@ -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__ */

86
ps2_ee/ps2_compat.c Normal file
View File

@ -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 */

104
ps2_ee/ps2_compat.h Normal file
View File

@ -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_ */

103
ps3_ppu/Makefile.PS3_PPU Normal file
View File

@ -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

49
ps3_ppu/config.h Normal file
View File

@ -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

72
ps3_ppu/ps3_compat.c Normal file
View File

@ -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);
}

115
ps3_ppu/ps3_compat.h Normal file
View File

@ -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

View File

@ -1,6 +1,6 @@
find_library(DL_LIBRARY dl) find_library(DL_LIBRARY dl)
set(SOURCES prog_access set(TEST_PROGS prog_access
prog_access2 prog_access2
prog_chmod prog_chmod
prog_chown prog_chown
@ -30,16 +30,14 @@ set(SOURCES prog_access
prog_unlink prog_unlink
prog_utimes) prog_utimes)
foreach(TARGET ${SOURCES}) foreach(TARGET ${TEST_PROGS})
add_executable(${TARGET} ${TARGET}.c) add_executable(${TARGET} ${TARGET}.c)
target_link_libraries(${TARGET} ${CORE_LIBRARIES}) target_link_libraries(${TARGET} nfs)
add_dependencies(${TARGET} nfs)
endforeach() endforeach()
add_library(ld_timeout SHARED ld_timeout.c) add_library(ld_timeout SHARED ld_timeout.c)
set_target_properties(ld_timeout PROPERTIES PREFIX "") set_target_properties(ld_timeout PROPERTIES PREFIX "")
target_link_libraries(ld_timeout ${CORE_LIBRARIES} ${DL_LIBRARY}) target_link_libraries(ld_timeout nfs ${DL_LIBRARY})
add_dependencies(ld_timeout nfs)
file(GLOB TESTS test_*.sh) file(GLOB TESTS test_*.sh)
@ -51,5 +49,3 @@ foreach(TEST ${TESTS})
COMMAND ${TEST} COMMAND ${TEST}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endforeach() endforeach()
add_definitions("-D_U_=__attribute__((unused))")

View File

@ -6,7 +6,7 @@ echo "NFSv${VERS} Basic chmod tests."
start_share 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) ... " echo -n "test chmod(0600) ... "
./prog_chmod "${TESTURL}/?version=${VERS}" "." /testfile 0600 || failure ./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 grep "nfs_mode:100755" "${TESTDIR}/output" >/dev/null || failure
success 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 stop_share

View File

@ -6,7 +6,7 @@ echo "NFSv${VERS} Basic chown tests."
start_share 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) ... " echo -n "test chown(1000, 2000) ... "
./prog_chown "${TESTURL}/?uid=0&version=${VERS}" "." /testfile 1000 2000 || failure ./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 grep "nfs_gid:3000" "${TESTDIR}/output" >/dev/null || failure
success 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 stop_share

View File

@ -6,7 +6,7 @@ echo "NFSv${VERS} Basic nfs_utimes() tests."
start_share 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" chmod 644 "${TESTDIR}/testfile"
echo -n "test nfs_utimes() ... " echo -n "test nfs_utimes() ... "
@ -25,6 +25,25 @@ echo -n "test nfs_mtime ... "
grep "nfs_mtime:23456" "${TESTDIR}/output" >/dev/null || failure grep "nfs_mtime:23456" "${TESTDIR}/output" >/dev/null || failure
success 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 stop_share

View File

@ -16,10 +16,6 @@ for IDX in `seq 1 100`; do
done done
success 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 ... " 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 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 success

View File

@ -6,6 +6,7 @@ echo "test we can build libnfs as an rpm"
[ -f "/etc/redhat-release" ] || { [ -f "/etc/redhat-release" ] || {
echo "SKIPPED. This is not a red-hat based system" echo "SKIPPED. This is not a red-hat based system"
exit 0
} }
echo -n "try building rpm packages ... " echo -n "try building rpm packages ... "

View File

@ -1,16 +1,10 @@
list(APPEND CORE_LIBRARIES ${SOCKET_LIBRARY}) set(UTILITIES nfs-cat nfs-ls)
set(SOURCES nfs-cat
nfs-ls)
if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows) if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
list(APPEND SOURCES nfs-cp) list(APPEND UTILITIES nfs-cp nfs-stat)
endif() endif()
foreach(TARGET ${SOURCES}) foreach(TARGET ${UTILITIES})
add_executable(${TARGET} ${TARGET}.c) add_executable(${TARGET} ${TARGET}.c)
target_link_libraries(${TARGET} ${CORE_LIBRARIES}) target_link_libraries(${TARGET} nfs nfs_mount)
add_dependencies(${TARGET} nfs)
endforeach() endforeach()
add_definitions("-D_U_=__attribute__((unused))")

View File

@ -1,7 +1,11 @@
bin_PROGRAMS = nfs-cat nfs-ls bin_PROGRAMS = nfs-cat nfs-ls
if HAVE_PTHREAD
LIBS += -lpthread
endif
if !HAVE_WIN32 if !HAVE_WIN32
bin_PROGRAMS += nfs-cp bin_PROGRAMS += nfs-cp nfs-stat
endif endif
AM_CPPFLAGS = \ AM_CPPFLAGS = \
@ -16,3 +20,4 @@ COMMON_LIBS = ../lib/libnfs.la $(LIBSOCKET)
nfs_cat_LDADD = $(COMMON_LIBS) nfs_cat_LDADD = $(COMMON_LIBS)
nfs_ls_LDADD = $(COMMON_LIBS) nfs_ls_LDADD = $(COMMON_LIBS)
nfs_cp_LDADD = $(COMMON_LIBS) nfs_cp_LDADD = $(COMMON_LIBS)
nfs_stat_LDADD = $(COMMON_LIBS)

View File

@ -165,6 +165,9 @@ int main(int argc, char *argv[])
struct client client; struct client client;
struct statvfs stvfs; struct statvfs stvfs;
struct nfs_url *url = NULL; struct nfs_url *url = NULL;
#ifdef HAVE_MULTITHREADING
int mt_started = 0;
#endif
#ifdef WIN32 #ifdef WIN32
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
@ -232,7 +235,6 @@ int main(int argc, char *argv[])
} }
nfs_destroy_url(url); nfs_destroy_url(url);
} }
url = nfs_parse_url_dir(nfs, argv[argc - 1]); url = nfs_parse_url_dir(nfs, argv[argc - 1]);
if (url == NULL) { if (url == NULL) {
fprintf(stderr, "%s\n", nfs_get_error(nfs)); fprintf(stderr, "%s\n", nfs_get_error(nfs));
@ -248,6 +250,18 @@ int main(int argc, char *argv[])
goto finished; 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); process_dir(nfs, "", 16);
if (summary) { if (summary) {
@ -261,6 +275,13 @@ int main(int argc, char *argv[])
ret = 0; ret = 0;
finished: finished:
#ifdef HAVE_MULTITHREADING
if (mt_started) {
printf("closing service thread\n");
nfs_mt_service_thread_stop(nfs);
}
#endif
if (ret > 0) { if (ret > 0) {
print_usage(); print_usage();
} }

292
utils/nfs-stat.c Normal file
View File

@ -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;
}

View File

@ -1,5 +1,5 @@
set(SOURCES win32_compat.c) set(SOURCES win32_compat.c)
set(HEADERS win32_compat.h set(HEADERS ../include/win32/win32_compat.h
win32_errnowrapper.h) win32_errnowrapper.h)
core_add_library(win32) core_add_library(win32)

View File

@ -28,23 +28,27 @@
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@ -111,7 +115,7 @@
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <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> <AdditionalIncludeDirectories>..\..\include\nfsc;..\..\include;..\..\.;..\..\win32;..\..\mount;..\..\nfs;..\..\nfs4;..\..\portmap;..\..\lib</AdditionalIncludeDirectories>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<DisableSpecificWarnings>4996</DisableSpecificWarnings> <DisableSpecificWarnings>4996</DisableSpecificWarnings>
@ -185,6 +189,7 @@
<ClCompile Include="..\..\lib\libnfs-sync.c" /> <ClCompile Include="..\..\lib\libnfs-sync.c" />
<ClCompile Include="..\..\lib\libnfs-zdr.c" /> <ClCompile Include="..\..\lib\libnfs-zdr.c" />
<ClCompile Include="..\..\lib\libnfs.c" /> <ClCompile Include="..\..\lib\libnfs.c" />
<ClCompile Include="..\..\lib\multithreading.c" />
<ClCompile Include="..\..\lib\nfs_v3.c" /> <ClCompile Include="..\..\lib\nfs_v3.c" />
<ClCompile Include="..\..\lib\nfs_v4.c" /> <ClCompile Include="..\..\lib\nfs_v4.c" />
<ClCompile Include="..\..\lib\pdu.c" /> <ClCompile Include="..\..\lib\pdu.c" />
@ -207,6 +212,7 @@
<ClCompile Include="..\win32_compat.c" /> <ClCompile Include="..\win32_compat.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\include\libnfs-multithreading.h" />
<ClInclude Include="..\..\include\nfsc\libnfs-zdr.h" /> <ClInclude Include="..\..\include\nfsc\libnfs-zdr.h" />
<ClInclude Include="..\..\mount\libnfs-raw-mount.h" /> <ClInclude Include="..\..\mount\libnfs-raw-mount.h" />
<ClInclude Include="..\..\nfs\libnfs-raw-nfs.h" /> <ClInclude Include="..\..\nfs\libnfs-raw-nfs.h" />

View File

@ -83,6 +83,9 @@
<ClCompile Include="..\..\nsm\nsm.c"> <ClCompile Include="..\..\nsm\nsm.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\lib\multithreading.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\nfs\libnfs-raw-nfs.h"> <ClInclude Include="..\..\nfs\libnfs-raw-nfs.h">
@ -115,6 +118,9 @@
<ClInclude Include="..\..\nlm\libnfs-raw-nlm.h"> <ClInclude Include="..\..\nlm\libnfs-raw-nlm.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\include\libnfs-multithreading.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\..\lib\libnfs-win32.def" /> <None Include="..\..\lib\libnfs-win32.def" />

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@ -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>

View File

@ -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"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
@ -28,23 +28,27 @@
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@ -68,7 +72,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<LibraryPath>..\libnfs\Debug;..\..\bin;$(LibraryPath)</LibraryPath> <LibraryPath>..\libnfs\x64\Debug;..\libnfs\Debug;..\..\bin;$(LibraryPath)</LibraryPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
@ -104,7 +108,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions)</PreprocessorDefinitions> <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> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@ -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"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
@ -28,23 +28,27 @@
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@ -68,7 +72,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<LibraryPath>..\libnfs\Debug;..\..\bin;$(LibraryPath)</LibraryPath> <LibraryPath>..\libnfs\x64\Debug;..\libnfs\Debug;..\..\bin;$(LibraryPath)</LibraryPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
@ -104,7 +108,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_U_=;%(PreprocessorDefinitions)</PreprocessorDefinitions> <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> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>

View File

@ -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>

54
win32/version.rc.template Normal file
View File

@ -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

View File

@ -50,7 +50,7 @@ int win32_inet_pton(int af, const char * src, void * dst)
struct sockaddr_in sa; struct sockaddr_in sa;
int len = sizeof(SOCKADDR); int len = sizeof(SOCKADDR);
int ret = -1; int ret = -1;
int strLen = strlen(src) + 1; size_t strLen = strlen(src) + 1;
#ifdef UNICODE #ifdef UNICODE
wchar_t *srcNonConst = (wchar_t *)malloc(strLen*sizeof(wchar_t)); wchar_t *srcNonConst = (wchar_t *)malloc(strLen*sizeof(wchar_t));
memset(srcNonConst, 0, strLen); 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) 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)) if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds))
fds[i].revents |= POLLIN; fds[i].revents |= POLLIN;
if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds)) if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
@ -197,6 +197,23 @@ int win32_gettimeofday(struct timeval *tv, struct timezone *tz)
return 0; 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
#endif