libnfs: Set as much stat information as possible

Set as much stat information as possible for stat, stat64, fstat and
readdir.

Fill in dev to the given fsid.
Fill in rdev to the given major and minor numbers.
Set the file type bits in the mode from the type returned by the server.
Set the number of blocks used based on the number of bytes used in
blocks of size 512 (which is what stat(2) uses), rounded up.
Fill in the nanosecond timestamps.

Signed-off-by: Ross Lagerwall <rosslagerwall@gmail.com>
libnfs-4.0.0-vitalif
Ross Lagerwall 2014-07-20 21:39:06 +01:00
parent 8dea7c3e2d
commit fc08ac459c
3 changed files with 110 additions and 15 deletions

View File

@ -153,6 +153,11 @@ AC_CHECK_MEMBER([struct sockaddr_storage.ss_family],
#include <sys/socket.h>
])
AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec])
# check where makedev is defined
AC_HEADER_MAJOR
#output
AC_CONFIG_FILES([Makefile]
[doc/Makefile]

View File

@ -270,6 +270,10 @@ struct nfs_stat_64 {
uint64_t nfs_atime;
uint64_t nfs_mtime;
uint64_t nfs_ctime;
uint64_t nfs_atime_nsec;
uint64_t nfs_mtime_nsec;
uint64_t nfs_ctime_nsec;
uint64_t nfs_used;
};
/*
@ -813,6 +817,14 @@ struct nfsdirent {
uint32_t uid;
uint32_t gid;
uint32_t nlink;
uint64_t dev;
uint64_t rdev;
uint64_t blksize;
uint64_t blocks;
uint64_t used;
uint32_t atime_nsec;
uint32_t mtime_nsec;
uint32_t ctime_nsec;
};
/*
* nfs_readdir() never blocks, so no special sync/async versions are available

View File

@ -59,6 +59,14 @@
#include <strings.h>
#endif
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#endif
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@ -1202,6 +1210,15 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c
/*
* Async stat()
*/
static dev_t specdata3_to_rdev(struct specdata3 *rdev)
{
#ifdef makedev
return makedev(rdev->specdata1, rdev->specdata2);
#else
return 0;
#endif
}
static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
{
GETATTR3res *res;
@ -1234,27 +1251,49 @@ static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_dat
return;
}
st.st_dev = -1;
st.st_dev = res->GETATTR3res_u.resok.obj_attributes.fsid;
st.st_ino = res->GETATTR3res_u.resok.obj_attributes.fileid;
st.st_mode = res->GETATTR3res_u.resok.obj_attributes.mode;
if (res->GETATTR3res_u.resok.obj_attributes.type == NF3DIR) {
st.st_mode |= S_IFDIR ;
}
if (res->GETATTR3res_u.resok.obj_attributes.type == NF3REG) {
st.st_mode |= S_IFREG ;
switch (res->GETATTR3res_u.resok.obj_attributes.type) {
case NF3REG:
st.st_mode |= S_IFREG;
break;
case NF3DIR:
st.st_mode |= S_IFDIR;
break;
case NF3BLK:
st.st_mode |= S_IFBLK;
break;
case NF3CHR:
st.st_mode |= S_IFCHR;
break;
case NF3LNK:
st.st_mode |= S_IFLNK;
break;
case NF3SOCK:
st.st_mode |= S_IFSOCK;
break;
case NF3FIFO:
st.st_mode |= S_IFIFO;
break;
}
st.st_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink;
st.st_uid = res->GETATTR3res_u.resok.obj_attributes.uid;
st.st_gid = res->GETATTR3res_u.resok.obj_attributes.gid;
st.st_rdev = 0;
st.st_rdev = specdata3_to_rdev(&res->GETATTR3res_u.resok.obj_attributes.rdev);
st.st_size = res->GETATTR3res_u.resok.obj_attributes.size;
#ifndef WIN32
st.st_blksize = NFS_BLKSIZE;
st.st_blocks = res->GETATTR3res_u.resok.obj_attributes.size / NFS_BLKSIZE;
st.st_blocks = (res->GETATTR3res_u.resok.obj_attributes.used + 512 - 1) / 512;
#endif//WIN32
st.st_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds;
st.st_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds;
st.st_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds;
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
st.st_atim.tv_nsec = res->GETATTR3res_u.resok.obj_attributes.atime.nseconds;
st.st_mtim.tv_nsec = res->GETATTR3res_u.resok.obj_attributes.mtime.nseconds;
st.st_ctim.tv_nsec = res->GETATTR3res_u.resok.obj_attributes.ctime.nseconds;
#endif
data->cb(0, nfs, &st, data->private_data);
free_nfs_cb_data(data);
@ -1318,23 +1357,46 @@ static void nfs_stat64_1_cb(struct rpc_context *rpc, int status, void *command_d
return;
}
st.nfs_dev = -1;
st.nfs_dev = res->GETATTR3res_u.resok.obj_attributes.fsid;
st.nfs_ino = res->GETATTR3res_u.resok.obj_attributes.fileid;
st.nfs_mode = res->GETATTR3res_u.resok.obj_attributes.mode;
if (res->GETATTR3res_u.resok.obj_attributes.type == NF3DIR) {
st.nfs_mode |= S_IFDIR ;
}
if (res->GETATTR3res_u.resok.obj_attributes.type == NF3REG) {
st.nfs_mode |= S_IFREG ;
switch (res->GETATTR3res_u.resok.obj_attributes.type) {
case NF3REG:
st.nfs_mode |= S_IFREG;
break;
case NF3DIR:
st.nfs_mode |= S_IFDIR;
break;
case NF3BLK:
st.nfs_mode |= S_IFBLK;
break;
case NF3CHR:
st.nfs_mode |= S_IFCHR;
break;
case NF3LNK:
st.nfs_mode |= S_IFLNK;
break;
case NF3SOCK:
st.nfs_mode |= S_IFSOCK;
break;
case NF3FIFO:
st.nfs_mode |= S_IFIFO;
break;
}
st.nfs_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink;
st.nfs_uid = res->GETATTR3res_u.resok.obj_attributes.uid;
st.nfs_gid = res->GETATTR3res_u.resok.obj_attributes.gid;
st.nfs_rdev = 0;
st.nfs_rdev = specdata3_to_rdev(&res->GETATTR3res_u.resok.obj_attributes.rdev);
st.nfs_size = res->GETATTR3res_u.resok.obj_attributes.size;
st.nfs_blksize = NFS_BLKSIZE;
st.nfs_blocks = (res->GETATTR3res_u.resok.obj_attributes.used + 512 - 1) / 512;
st.nfs_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds;
st.nfs_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds;
st.nfs_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds;
st.nfs_atime_nsec = res->GETATTR3res_u.resok.obj_attributes.atime.nseconds;
st.nfs_mtime_nsec = res->GETATTR3res_u.resok.obj_attributes.mtime.nseconds;
st.nfs_ctime_nsec = res->GETATTR3res_u.resok.obj_attributes.ctime.nseconds;
st.nfs_used = res->GETATTR3res_u.resok.obj_attributes.used;
data->cb(0, nfs, &st, data->private_data);
free_nfs_cb_data(data);
@ -2991,13 +3053,21 @@ static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_d
nfsdirent->atime.tv_sec = attributes->atime.seconds;
nfsdirent->atime.tv_usec = attributes->atime.nseconds/1000;
nfsdirent->atime_nsec = attributes->atime.nseconds;
nfsdirent->mtime.tv_sec = attributes->mtime.seconds;
nfsdirent->mtime.tv_usec = attributes->mtime.nseconds/1000;
nfsdirent->mtime_nsec = attributes->mtime.nseconds;
nfsdirent->ctime.tv_sec = attributes->ctime.seconds;
nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000;
nfsdirent->ctime_nsec = attributes->ctime.nseconds;
nfsdirent->uid = attributes->uid;
nfsdirent->gid = attributes->gid;
nfsdirent->nlink = attributes->nlink;
nfsdirent->dev = attributes->fsid;
nfsdirent->rdev = specdata3_to_rdev(&attributes->rdev);
nfsdirent->blksize = NFS_BLKSIZE;
nfsdirent->blocks = (attributes->used + 512 - 1) / 512;
nfsdirent->used = attributes->used;
}
}
@ -3232,13 +3302,21 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da
nfsdirent->atime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.atime.seconds;
nfsdirent->atime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.atime.nseconds/1000;
nfsdirent->atime_nsec = entry->name_attributes.post_op_attr_u.attributes.atime.nseconds;
nfsdirent->mtime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.mtime.seconds;
nfsdirent->mtime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.mtime.nseconds/1000;
nfsdirent->mtime_nsec = entry->name_attributes.post_op_attr_u.attributes.mtime.nseconds;
nfsdirent->ctime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.ctime.seconds;
nfsdirent->ctime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.ctime.nseconds/1000;
nfsdirent->ctime_nsec = entry->name_attributes.post_op_attr_u.attributes.ctime.nseconds;
nfsdirent->uid = entry->name_attributes.post_op_attr_u.attributes.uid;
nfsdirent->gid = entry->name_attributes.post_op_attr_u.attributes.gid;
nfsdirent->nlink = entry->name_attributes.post_op_attr_u.attributes.nlink;
nfsdirent->dev = entry->name_attributes.post_op_attr_u.attributes.fsid;
nfsdirent->rdev = specdata3_to_rdev(&entry->name_attributes.post_op_attr_u.attributes.rdev);
nfsdirent->blksize = NFS_BLKSIZE;
nfsdirent->blocks = (entry->name_attributes.post_op_attr_u.attributes.used + 512 - 1) / 512;
nfsdirent->used = entry->name_attributes.post_op_attr_u.attributes.used;
}
nfsdirent->next = nfsdir->entries;