Merge branch 'nfsv4'

libnfs-4.0.0-vitalif
Ronnie Sahlberg 2017-07-01 08:43:23 +10:00
commit 9776ca3a95
18 changed files with 5958 additions and 4494 deletions

1
README
View File

@ -66,6 +66,7 @@ Arguments supported by libnfs are :
times before failing and returing an error back times before failing and returing an error back
to the application. to the application.
if=<interface> : Interface name (e.g., eth1) to bind; requires `root` if=<interface> : Interface name (e.g., eth1) to bind; requires `root`
version=<3|4> : NFS Version. Default is 3.
Auto_traverse_mounts Auto_traverse_mounts
==================== ====================

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>
@ -234,10 +235,229 @@ void rpc_free_all_fragments(struct rpc_context *rpc);
int rpc_is_udp_socket(struct rpc_context *rpc); int rpc_is_udp_socket(struct rpc_context *rpc);
int rpc_current_time(void); int rpc_current_time(void);
const struct nfs_fh3 *nfs_get_rootfh(struct nfs_context *nfs);
void *zdr_malloc(ZDR *zdrs, uint32_t size); void *zdr_malloc(ZDR *zdrs, uint32_t size);
struct nfs_cb_data;
void free_nfs_cb_data(struct nfs_cb_data *data);
int check_nfs_error(struct nfs_context *nfs, int status,
struct nfs_cb_data *data, void *command_data);
struct nfs_specdata {
uint32_t specdata1;
uint32_t specdata2;
};
struct nfs_time {
uint32_t seconds;
uint32_t nseconds;
};
struct nfs_attr {
uint32_t type;
uint32_t mode;
uint32_t uid;
uint32_t gid;
uint32_t nlink;
uint64_t size;
uint64_t used;
uint64_t fsid;
struct nfs_specdata rdev;
struct nfs_time atime;
struct nfs_time mtime;
struct nfs_time ctime;
};
struct nfs_fh {
int len;
char *val;
};
struct nfs_context {
struct rpc_context *rpc;
char *server;
char *export;
struct nfs_fh rootfh;
uint64_t readmax;
uint64_t writemax;
char *cwd;
int dircache_enabled;
int auto_reconnect;
struct nfsdir *dircache;
uint16_t mask;
int auto_traverse_mounts;
struct nested_mounts *nested_mounts;
int version;
};
typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_attr *attr,
struct nfs_cb_data *data);
struct nfs_cb_data {
struct nfs_context *nfs;
struct nfsfh *nfsfh;
char *saved_path, *path;
int link_count, no_follow;
nfs_cb cb;
void *private_data;
continue_func continue_cb;
void *continue_data;
void (*free_continue_data)(void *);
uint64_t continue_int;
struct nfs_fh fh;
/* for multi-read/write calls. */
int error;
int cancel;
int oom;
int num_calls;
size_t count, org_count;
uint64_t offset, max_offset, org_offset;
char *buffer;
int not_my_buffer;
const char *usrbuf;
int update_pos;
};
struct nested_mounts {
struct nested_mounts *next;
char *path;
struct nfs_fh fh;
struct nfs_attr attr;
};
#define MAX_DIR_CACHE 128
#define MAX_LINK_COUNT 40
struct nfsdir {
struct nfs_fh fh;
struct nfs_attr attr;
struct nfsdir *next;
struct nfsdirent *entries;
struct nfsdirent *current;
};
struct nfs_readahead {
uint64_t fh_offset;
uint32_t cur_ra;
};
struct nfs_pagecache_entry {
char buf[NFS_BLKSIZE];
uint64_t offset;
time_t ts;
};
struct nfs_pagecache {
struct nfs_pagecache_entry *entries;
uint32_t num_entries;
time_t ttl;
};
struct nfsfh {
struct nfs_fh fh;
int is_sync;
int is_append;
uint64_t offset;
struct nfs_readahead ra;
struct nfs_pagecache pagecache;
};
const struct nfs_fh *nfs_get_rootfh(struct nfs_context *nfs);
int nfs_normalize_path(struct nfs_context *nfs, char *path);
void nfs_free_nfsdir(struct nfsdir *nfsdir);
void nfs_free_nfsfh(struct nfsfh *nfsfh);
void nfs_dircache_add(struct nfs_context *nfs, struct nfsdir *nfsdir);
struct nfsdir *nfs_dircache_find(struct nfs_context *nfs, struct nfs_fh *fh);
void nfs_dircache_drop(struct nfs_context *nfs, struct nfs_fh *fh);
char * nfs_pagecache_get(struct nfs_pagecache *pagecache, uint64_t offset);
void nfs_pagecache_put(struct nfs_pagecache *pagecache, uint64_t offset,
const char *buf, size_t len);
int nfs3_access_async(struct nfs_context *nfs, const char *path, int mode,
nfs_cb cb, void *private_data);
int nfs3_access2_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs3_chdir_async(struct nfs_context *nfs, const char *path,
nfs_cb cb, void *private_data);
int nfs3_chmod_async_internal(struct nfs_context *nfs, const char *path,
int no_follow, int mode, nfs_cb cb,
void *private_data);
int nfs3_chown_async_internal(struct nfs_context *nfs, const char *path,
int no_follow, int uid, int gid,
nfs_cb cb, void *private_data);
int nfs3_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
void *private_data);
int nfs3_create_async(struct nfs_context *nfs, const char *path, int flags,
int mode, nfs_cb cb, void *private_data);
int nfs3_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode,
nfs_cb cb, void *private_data);
int nfs3_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid,
int gid, nfs_cb cb, void *private_data);
int nfs3_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
void *private_data);
int nfs3_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
void *private_data);
int nfs3_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
void *private_data);
int nfs3_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
uint64_t length, nfs_cb cb, void *private_data);
int nfs3_link_async(struct nfs_context *nfs, const char *oldpath,
const char *newpath, nfs_cb cb, void *private_data);
int nfs3_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
int64_t offset, int whence, nfs_cb cb, void *private_data);
int nfs3_mkdir2_async(struct nfs_context *nfs, const char *path, int mode,
nfs_cb cb, void *private_data);
int nfs3_mknod_async(struct nfs_context *nfs, const char *path, int mode,
int dev, nfs_cb cb, void *private_data);
int nfs3_mount_async(struct nfs_context *nfs, const char *server,
const char *export, nfs_cb cb, void *private_data);
int nfs3_open_async(struct nfs_context *nfs, const char *path, int flags,
nfs_cb cb, void *private_data);
int nfs3_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs3_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh,
uint64_t offset, size_t count, nfs_cb cb,
void *private_data, int update_pos);
int nfs3_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh,
uint64_t offset, size_t count, const char *buf,
nfs_cb cb, void *private_data, int update_pos);
int nfs3_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs3_rename_async(struct nfs_context *nfs, const char *oldpath,
const char *newpath, nfs_cb cb, void *private_data);
int nfs3_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs3_stat_async(struct nfs_context *nfs, const char *path,
nfs_cb cb, void *private_data);
int nfs3_stat64_async_internal(struct nfs_context *nfs, const char *path,
int no_follow, nfs_cb cb, void *private_data);
int nfs3_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs3_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_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs3_utime_async(struct nfs_context *nfs, const char *path,
struct utimbuf *times, nfs_cb cb, void *private_data);
int nfs3_utimes_async_internal(struct nfs_context *nfs, const char *path,
int no_follow, struct timeval *times,
nfs_cb cb, void *private_data);
int nfs3_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
uint64_t count, const void *buf, nfs_cb cb,
void *private_data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -144,11 +144,11 @@ char *rpc_get_error(struct rpc_context *rpc);
*/ */
struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs); struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs);
/* This function returns the nfs_fh3 structure from a nfsfh structure. /* This function returns the nfs_fh structure from a nfsfh structure.
This allows to use a file opened with nfs_open() together with low-level This allows to use a file opened with nfs_open() together with low-level
rpc functions that thake a nfs filehandles. rpc functions that thake a nfs filehandle
*/ */
struct nfs_fh3 *nfs_get_fh(struct nfsfh *nfsfh); struct nfs_fh *nfs_get_fh(struct nfsfh *nfsfh);
/* Control what the next XID value to be used on the context will be. /* Control what the next XID value to be used on the context will be.
This can be used when multiple contexts are used to the same server This can be used when multiple contexts are used to the same server

View File

@ -192,6 +192,7 @@ EXTERN void nfs_destroy_context(struct nfs_context *nfs);
* >=1 : Retry to connect back to the server this many * >=1 : Retry to connect back to the server this many
* times before failing and returing an error back * times before failing and returing an error back
* to the application. * to the application.
* version=<3|4> : NFS version. Default is 3.
*/ */
/* /*
* Parse a complete NFS URL including, server, path and * Parse a complete NFS URL including, server, path and
@ -244,6 +245,13 @@ EXTERN void nfs_set_debug(struct nfs_context *nfs, int level);
EXTERN void nfs_set_dircache(struct nfs_context *nfs, int enabled); EXTERN void nfs_set_dircache(struct nfs_context *nfs, int enabled);
EXTERN void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries); EXTERN void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries);
/*
* Set NFS version. Supported versions are
* NFS_V3 (default)
* NFS_V4
*/
EXTERN int nfs_set_version(struct nfs_context *nfs, int version);
/* /*
* Invalidate the pagecache * Invalidate the pagecache
*/ */
@ -1445,14 +1453,14 @@ EXTERN int nfs_access2(struct nfs_context *nfs, const char *path);
* -errno : An error occured. * -errno : An error occured.
* data is the error string. * data is the error string.
*/ */
EXTERN int nfs_symlink_async(struct nfs_context *nfs, const char *oldpath, const char *newpath, nfs_cb cb, void *private_data); EXTERN int nfs_symlink_async(struct nfs_context *nfs, const char *target, const char *linkname, nfs_cb cb, void *private_data);
/* /*
* Sync symlink(<path>) * Sync symlink(<path>)
* Function returns * Function returns
* 0 : The operation was successful. * 0 : The operation was successful.
* -errno : The command failed. * -errno : The command failed.
*/ */
EXTERN int nfs_symlink(struct nfs_context *nfs, const char *oldpath, const char *newpath); EXTERN int nfs_symlink(struct nfs_context *nfs, const char *target, const char *linkname);
/* /*

View File

@ -19,6 +19,7 @@ libnfs_la_SOURCES = \
libnfs.c \ libnfs.c \
libnfs-sync.c \ libnfs-sync.c \
libnfs-zdr.c \ libnfs-zdr.c \
nfs3.c \
pdu.c \ pdu.c \
socket.c \ socket.c \
../win32/win32_compat.c ../win32/win32_compat.c

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>
@ -185,7 +186,8 @@ static void mount_cb(int status, struct nfs_context *nfs, void *data, void *priv
cb_data->status = status; cb_data->status = status;
if (status < 0) { if (status < 0) {
nfs_set_error(nfs, "mount/mnt call failed with \"%s\"", (char *)data); nfs_set_error(nfs, "%s: %s",
__FUNCTION__, nfs_get_error(nfs));
return; return;
} }
} }
@ -200,7 +202,8 @@ int nfs_mount(struct nfs_context *nfs, const char *server, const char *export)
cb_data.is_finished = 0; cb_data.is_finished = 0;
if (nfs_mount_async(nfs, server, export, mount_cb, &cb_data) != 0) { if (nfs_mount_async(nfs, server, export, mount_cb, &cb_data) != 0) {
nfs_set_error(nfs, "nfs_mount_async failed"); nfs_set_error(nfs, "nfs_mount_async failed. %s",
nfs_get_error(nfs));
return -1; return -1;
} }
@ -1398,7 +1401,8 @@ int nfs_access2(struct nfs_context *nfs, const char *path)
/* /*
* symlink() * symlink()
*/ */
static void symlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data) static void
symlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
{ {
struct sync_cb_data *cb_data = private_data; struct sync_cb_data *cb_data = private_data;
@ -1406,19 +1410,23 @@ static void symlink_cb(int status, struct nfs_context *nfs, void *data, void *pr
cb_data->status = status; cb_data->status = status;
if (status < 0) { if (status < 0) {
nfs_set_error(nfs, "symlink call failed with \"%s\"", (char *)data); nfs_set_error(nfs, "symlink call failed with \"%s\"",
(char *)data);
return; return;
} }
} }
int nfs_symlink(struct nfs_context *nfs, const char *oldpath, const char *newpath) int
nfs_symlink(struct nfs_context *nfs, const char *target, const char *linkname)
{ {
struct sync_cb_data cb_data; struct sync_cb_data cb_data;
cb_data.is_finished = 0; cb_data.is_finished = 0;
if (nfs_symlink_async(nfs, oldpath, newpath, symlink_cb, &cb_data) != 0) { if (nfs_symlink_async(nfs, target, linkname, symlink_cb,
nfs_set_error(nfs, "nfs_symlink_async failed"); &cb_data) != 0) {
nfs_set_error(nfs, "nfs_symlink_async failed: %s",
nfs_get_error(nfs));
return -1; return -1;
} }
@ -1428,7 +1436,6 @@ int nfs_symlink(struct nfs_context *nfs, const char *oldpath, const char *newpat
} }
/* /*
* rename() * rename()
*/ */

View File

@ -82,6 +82,7 @@ nfs_set_readahead
nfs_set_tcp_syncnt nfs_set_tcp_syncnt
nfs_set_timeout nfs_set_timeout
nfs_set_uid nfs_set_uid
nfs_set_version
nfs_stat nfs_stat
nfs_stat_async nfs_stat_async
nfs_stat64 nfs_stat64

File diff suppressed because it is too large Load Diff

4879
lib/nfs3.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ AM_CPPFLAGS = -I${srcdir}/../include -I${srcdir}/../include/nfsc \
AM_CFLAGS = $(WARN_CFLAGS) AM_CFLAGS = $(WARN_CFLAGS)
LDADD = ../lib/libnfs.la LDADD = ../lib/libnfs.la
noinst_PROGRAMS = prog_fstat prog_stat prog_timeout noinst_PROGRAMS = prog_fstat prog_stat prog_symlink prog_timeout
EXTRA_PROGRAMS = ld_timeout EXTRA_PROGRAMS = ld_timeout
CLEANFILES = ld_timeout.o ld_timeout.so CLEANFILES = ld_timeout.o ld_timeout.so

View File

@ -1,5 +1,6 @@
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
/* /*
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2015 Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2017
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,6 @@
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
/* /*
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2015 Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2017
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

98
tests/prog_symlink.c Normal file
View File

@ -0,0 +1,98 @@
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
/*
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 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-symlink <url> <target> <link>\n");
exit(1);
}
int main(int argc, char *argv[])
{
struct nfs_context *nfs = NULL;
struct nfs_url *url = NULL;
int ret = 0;
char buf[1024];
if (argc != 4) {
usage();
}
nfs = nfs_init_context();
if (nfs == NULL) {
printf("failed to init context\n");
exit(1);
}
url = nfs_parse_url_full(nfs, argv[1]);
if (url == NULL) {
fprintf(stderr, "%s\n", nfs_get_error(nfs));
exit(1);
}
if (nfs_mount(nfs, url->server, url->path) != 0) {
fprintf(stderr, "Failed to mount nfs share : %s\n",
nfs_get_error(nfs));
ret = 1;
goto finished;
}
if (nfs_symlink(nfs, argv[2], argv[3])) {
fprintf(stderr, "Failed to create symlink: %s\n",
nfs_get_error(nfs));
ret = 1;
goto finished;
}
memset(buf, 0, sizeof(buf));
if (nfs_readlink(nfs, argv[3], buf, sizeof(buf))) {
fprintf(stderr, "Failed to read symlink: %s\n",
nfs_get_error(nfs));
ret = 1;
goto finished;
}
if (strcmp(argv[2], buf)) {
fprintf(stderr, "Symlink target did not read back correctly."
"Expected \"%s\" Got \"%s\"\n",
buf, argv[2]);
ret = 1;
goto finished;
}
finished:
nfs_destroy_url(url);
nfs_destroy_context(nfs);
return ret;
}

View File

@ -1,5 +1,6 @@
/* -*- mode:c; tab-width:8; c-basic-offset:8; indent-tabs-mode:nil; -*- */
/* /*
Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2015 Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2017
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -0,0 +1,20 @@
#!/bin/sh
. ./functions.sh
echo "basic symlink test"
start_share
echo -n "Create a symlink from a root path (absolute) ... "
./prog_symlink "${TESTURL}/" kangabanga /symlink || failure
success
echo -n "Create a symlink from a nested path (absolute) ... "
mkdir "${TESTDIR}/subdir"
./prog_symlink "${TESTURL}/" kangabanga /subdir/symlink || failure
success
stop_share
exit 0

View File

@ -52,6 +52,15 @@ echo -n "test nfs_fstat64() for memory leaks ... "
libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_fstat "${TESTURL}/file.99" >/dev/null 2>&1 || failure libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_fstat "${TESTURL}/file.99" >/dev/null 2>&1 || failure
success success
echo -n "test nfs_symlink()/nfs_readlink() for memory leaks ... "
libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_symlink "${TESTURL}/" kangabanga /symlink >/dev/null 2>&1 || failure
success
echo -n "test nfs_symlink()/nfs_readlink() for memory leaks (2) ... "
mkdir "${TESTDIR}/subdir"
libtool --mode=execute valgrind --leak-check=full --error-exitcode=1 ./prog_symlink "${TESTURL}/" kangabanga /subdir/symlink >/dev/null 2>&1 || failure
success
stop_share stop_share
exit 0 exit 0

View File

@ -185,6 +185,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\nfsv3.c" />
<ClCompile Include="..\..\lib\pdu.c" /> <ClCompile Include="..\..\lib\pdu.c" />
<ClCompile Include="..\..\lib\socket.c" /> <ClCompile Include="..\..\lib\socket.c" />
<ClCompile Include="..\..\mount\libnfs-raw-mount.c" /> <ClCompile Include="..\..\mount\libnfs-raw-mount.c" />

View File

@ -53,6 +53,9 @@
<ClCompile Include="..\..\lib\libnfs-sync.c"> <ClCompile Include="..\..\lib\libnfs-sync.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\lib\nfsv3.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\lib\pdu.c"> <ClCompile Include="..\..\lib\pdu.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>