Hello community, here is the log from the commit of package libnfs for openSUSE:Factory checked in at 2019-07-31 14:12:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libnfs (Old) and /work/SRC/openSUSE:Factory/.libnfs.new.4126 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libnfs" Wed Jul 31 14:12:06 2019 rev:7 rq:718320 version:4.0.0 Changes: -------- --- /work/SRC/openSUSE:Factory/libnfs/libnfs.changes 2018-11-26 10:11:59.806316784 +0100 +++ /work/SRC/openSUSE:Factory/.libnfs.new.4126/libnfs.changes 2019-07-31 14:12:07.550950528 +0200 @@ -1,0 +2,20 @@ +Wed Jul 24 15:18:59 UTC 2019 - Bjørn Lie <[email protected]> + +- Update to version 4.0.0: + + Fix the versioning in makerpms.sh. + + Fix some compile issues in the test programs. + + NFSv3: skip commit on close if the file has not been written + to. + + Add nfs_umount() to NFSv3. + + Add nfs_statvfs64(). + + Fix invalid shift of pid_t when generating rpc->xid. + + Compile fixes for Mac OSX. + + Fix for dup2() on Windows. + + NFSv4 fix for directory handling. + + Improvements to configure/building. +- Bump sover to 13 following upstream. +- Use modern macros. +- Pass explicit --enable-utils to configure, ensure we build the + utils. + +------------------------------------------------------------------- Old: ---- libnfs-3.0.0.tar.gz New: ---- libnfs-4.0.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libnfs.spec ++++++ --- /var/tmp/diff_new_pack.Hcx3EH/_old 2019-07-31 14:12:07.974950381 +0200 +++ /var/tmp/diff_new_pack.Hcx3EH/_new 2019-07-31 14:12:07.974950381 +0200 @@ -1,7 +1,7 @@ # # spec file for package libnfs # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # Copyright (c) 2015 Bjørn Lie, Bryne, Norway. # # All modifications and additions to the file contributed by third parties @@ -17,15 +17,17 @@ # -%define sover 12 +%define sover 13 + Name: libnfs -Version: 3.0.0 +Version: 4.0.0 Release: 0 Summary: Client library for accessing NFS shares over a network License: LGPL-2.1-or-later AND BSD-2-Clause AND GPL-3.0-or-later Group: Productivity/Networking/NFS URL: https://github.com/sahlberg/libnfs -Source0: https://github.com/sahlberg/libnfs/archive/libnfs-%{version}.tar.gz +Source0: %{url}/archive/libnfs-%{version}.tar.gz + BuildRequires: autoconf BuildRequires: libtool BuildRequires: pkgconfig @@ -69,14 +71,16 @@ accessing NFS servers using libnfs. %prep -%setup -q -n %{name}-%{name}-%{version} +%autosetup -p1 -n %{name}-%{name}-%{version} %build autoreconf -fiv %configure \ --disable-static \ - --disable-examples -make %{?_smp_mflags} + --disable-examples \ + --enable-utils \ + %{nil} +%make_build %install %make_install ++++++ libnfs-3.0.0.tar.gz -> libnfs-4.0.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/CHANGELOG new/libnfs-libnfs-4.0.0/CHANGELOG --- old/libnfs-libnfs-3.0.0/CHANGELOG 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/CHANGELOG 2019-02-12 22:38:04.000000000 +0100 @@ -1,3 +1,16 @@ +Changes since 3.0.0 + +Fix the versioning in makerpms.sh +Fix some compile issues in the test programs. +NFSv3: skip commit on close if the file has not been written to. +Add nfs_umount() to NFSv3 +Add nfs_statvfs64() +Fix invalid shift of pid_t when generating rpc->xid +Compile fixes for Mac OSX +Fix for dup2() on Windows +NFSv4 fix for directory handling +Improvements to configure/bulding + Changes since 2.0.0 NFSv4 support. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/README new/libnfs-libnfs-4.0.0/README --- old/libnfs-libnfs-3.0.0/README 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/README 2019-02-12 22:38:04.000000000 +0100 @@ -25,9 +25,9 @@ NFSv4: ====== -NFSv4 is supported but only for the RAW ASYNC interface. -Examples/nfsv4-cat.c is a "simple" example to illustrate how to use -NFSv4 to connect to a server and read a file off the server. +NFSv3 is the default but NFSv4 can be selected either by using the URL argument +version=4 or programatically calling nfs_set_version(nfs, NFS_V4) before +connecting to the server/share. SERVER SUPPORT: =============== @@ -67,8 +67,6 @@ to the application. if=<interface> : Interface name (e.g., eth1) to bind; requires `root` version=<3|4> : NFS Version. Default is 3. - This is just a placeholder for now. NFSv4 support is not - yet functional. nfsport=<port> : Use this port for NFS instead of using the portmapper. mountport=<port> : Use this port for the MOUNT protocol instead of using portmapper. This argument is ignored for NFSv4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/configure.ac new/libnfs-libnfs-4.0.0/configure.ac --- old/libnfs-libnfs-3.0.0/configure.ac 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/configure.ac 2019-02-12 22:38:04.000000000 +0100 @@ -1,5 +1,5 @@ AC_PREREQ(2.50) -AC_INIT([libnfs], [3.0.0], [[email protected]]) +AC_INIT([libnfs], [4.0.0], [[email protected]]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) AC_CANONICAL_HOST @@ -25,11 +25,13 @@ AC_SYS_LARGEFILE #option: utils +MAYBE_UTILS="utils" AC_ARG_ENABLE([utils], [AC_HELP_STRING([--enable-utils], [Build util programs])], - [MAYBE_UTILS=""], - [MAYBE_UTILS="utils"]) + [if test $enableval = no ; then + MAYBE_UTILS="" + fi]) AC_SUBST(MAYBE_UTILS) #option: examples diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/examples/nfs-fh.c new/libnfs-libnfs-4.0.0/examples/nfs-fh.c --- old/libnfs-libnfs-3.0.0/examples/nfs-fh.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/examples/nfs-fh.c 2019-02-12 22:38:04.000000000 +0100 @@ -122,6 +122,7 @@ if (nfsfh) { nfs_close(nfs, nfsfh); } + nfs_umount(nfs); if (url) { nfs_destroy_url(url); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/include/libnfs-private.h new/libnfs-libnfs-4.0.0/include/libnfs-private.h --- old/libnfs-libnfs-3.0.0/include/libnfs-private.h 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/include/libnfs-private.h 2019-02-12 22:38:04.000000000 +0100 @@ -463,10 +463,13 @@ int no_follow, nfs_cb cb, void *private_data); int nfs3_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); +int nfs3_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, + void *private_data); int nfs3_symlink_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); int nfs3_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data); +int nfs3_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data); int nfs3_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); int nfs3_utime_async(struct nfs_context *nfs, const char *path, @@ -540,6 +543,8 @@ int no_follow, nfs_cb cb, void *private_data); int nfs4_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); +int nfs4_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, + void *private_data); int nfs4_symlink_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); int nfs4_truncate_async(struct nfs_context *nfs, const char *path, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/include/nfsc/libnfs.h new/libnfs-libnfs-4.0.0/include/nfsc/libnfs.h --- old/libnfs-libnfs-3.0.0/include/nfsc/libnfs.h 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/include/nfsc/libnfs.h 2019-02-12 22:38:04.000000000 +0100 @@ -53,8 +53,10 @@ #if defined(WIN32) #define EXTERN __declspec( dllexport ) #else +#ifndef EXTERN #define EXTERN #endif +#endif #ifdef WIN32 #ifdef HAVE_FUSE_H @@ -314,6 +316,39 @@ const char *exportname); +/* + * UNMOUNT THE EXPORT + */ +/* + * Async nfs umount. + * For NFSv4 this is a NO-OP. + * For NFSv3 this function returns unregisters the mount from the MOUNT Daemon. + * + * 0 : The command was queued successfully. The callback will be invoked once + * the command completes. + * <0 : An error occured when trying to queue the command. + * The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * 0 : Success. + * data is NULL + * -errno : An error occured. + * data is the error string. + */ +EXTERN int nfs_umount_async(struct nfs_context *nfs, nfs_cb cb, + void *private_data); +/* + * Sync nfs umount. + * For NFSv4 this is a NO-OP. + * For NFSv3 this function returns unregisters the mount from the MOUNT Daemon. + * + * Function returns + * 0 : The operation was successful. + * -errno : The command failed. + */ +EXTERN int nfs_umount(struct nfs_context *nfs); + + /* @@ -1290,8 +1325,23 @@ /* * STATVFS() */ +struct nfs_statvfs_64 { + uint64_t f_bsize; + uint64_t f_frsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + uint64_t f_favail; + uint64_t f_fsid; + uint64_t f_flag; + uint64_t f_namemax; +}; /* * Async statvfs(<dirname>) + * This function is deprecated. Use nfs_statvfs64_async() instead. + * * Function returns * 0 : The command was queued successfully. The callback will be invoked once * the command completes. @@ -1309,13 +1359,40 @@ nfs_cb cb, void *private_data); /* * Sync statvfs(<dirname>) + * This function is deprecated. Use nfs_statvfs64() instead. + * * Function returns * 0 : The operation was successful. * -errno : The command failed. */ EXTERN int nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs); - +/* + * Async statvfs64(<dirname>) + * + * Function returns + * 0 : The command was queued successfully. The callback will be invoked once + * the command completes. + * <0 : An error occured when trying to queue the command. + * The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * 0 : Success. + * data is struct nfs_statvfs_64 * + * -errno : An error occured. + * data is the error string. + */ +EXTERN int nfs_statvfs64_async(struct nfs_context *nfs, const char *path, + nfs_cb cb, void *private_data); +/* + * Sync statvfs64(<dirname>) + * + * Function returns + * 0 : The operation was successful. + * -errno : The command failed. + */ +EXTERN int nfs_statvfs64(struct nfs_context *nfs, const char *path, + struct nfs_statvfs_64 *svfs); /* * READLINK() @@ -1336,7 +1413,6 @@ * -errno : An error occured. * data is the error string. */ -struct statvfs; EXTERN int nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/CMakeLists.txt new/libnfs-libnfs-4.0.0/lib/CMakeLists.txt --- old/libnfs-libnfs-3.0.0/lib/CMakeLists.txt 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/CMakeLists.txt 2019-02-12 22:38:04.000000000 +0100 @@ -9,6 +9,7 @@ add_library(nfs ${SOURCES}) target_link_libraries(nfs PUBLIC ${core_DEPENDS}) +target_include_directories(nfs PUBLIC ../include) set_target_properties(nfs PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${SOVERSION}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/Makefile.am new/libnfs-libnfs-4.0.0/lib/Makefile.am --- old/libnfs-libnfs-3.0.0/lib/Makefile.am 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/Makefile.am 2019-02-12 22:38:04.000000000 +0100 @@ -25,7 +25,7 @@ socket.c \ ../win32/win32_compat.c -SOCURRENT=12 +SOCURRENT=13 SOREVISION=0 SOAGE=0 libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/init.c new/libnfs-libnfs-4.0.0/lib/init.c --- old/libnfs-libnfs-3.0.0/lib/init.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/init.c 2019-02-12 22:38:04.000000000 +0100 @@ -81,7 +81,9 @@ free(rpc); return NULL; } - rpc->xid = salt + (uint32_t)rpc_current_time() + (getpid() << 16); + // Add PID to rpc->xid for easier debugging, making sure to cast + // pid to 32-bit type to avoid invalid left-shifts. + rpc->xid = salt + rpc_current_time() + ((uint32_t)getpid() << 16); salt += 0x01000000; rpc->fd = -1; rpc->tcp_syncnt = RPC_PARAM_UNDEFINED; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/libnfs-sync.c new/libnfs-libnfs-4.0.0/lib/libnfs-sync.c --- old/libnfs-libnfs-3.0.0/lib/libnfs-sync.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/libnfs-sync.c 2019-02-12 22:38:04.000000000 +0100 @@ -229,6 +229,57 @@ /* + * unregister the mount + */ +static void +umount_cb(int status, struct nfs_context *nfs, void *data, void *private_data) +{ + struct sync_cb_data *cb_data = private_data; + + cb_data->is_finished = 1; + cb_data->status = status; + + if (status < 0) { + nfs_set_error(nfs, "%s: %s", + __FUNCTION__, nfs_get_error(nfs)); + return; + } +} + +int +nfs_umount(struct nfs_context *nfs) +{ + struct sync_cb_data cb_data; + struct rpc_context *rpc = nfs_get_rpc_context(nfs); + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + cb_data.is_finished = 0; + + if (nfs_umount_async(nfs, umount_cb, &cb_data) != 0) { + nfs_set_error(nfs, "nfs_umount_async failed. %s", + nfs_get_error(nfs)); + return -1; + } + + wait_for_nfs_reply(nfs, &cb_data); + + /* Dont want any more callbacks even if the socket is closed */ + rpc->connect_cb = NULL; + + /* Ensure that no RPCs are pending. In error case (e.g. timeout in + * wait_for_nfs_reply()) we can disconnect; in success case all RPCs + * are completed by definition. + */ + if (cb_data.status) { + rpc_disconnect(rpc, "failed mount"); + } + + return cb_data.status; +} + + +/* * stat() */ static void @@ -1166,6 +1217,46 @@ return cb_data.status; } +/* + * statvfs64() + */ +static void +statvfs64_cb(int status, struct nfs_context *nfs, void *data, + void *private_data) +{ + struct sync_cb_data *cb_data = private_data; + + cb_data->is_finished = 1; + cb_data->status = status; + + if (status < 0) { + nfs_set_error(nfs, "statvfs64 call failed with \"%s\"", + (char *)data); + return; + } + + memcpy(cb_data->return_data, data, sizeof(struct nfs_statvfs_64)); +} + +int +nfs_statvfs64(struct nfs_context *nfs, const char *path, + struct nfs_statvfs_64 *svfs) +{ + struct sync_cb_data cb_data; + + cb_data.is_finished = 0; + cb_data.return_data = svfs; + + if (nfs_statvfs64_async(nfs, path, statvfs64_cb, &cb_data) != 0) { + nfs_set_error(nfs, "nfs_statvfs64_async failed. %s", + nfs_get_error(nfs)); + return -1; + } + + wait_for_nfs_reply(nfs, &cb_data); + + return cb_data.status; +} /* * readlink() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/libnfs-win32.def new/libnfs-libnfs-4.0.0/lib/libnfs-win32.def --- old/libnfs-libnfs-3.0.0/lib/libnfs-win32.def 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/libnfs-win32.def 2019-02-12 22:38:04.000000000 +0100 @@ -95,10 +95,14 @@ nfs_stat64_async nfs_statvfs nfs_statvfs_async +nfs_statvfs64 +nfs_statvfs64_async nfs_symlink nfs_symlink_async nfs_truncate nfs_truncate_async +nfs_umount +nfs_umount_async nfs_unlink nfs_unlink_async nfs_utime diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/libnfs.c new/libnfs-libnfs-4.0.0/lib/libnfs.c --- old/libnfs-libnfs-3.0.0/lib/libnfs.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/libnfs.c 2019-02-12 22:38:04.000000000 +0100 @@ -66,10 +66,15 @@ #include <sys/sysmacros.h> #endif +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + #include <errno.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include "slist.h" #include "libnfs.h" #include "libnfs-raw.h" @@ -860,6 +865,26 @@ } } +/* + * Async call for umounting an nfs share + */ +int +nfs_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data) +{ + switch (nfs->version) { + case NFS_V3: + return nfs3_umount_async(nfs, cb, private_data); + case NFS_V4: + /* umount is a no-op in v4 */ + (*cb)(0, nfs, NULL, private_data); + return 0; + default: + nfs_set_error(nfs, "%s does not support NFSv%d", + __FUNCTION__, nfs->version); + return -1; + } +} + int nfs_normalize_path(struct nfs_context *nfs, char *path) { @@ -1462,6 +1487,22 @@ default: nfs_set_error(nfs, "%s does not support NFSv%d", __FUNCTION__, nfs->version); + return -1; + } +} + +int +nfs_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, + void *private_data) +{ + switch (nfs->version) { + case NFS_V3: + return nfs3_statvfs64_async(nfs, path, cb, private_data); + case NFS_V4: + return nfs4_statvfs64_async(nfs, path, cb, private_data); + default: + nfs_set_error(nfs, "%s does not support NFSv%d", + __FUNCTION__, nfs->version); return -1; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/nfs_v3.c new/libnfs-libnfs-4.0.0/lib/nfs_v3.c --- old/libnfs-libnfs-3.0.0/lib/nfs_v3.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/nfs_v3.c 2019-02-12 22:38:04.000000000 +0100 @@ -1152,6 +1152,92 @@ return 0; } +static void +nfs3_umount_2_cb(struct rpc_context *rpc, int status, void *command_data, + void *private_data) +{ + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (check_nfs3_error(nfs, status, data, command_data)) { + free_nfs_cb_data(data); + return; + } + + rpc_disconnect(rpc, "umount"); + data->cb(0, nfs, NULL, data->private_data); + free_nfs_cb_data(data); +} + +static void +nfs3_umount_1_cb(struct rpc_context *rpc, int status, void *command_data, + void *private_data) +{ + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (check_nfs3_error(nfs, status, data, command_data)) { + free_nfs_cb_data(data); + return; + } + + if (rpc_mount3_umnt_async(rpc, nfs3_umount_2_cb, nfs->export, + data) != 0) { + nfs_set_error(nfs, "%s: %s.", __FUNCTION__, nfs_get_error(nfs)); + data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); + free_nfs_cb_data(data); + return; + } +} + +int +nfs3_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data) +{ + struct nfs_cb_data *data; + + data = malloc(sizeof(struct nfs_cb_data)); + if (data == NULL) { + nfs_set_error(nfs, "out of memory. failed to allocate " + "memory for nfs mount data"); + return -1; + } + memset(data, 0, sizeof(struct nfs_cb_data)); + + data->nfs = nfs; + data->cb = cb; + data->private_data = private_data; + + rpc_disconnect(nfs->rpc, "umount"); + + if (nfs->mountport) { + if (rpc_connect_port_async(nfs->rpc, nfs->server, + nfs->mountport, + MOUNT_PROGRAM, MOUNT_V3, + nfs3_umount_1_cb, data) != 0) { + nfs_set_error(nfs, "Failed to start connection. %s", + nfs_get_error(nfs)); + free_nfs_cb_data(data); + return -1; + } + return 0; + } + + if (rpc_connect_program_async(nfs->rpc, nfs->server, + MOUNT_PROGRAM, MOUNT_V3, + nfs3_umount_1_cb, data) != 0) { + nfs_set_error(nfs, "Failed to start connection. %s", + nfs_get_error(nfs)); + free_nfs_cb_data(data); + return -1; + } + + return 0; +} + struct nfs_link_data { char *oldpath; @@ -2272,6 +2358,7 @@ struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct statvfs svfs; + struct nfs_statvfs_64 svfs64; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -2292,21 +2379,39 @@ return; } - svfs.f_bsize = NFS_BLKSIZE; - svfs.f_frsize = NFS_BLKSIZE; - svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/NFS_BLKSIZE; - svfs.f_bfree = res->FSSTAT3res_u.resok.fbytes/NFS_BLKSIZE; - svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/NFS_BLKSIZE; - svfs.f_files = (uint32_t)res->FSSTAT3res_u.resok.tfiles; - svfs.f_ffree = (uint32_t)res->FSSTAT3res_u.resok.ffiles; + if (data->continue_int == 0) { + /* statvfs */ + svfs.f_bsize = NFS_BLKSIZE; + svfs.f_frsize = NFS_BLKSIZE; + svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/NFS_BLKSIZE; + svfs.f_bfree = res->FSSTAT3res_u.resok.fbytes/NFS_BLKSIZE; + svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/NFS_BLKSIZE; + svfs.f_files = (uint32_t)res->FSSTAT3res_u.resok.tfiles; + svfs.f_ffree = (uint32_t)res->FSSTAT3res_u.resok.ffiles; #if !defined(__ANDROID__) - svfs.f_favail = (uint32_t)res->FSSTAT3res_u.resok.afiles; - svfs.f_fsid = 0; - svfs.f_flag = 0; - svfs.f_namemax = 256; + svfs.f_favail = (uint32_t)res->FSSTAT3res_u.resok.afiles; + svfs.f_fsid = 0; + svfs.f_flag = 0; + svfs.f_namemax = 256; #endif + data->cb(0, nfs, &svfs, data->private_data); + } else { + /* statvfs64 */ + svfs64.f_bsize = NFS_BLKSIZE; + svfs64.f_frsize = NFS_BLKSIZE; + svfs64.f_blocks = res->FSSTAT3res_u.resok.tbytes/NFS_BLKSIZE; + svfs64.f_bfree = res->FSSTAT3res_u.resok.fbytes/NFS_BLKSIZE; + svfs64.f_bavail = res->FSSTAT3res_u.resok.abytes/NFS_BLKSIZE; + svfs64.f_files = res->FSSTAT3res_u.resok.tfiles; + svfs64.f_ffree = res->FSSTAT3res_u.resok.ffiles; + svfs64.f_favail = res->FSSTAT3res_u.resok.afiles; + svfs64.f_fsid = 0; + svfs64.f_flag = 0; + svfs64.f_namemax = 256; + + data->cb(0, nfs, &svfs64, data->private_data); + } - data->cb(0, nfs, &svfs, data->private_data); free_nfs_cb_data(data); } @@ -2344,6 +2449,19 @@ return 0; } +int +nfs3_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, + void *private_data) +{ + if (nfs3_lookuppath_async(nfs, path, 0, cb, private_data, + nfs3_statvfs_continue_internal, + NULL, NULL, 1) != 0) { + return -1; + } + + return 0; +} + static void nfs3_lseek_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) @@ -4169,6 +4287,12 @@ { struct nfs_cb_data *data; + if (!nfsfh->is_dirty) { + nfs_free_nfsfh(nfsfh); + cb(0, nfs, NULL, private_data); + return 0; + } + data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " @@ -4341,6 +4465,7 @@ { struct nfs_cb_data *data; + nfsfh->is_dirty = 1; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { nfs_set_error(nfs, "out of memory: failed to allocate " diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/nfs_v4.c new/libnfs-libnfs-4.0.0/lib/nfs_v4.c --- old/libnfs-libnfs-3.0.0/lib/nfs_v4.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/nfs_v4.c 2019-02-12 22:38:04.000000000 +0100 @@ -141,7 +141,8 @@ /* Do not follow symlinks for the final component on a lookup. * I.e. stat vs lstat */ -#define LOOKUP_FLAG_NO_FOLLOW 0x0001 +#define LOOKUP_FLAG_NO_FOLLOW 0x0001 +#define LOOKUP_FLAG_IS_STATVFS64 0x0002 int flags; /* Internal callback for open-with-continuation use */ @@ -1964,6 +1965,37 @@ } static void +nfs4_open_chmod_cb(struct rpc_context *rpc, int status, void *command_data, + void *private_data) +{ + struct nfs4_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + struct nfsfh *fh = data->filler.blob0.val; + COMPOUND4res *res = command_data; + COMPOUND4args args; + nfs_argop4 op[2]; + int i; + + if (check_nfs4_error(nfs, status, data, res, "OPEN")) { + return; + } + + i = nfs4_op_putfh(nfs, op, fh); + i += nfs4_op_chmod(nfs, &op[i], fh, data->filler.blob3.val); + + memset(&args, 0, sizeof(args)); + args.argarray.argarray_len = i; + args.argarray.argarray_val = op; + + if (rpc_nfs4_compound_async(nfs->rpc, nfs4_open_setattr_cb, &args, + data) != 0) { + data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data); + free_nfs4_cb_data(data); + return; + } +} + +static void nfs4_open_confirm_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { @@ -2118,6 +2150,25 @@ free_nfs4_cb_data(data); } +static void +nfs4_init_random_verifier(char *verifier) +{ + static uint64_t seed = 0, v; + int i; + + if (seed == 0) { + seed = ~rpc_current_time() << 32 | getpid(); + } else { + seed *= 1337; + } + + v = seed; + for (i = 0; i < NFS4_VERIFIER_SIZE; i++) { + verifier[i] = v & 0xff; + v >>= 8; + } +} + /* filler.flags are the open flags * filler.data is the object name */ @@ -2127,6 +2178,7 @@ struct nfs_context *nfs = data->nfs; OPEN4args *oargs; uint32_t access_mask = 0; + verifier4 verifier; int i; if (data->filler.flags & O_WRONLY) { @@ -2135,7 +2187,7 @@ if (data->filler.flags & O_RDWR) { access_mask |= ACCESS4_READ|ACCESS4_MODIFY; } - if (!(data->filler.flags & (O_WRONLY|O_RDWR))) { + if (!(data->filler.flags & O_WRONLY)) { access_mask |= ACCESS4_READ; } @@ -2166,12 +2218,20 @@ fa = &ch->createhow4_u.createattrs; oargs->openhow.opentype = OPEN4_CREATE; - ch->mode = UNCHECKED4; - fa->attrmask.bitmap4_len = data->filler.blob1.len; - fa->attrmask.bitmap4_val = data->filler.blob1.val; + if (data->filler.flags|O_EXCL) { + ch->mode = EXCLUSIVE4; - fa->attr_vals.attrlist4_len = data->filler.blob2.len; - fa->attr_vals.attrlist4_val = data->filler.blob2.val; + nfs4_init_random_verifier(&verifier[0]); + memcpy(ch->createhow4_u.createverf, verifier, + sizeof(verifier4)); + } else { + ch->mode = UNCHECKED4; + fa->attrmask.bitmap4_len = data->filler.blob1.len; + fa->attrmask.bitmap4_val = data->filler.blob1.val; + + fa->attr_vals.attrlist4_len = data->filler.blob2.len; + fa->attr_vals.attrlist4_val = data->filler.blob2.val; + } } else { oargs->openhow.opentype = OPEN4_NOCREATE; } @@ -2373,6 +2433,7 @@ int mode, nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; + uint32_t m; data = init_cb_data_split_path(nfs, path); if (data == NULL) { @@ -2386,6 +2447,10 @@ if (flags & O_TRUNC && !(flags & (O_RDWR|O_WRONLY))) { flags &= ~O_TRUNC; } + /* Successful O_EXCL means the file is 0 size already. */ + if (flags & O_EXCL) { + flags &= ~O_TRUNC; + } if (flags & O_TRUNC) { data->open_cb = nfs4_open_truncate_cb; @@ -2400,6 +2465,20 @@ memset(data->filler.blob3.val, 0, 12); } + if (flags & O_EXCL) { + data->open_cb = nfs4_open_chmod_cb; + + data->filler.blob3.val = malloc(4); + if (data->filler.blob3.val == NULL) { + nfs_set_error(nfs, "Out of memory"); + free_nfs4_cb_data(data); + return -1; + } + data->filler.blob3.free = free; + + m = htonl(mode); + memcpy(data->filler.blob3.val, &m, sizeof(uint32_t)); + } return nfs4_open_async_internal(nfs, data, flags, mode); } @@ -3536,7 +3615,7 @@ struct nfs4_cb_data *data; struct nfsdir *nfsdir; - data = init_cb_data_split_path(nfs, path); + data = init_cb_data_full_path(nfs, path); if (data == NULL) { return -1; } @@ -4311,6 +4390,83 @@ return 0; } +static int +nfs_parse_statvfs64(struct nfs_context *nfs, struct nfs4_cb_data *data, + struct nfs_statvfs_64 *svfs64, const char *buf, int len) +{ + uint64_t u64; + uint32_t u32; + + svfs64->f_bsize = NFS_BLKSIZE; + svfs64->f_frsize = NFS_BLKSIZE; + svfs64->f_flag = 0; + + /* FSID + * NFSv4 FSID is 2*64 bit but statvfs fsid is just an + * unsigmed long. Mix the 2*64 bits and hope for the best. + */ + CHECK_GETATTR_BUF_SPACE(len, 16); + memcpy(&u64, buf, 8); + svfs64->f_fsid = nfs_ntoh64(u64); + buf += 8; + len -= 8; + memcpy(&u64, buf, 8); + svfs64->f_fsid |= nfs_ntoh64(u64); + buf += 8; + len -= 8; + + /* Files Avail */ + CHECK_GETATTR_BUF_SPACE(len, 8); + memcpy(&u64, buf, 8); + svfs64->f_favail = nfs_ntoh64(u64); + buf += 8; + len -= 8; + + /* Files Free */ + CHECK_GETATTR_BUF_SPACE(len, 8); + memcpy(&u64, buf, 8); + svfs64->f_ffree = nfs_ntoh64(u64); + buf += 8; + len -= 8; + + /* Files Total */ + CHECK_GETATTR_BUF_SPACE(len, 8); + memcpy(&u64, buf, 8); + svfs64->f_files = nfs_ntoh64(u64); + buf += 8; + len -= 8; + + /* Max Name */ + CHECK_GETATTR_BUF_SPACE(len, 4); + memcpy(&u32, buf, 4); + svfs64->f_namemax = ntohl(u32); + buf += 4; + len -= 4; + + /* Space Avail */ + CHECK_GETATTR_BUF_SPACE(len, 8); + memcpy(&u64, buf, 8); + svfs64->f_bavail = nfs_ntoh64(u64) / svfs64->f_frsize; + buf += 8; + len -= 8; + + /* Space Free */ + CHECK_GETATTR_BUF_SPACE(len, 8); + memcpy(&u64, buf, 8); + svfs64->f_bfree = nfs_ntoh64(u64) / svfs64->f_frsize; + buf += 8; + len -= 8; + + /* Space Total */ + CHECK_GETATTR_BUF_SPACE(len, 8); + memcpy(&u64, buf, 8); + svfs64->f_blocks = nfs_ntoh64(u64) / svfs64->f_frsize; + buf += 8; + len -= 8; + + return 0; +} + static void nfs4_statvfs_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) @@ -4320,6 +4476,7 @@ COMPOUND4res *res = command_data; GETATTR4resok *garesok; struct statvfs svfs; + struct nfs_statvfs_64 svfs64; int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -4329,27 +4486,44 @@ } memset(&svfs, 0, sizeof(svfs)); + memset(&svfs64, 0, sizeof(svfs64)); if ((i = nfs4_find_op(nfs, data, res, OP_GETATTR, "GETATTR")) < 0) { return; } garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4; - if (nfs_parse_statvfs(nfs, data, &svfs, + if (data->flags & LOOKUP_FLAG_IS_STATVFS64) { + /* statvfs64 */ + if (nfs_parse_statvfs64(nfs, data, &svfs64, garesok->obj_attributes.attr_vals.attrlist4_val, garesok->obj_attributes.attr_vals.attrlist4_len) < 0) { - data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); - free_nfs4_cb_data(data); - return; + data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); + free_nfs4_cb_data(data); + return; + } + + data->cb(0, nfs, &svfs64, data->private_data); + } else { + /* statvfs */ + if (nfs_parse_statvfs(nfs, data, &svfs, + garesok->obj_attributes.attr_vals.attrlist4_val, + garesok->obj_attributes.attr_vals.attrlist4_len) < 0) { + data->cb(-EINVAL, nfs, nfs_get_error(nfs), data->private_data); + free_nfs4_cb_data(data); + return; + } + + data->cb(0, nfs, &svfs, data->private_data); } - data->cb(0, nfs, &svfs, data->private_data); free_nfs4_cb_data(data); } -int -nfs4_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, - void *private_data) +static int +nfs4_statvfs_async_internal(struct nfs_context *nfs, const char *path, + int is_statvfs64, + nfs_cb cb, void *private_data) { struct nfs4_cb_data *data; COMPOUND4args args; @@ -4367,6 +4541,9 @@ data->nfs = nfs; data->cb = cb; data->private_data = private_data; + if (is_statvfs64) { + data->flags |= LOOKUP_FLAG_IS_STATVFS64; + } fh.fh.len = nfs->rootfh.len; fh.fh.val = nfs->rootfh.val; @@ -4387,6 +4564,22 @@ return 0; } +int +nfs4_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, + void *private_data) +{ + return nfs4_statvfs_async_internal(nfs, path, 0, + cb, private_data); +} + +int +nfs4_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, + void *private_data) +{ + return nfs4_statvfs_async_internal(nfs, path, 1, + cb, private_data); +} + static void nfs4_chmod_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/lib/socket.c new/libnfs-libnfs-4.0.0/lib/socket.c --- old/libnfs-libnfs-3.0.0/lib/socket.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/lib/socket.c 2019-02-12 22:38:04.000000000 +0100 @@ -86,6 +86,12 @@ #include "win32_errnowrapper.h" #endif +#ifndef MSG_NOSIGNAL +#if (defined(__APPLE__) && defined(__MACH__)) +#define MSG_NOSIGNAL 0 +#endif +#endif + static int rpc_reconnect_requeue(struct rpc_context *rpc); @@ -93,13 +99,15 @@ create_socket(int domain, int type, int protocol) { #ifdef SOCK_CLOEXEC - /* Linux-specific extension (since 2.6.27): set the +#ifdef __linux__ + /* Linux-specific extension (since 2.6.27): set the close-on-exec flag on all sockets to avoid leaking file descriptors to child processes */ int fd = socket(domain, type|SOCK_CLOEXEC, protocol); if (fd >= 0 || errno != EINVAL) return fd; #endif +#endif return socket(domain, type, protocol); } @@ -589,11 +597,18 @@ } if (rpc->old_fd) { +#if !defined(WIN32) if (dup2(rpc->fd, rpc->old_fd) == -1) { return -1; } close(rpc->fd); rpc->fd = rpc->old_fd; +#else + /* On Windows dup2 does not work on sockets + * instead just close the old socket */ + close(rpc->old_fd); + rpc->old_fd = 0; +#endif } /* Some systems allow you to set capabilities on an executable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/packaging/RPM/libnfs.spec.in new/libnfs-libnfs-4.0.0/packaging/RPM/libnfs.spec.in --- old/libnfs-libnfs-3.0.0/packaging/RPM/libnfs.spec.in 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/packaging/RPM/libnfs.spec.in 2019-02-12 22:38:04.000000000 +0100 @@ -113,6 +113,17 @@ %{_mandir}/man1/nfs-ls.1.gz %changelog +* Wed Feb 13 2019 : Version 4.0.0 +- Fix the versioning in makerpms.sh +- Fix some compile issues in the test programs. +- NFSv3: skip commit on close if the file has not been written to. +- Add nfs_umount() to NFSv3 +- Add nfs_statvfs64() +- Fix invalid shift of pid_t when generating rpc->xid +- Compile fixes for Mac OSX +- Fix for dup2() on Windows +- NFSv4 fix for directory handling +- Improvements to configure/bulding * Sun Jun 24 2018 : Version 3.0.0 - NFSv4 support. - lockf() support (NFSv4 only). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/packaging/RPM/makerpms.sh new/libnfs-libnfs-4.0.0/packaging/RPM/makerpms.sh --- old/libnfs-libnfs-3.0.0/packaging/RPM/makerpms.sh 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/packaging/RPM/makerpms.sh 2019-02-12 22:38:04.000000000 +0100 @@ -50,7 +50,7 @@ # # If we're not directly on a tag, this is a devel release; we append # .0.<patchnum>.<checksum>.devel to the release. -TAG=`git describe` +TAG=`git describe --tags` case "$TAG" in libnfs-*) TAG=${TAG##libnfs-} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/tests/CMakeLists.txt new/libnfs-libnfs-4.0.0/tests/CMakeLists.txt --- old/libnfs-libnfs-3.0.0/tests/CMakeLists.txt 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/tests/CMakeLists.txt 2019-02-12 22:38:04.000000000 +0100 @@ -19,6 +19,7 @@ prog_mount prog_open_read prog_open_write + prog_opendir prog_rename prog_rmdir prog_stat diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/tests/Makefile.am new/libnfs-libnfs-4.0.0/tests/Makefile.am --- old/libnfs-libnfs-3.0.0/tests/Makefile.am 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/tests/Makefile.am 2019-02-12 22:38:04.000000000 +0100 @@ -7,7 +7,7 @@ noinst_PROGRAMS = prog_access prog_access2 prog_chmod prog_chown prog_create \ prog_fchmod prog_fchown prog_fstat prog_ftruncate prog_lchmod \ prog_lchown prog_link prog_lseek prog_lstat prog_mkdir \ - prog_mknod prog_mount prog_open_read prog_open_write \ + prog_mknod prog_mount prog_opendir prog_open_read prog_open_write \ prog_rename prog_rmdir prog_stat prog_statvfs prog_symlink \ prog_timeout prog_truncate prog_unlink prog_utimes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/tests/prog_open_read.c new/libnfs-libnfs-4.0.0/tests/prog_open_read.c --- old/libnfs-libnfs-3.0.0/tests/prog_open_read.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/tests/prog_open_read.c 2019-02-12 22:38:04.000000000 +0100 @@ -43,7 +43,7 @@ struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; int ret = 0; - int flags = 0, count; + int flags = 0, count, res, pos; struct nfsfh *fh; char buf[1024]; @@ -111,7 +111,17 @@ goto finished; } - write(1, buf, count); + pos = 0; + while (count) { + res = write(1, &buf[pos], count); + if (res < 0) { + fprintf(stderr, "write() failed\n"); + ret = 1; + goto finished; + } + count -= res; + pos += res; + } if (nfs_close(nfs, fh)) { fprintf(stderr, "Failed to close(): %s\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/tests/prog_opendir.c new/libnfs-libnfs-4.0.0/tests/prog_opendir.c --- old/libnfs-libnfs-3.0.0/tests/prog_opendir.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libnfs-libnfs-4.0.0/tests/prog_opendir.c 2019-02-12 22:38:04.000000000 +0100 @@ -0,0 +1,99 @@ +/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */ +/* + Copyright (C) by Ronnie Sahlberg <[email protected]> 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#define _FILE_OFFSET_BITS 64 +#define _GNU_SOURCE + +#include <fcntl.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "libnfs.h" + +void usage(void) +{ + fprintf(stderr, "Usage: prog_opendir <url> <cwd> <path>\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct nfs_context *nfs = NULL; + struct nfs_url *url = NULL; + struct nfsdirent *nfsdirent; + struct nfsdir *nfsdir; + int ret = 0; + + if (argc != 4) { + usage(); + } + + nfs = nfs_init_context(); + if (nfs == NULL) { + printf("failed to init context\n"); + exit(1); + } + + nfs_set_timeout(nfs, 300); + + url = nfs_parse_url_full(nfs, argv[1]); + if (url == NULL) { + fprintf(stderr, "%s\n", nfs_get_error(nfs)); + exit(1); + } + + if (nfs_mount(nfs, url->server, url->path) != 0) { + fprintf(stderr, "Failed to mount nfs share : %s\n", + nfs_get_error(nfs)); + ret = 1; + goto finished; + } + + if (nfs_chdir(nfs, argv[2]) != 0) { + fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", + argv[2], nfs_get_error(nfs)); + ret = 1; + goto finished; + } + + if (nfs_opendir(nfs, argv[3], &nfsdir)) { + fprintf(stderr, "Failed to opendir() : %s\n", + nfs_get_error(nfs)); + ret = 1; + goto finished; + } + + while((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) { + if (!strcmp(nfsdirent->name, ".") || !strcmp(nfsdirent->name, "..")) { + continue; + } + printf("%s\n", nfsdirent->name); + } + nfs_closedir(nfs, nfsdir); + +finished: + nfs_destroy_url(url); + nfs_destroy_context(nfs); + + return ret; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/tests/prog_statvfs.c new/libnfs-libnfs-4.0.0/tests/prog_statvfs.c --- old/libnfs-libnfs-3.0.0/tests/prog_statvfs.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/tests/prog_statvfs.c 2019-02-12 22:38:04.000000000 +0100 @@ -40,7 +40,7 @@ { struct nfs_context *nfs = NULL; struct nfs_url *url = NULL; - struct statvfs svfs; + struct nfs_statvfs_64 svfs; int ret = 0; if (argc != 4) { @@ -75,23 +75,23 @@ goto finished; } - if (nfs_statvfs(nfs, argv[3], &svfs)) { - fprintf(stderr, "statvfs failed : %s\n", + if (nfs_statvfs64(nfs, argv[3], &svfs)) { + fprintf(stderr, "statvfs64 failed : %s\n", nfs_get_error(nfs)); ret = 1; goto finished; } - printf("bsize:%lu\n", svfs.f_bsize); - printf("frsize:%lu\n", svfs.f_frsize); - printf("blocks:%lu\n", svfs.f_blocks); - printf("bfree:%lu\n", svfs.f_bfree); - printf("bavail:%lu\n", svfs.f_bavail); - printf("files:%lu\n", svfs.f_files); - printf("ffree:%lu\n", svfs.f_ffree); - printf("favail:%lu\n", svfs.f_favail); - printf("fsid:%lu\n", svfs.f_fsid); - printf("namemax:%lu\n", svfs.f_namemax); + printf("bsize:%" PRIu64 "\n", svfs.f_bsize); + printf("frsize:%" PRIu64 "\n", svfs.f_frsize); + printf("blocks:%" PRIu64 "\n", svfs.f_blocks); + printf("bfree:%" PRIu64 "\n", svfs.f_bfree); + printf("bavail:%" PRIu64 "\n", svfs.f_bavail); + printf("files:%" PRIu64 "\n", svfs.f_files); + printf("ffree:%" PRIu64 "\n", svfs.f_ffree); + printf("favail:%" PRIu64 "\n", svfs.f_favail); + printf("fsid:%" PRIu64 "\n", svfs.f_fsid); + printf("namemax:%" PRIu64 "\n", svfs.f_namemax); finished: nfs_destroy_url(url); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/tests/test_0460_opendir.sh new/libnfs-libnfs-4.0.0/tests/test_0460_opendir.sh --- old/libnfs-libnfs-3.0.0/tests/test_0460_opendir.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/libnfs-libnfs-4.0.0/tests/test_0460_opendir.sh 2019-02-12 22:38:04.000000000 +0100 @@ -0,0 +1,58 @@ +#!/bin/sh +# +# NFS servers generally want us to be root in order to create device nodes. +# We can lie and impersonate root by setting uid=0 in the URL. + +. ./functions.sh + +echo "NFSv${VERS} Basic opendir test." + +start_share + +mkdir "${TESTDIR}/subdir" +mkdir "${TESTDIR}/subdir/subdir2" +touch "${TESTDIR}/subdir/subdir2/file" + +echo -n "Open '.' in the root directory (1)... " +./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "." "." > "${TESTDIR}/output" || failure +success + +echo -n "Check the directory listing ... " +grep "^subdir$" "${TESTDIR}/output" >/dev/null || failure +success + +echo -n "Open a subdir in the root directory (2)... " +./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "." "subdir" > "${TESTDIR}/output" || failure +success + +echo -n "Check the directory listing ... " +grep "^subdir2$" "${TESTDIR}/output" >/dev/null || failure +success + +echo -n "Open '.' in a subdir (3)... " +./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "subdir" "." > "${TESTDIR}/output" || failure +success + +echo -n "Check the directory listing ... " +grep "^subdir2$" "${TESTDIR}/output" >/dev/null || failure +success + +echo -n "Open 'subdir2' in a subdir (4)... " +./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "subdir" "subdir2" > "${TESTDIR}/output" || failure +success + +echo -n "Check the directory listing ... " +grep "^file$" "${TESTDIR}/output" >/dev/null || failure +success + +echo -n "Open '..' in a subdir (5)... " +./prog_opendir "${TESTURL}/?uid=0&version=${VERS}" "subdir/subdir2" ".." > "${TESTDIR}/output" || failure +success + +echo -n "Check the directory listing ... " +grep "^subdir2$" "${TESTDIR}/output" >/dev/null || failure +success + +stop_share + +exit 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libnfs-libnfs-3.0.0/utils/nfs-cp.c new/libnfs-libnfs-4.0.0/utils/nfs-cp.c --- old/libnfs-libnfs-3.0.0/utils/nfs-cp.c 2018-06-24 00:53:52.000000000 +0200 +++ new/libnfs-libnfs-4.0.0/utils/nfs-cp.c 2019-02-12 22:38:04.000000000 +0100 @@ -197,8 +197,9 @@ return NULL; } } else { - if (nfs_creat(file_context->nfs, file_context->url->file, 0660, - &file_context->nfsfh) != 0) { + if (nfs_create(file_context->nfs, file_context->url->file, + flags, 0660, + &file_context->nfsfh) != 0) { fprintf(stderr, "Failed to creat file %s: %s\n", file_context->url->file, nfs_get_error(file_context->nfs)); @@ -241,7 +242,7 @@ return 10; } - dst = open_file(argv[2], O_WRONLY|O_CREAT|O_TRUNC); + dst = open_file(argv[2], O_WRONLY|O_CREAT|O_EXCL|O_TRUNC); if (dst == NULL) { fprintf(stderr, "Failed to open %s\n", argv[2]); free_file_context(src);
