Add nfs_statvfs64()

Add a new function nfs_statvfs64() that returns a struct nfs_statvfs_64
where all fields are uint64_t.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
libnfs-4.0.0-vitalif
Ronnie Sahlberg 2018-12-26 13:33:38 +10:00
parent d21b48256e
commit 48a559cb47
8 changed files with 285 additions and 36 deletions

View File

@ -463,6 +463,8 @@ int nfs3_stat64_async(struct nfs_context *nfs, const char *path,
int no_follow, nfs_cb cb, void *private_data);
int nfs3_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs3_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs3_symlink_async(struct nfs_context *nfs, const char *oldpath,
const char *newpath, nfs_cb cb, void *private_data);
int nfs3_truncate_async(struct nfs_context *nfs, const char *path,
@ -540,6 +542,8 @@ int nfs4_stat64_async(struct nfs_context *nfs, const char *path,
int no_follow, nfs_cb cb, void *private_data);
int nfs4_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs4_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data);
int nfs4_symlink_async(struct nfs_context *nfs, const char *oldpath,
const char *newpath, nfs_cb cb, void *private_data);
int nfs4_truncate_async(struct nfs_context *nfs, const char *path,

View File

@ -1292,8 +1292,23 @@ EXTERN void nfs_getcwd(struct nfs_context *nfs, const char **cwd);
/*
* STATVFS()
*/
struct nfs_statvfs_64 {
uint64_t f_bsize;
uint64_t f_frsize;
uint64_t f_blocks;
uint64_t f_bfree;
uint64_t f_bavail;
uint64_t f_files;
uint64_t f_ffree;
uint64_t f_favail;
uint64_t f_fsid;
uint64_t f_flag;
uint64_t f_namemax;
};
/*
* Async statvfs(<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.
@ -1311,13 +1326,40 @@ EXTERN int nfs_statvfs_async(struct nfs_context *nfs, const char *path,
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()
@ -1338,7 +1380,6 @@ EXTERN int nfs_statvfs(struct nfs_context *nfs, const char *path,
* -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);
/*

View File

@ -1166,6 +1166,46 @@ nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs)
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()

View File

@ -95,6 +95,8 @@ nfs_stat64
nfs_stat64_async
nfs_statvfs
nfs_statvfs_async
nfs_statvfs64
nfs_statvfs64_async
nfs_symlink
nfs_symlink_async
nfs_truncate

View File

@ -1471,6 +1471,22 @@ nfs_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
}
}
int
nfs_statvfs64_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data)
{
switch (nfs->version) {
case NFS_V3:
return nfs3_statvfs64_async(nfs, path, cb, private_data);
case NFS_V4:
return nfs4_statvfs64_async(nfs, path, cb, private_data);
default:
nfs_set_error(nfs, "%s does not support NFSv%d",
__FUNCTION__, nfs->version);
return -1;
}
}
int
nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
void *private_data)

View File

@ -2272,6 +2272,7 @@ nfs3_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_data,
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 +2293,39 @@ nfs3_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_data,
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 +2363,19 @@ nfs3_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
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)

View File

@ -141,7 +141,8 @@ struct nfs4_cb_data {
/* 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 */
@ -4389,6 +4390,83 @@ nfs_parse_statvfs(struct nfs_context *nfs, struct nfs4_cb_data *data,
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)
@ -4398,6 +4476,7 @@ nfs4_statvfs_cb(struct rpc_context *rpc, int status, void *command_data,
COMPOUND4res *res = command_data;
GETATTR4resok *garesok;
struct statvfs svfs;
struct nfs_statvfs_64 svfs64;
int i;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
@ -4413,21 +4492,37 @@ nfs4_statvfs_cb(struct rpc_context *rpc, int status, void *command_data,
}
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;
@ -4445,6 +4540,9 @@ nfs4_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
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;
@ -4465,6 +4563,22 @@ nfs4_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
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)

View File

@ -40,7 +40,7 @@ int main(int argc, char *argv[])
{
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 @@ int main(int argc, char *argv[])
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);