From: Ronnie Sahlberg Date: Wed, 5 Mar 2014 03:40:05 +0000 (-0800) Subject: Add a new nfs_stat64() function that operates on a always-64-bit stat structure X-Git-Tag: upstream/1.9.6^2~84 X-Git-Url: https://git.piment-noir.org/?p=deb_libnfs.git;a=commitdiff_plain;h=479302f72943be9f45d6b18c82c5502be12efa5a Add a new nfs_stat64() function that operates on a always-64-bit stat structure --- diff --git a/examples/nfs-ls.c b/examples/nfs-ls.c index e87ffa8..f6b223d 100644 --- a/examples/nfs-ls.c +++ b/examples/nfs-ls.c @@ -91,7 +91,7 @@ void process_dir(struct nfs_context *nfs, char *dir, int level) { struct nfsdirent *nfsdirent; struct statvfs svfs; struct nfsdir *nfsdir; - struct stat st; + struct nfs_stat_64 st; if (!level) { printf("Recursion detected!\n"); @@ -111,13 +111,13 @@ void process_dir(struct nfs_context *nfs, char *dir, int level) { } snprintf(path, 1024, "%s/%s", dir, nfsdirent->name); - ret = nfs_stat(nfs, path, &st); + ret = nfs_stat64(nfs, path, &st); if (ret != 0) { fprintf(stderr, "Failed to stat(%s) %s\n", path, nfs_get_error(nfs)); continue; } - switch (st.st_mode & S_IFMT) { + switch (st.nfs_mode & S_IFMT) { #ifndef WIN32 case S_IFLNK: printf("l"); @@ -137,28 +137,28 @@ void process_dir(struct nfs_context *nfs, char *dir, int level) { break; } printf("%c%c%c", - "-r"[!!(st.st_mode & S_IRUSR)], - "-w"[!!(st.st_mode & S_IWUSR)], - "-x"[!!(st.st_mode & S_IXUSR)] + "-r"[!!(st.nfs_mode & S_IRUSR)], + "-w"[!!(st.nfs_mode & S_IWUSR)], + "-x"[!!(st.nfs_mode & S_IXUSR)] ); printf("%c%c%c", - "-r"[!!(st.st_mode & S_IRGRP)], - "-w"[!!(st.st_mode & S_IWGRP)], - "-x"[!!(st.st_mode & S_IXGRP)] + "-r"[!!(st.nfs_mode & S_IRGRP)], + "-w"[!!(st.nfs_mode & S_IWGRP)], + "-x"[!!(st.nfs_mode & S_IXGRP)] ); printf("%c%c%c", - "-r"[!!(st.st_mode & S_IROTH)], - "-w"[!!(st.st_mode & S_IWOTH)], - "-x"[!!(st.st_mode & S_IXOTH)] + "-r"[!!(st.nfs_mode & S_IROTH)], + "-w"[!!(st.nfs_mode & S_IWOTH)], + "-x"[!!(st.nfs_mode & S_IXOTH)] ); - printf(" %2d", (int) st.st_nlink); - printf(" %5d", st.st_uid); - printf(" %5d", st.st_gid); - printf(" %12" PRId64, st.st_size); + printf(" %2d", (int)st.nfs_nlink); + printf(" %5d", (int)st.nfs_uid); + printf(" %5d", (int)st.nfs_gid); + printf(" %12" PRId64, st.nfs_size); printf(" %s\n", path + 1); - if (recursive && (st.st_mode & S_IFMT) == S_IFDIR) { + if (recursive && (st.nfs_mode & S_IFMT) == S_IFDIR) { process_dir(nfs, path, level - 1); } } diff --git a/include/nfsc/libnfs.h b/include/nfsc/libnfs.h index 4657111..406fcdf 100644 --- a/include/nfsc/libnfs.h +++ b/include/nfsc/libnfs.h @@ -224,6 +224,7 @@ EXTERN int nfs_mount(struct nfs_context *nfs, const char *server, const char *ex * -errno : An error occured. * data is the error string. */ +/* This function is deprecated. Use nfs_stat64_async() instead */ struct stat; EXTERN int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); /* @@ -232,12 +233,59 @@ EXTERN int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, * 0 : The operation was successfull. * -errno : The command failed. */ +/* This function is deprecated. Use nfs_stat64() instead */ #ifdef WIN32 EXTERN int nfs_stat(struct nfs_context *nfs, const char *path, struct __stat64 *st); #else EXTERN int nfs_stat(struct nfs_context *nfs, const char *path, struct stat *st); #endif + +/* nfs_stat64 + * 64 bit version if stat. All fields are always 64bit. + * Use these functions instead of nfs_stat[_async](), especially if you + * have weird stat structures. + */ +/* + * STAT() + */ +struct nfs_stat_64 { + uint64_t nfs_dev; + uint64_t nfs_ino; + uint64_t nfs_mode; + uint64_t nfs_nlink; + uint64_t nfs_uid; + uint64_t nfs_gid; + uint64_t nfs_rdev; + uint64_t nfs_size; + uint64_t nfs_blksize; + uint64_t nfs_blocks; + uint64_t nfs_atime; + uint64_t nfs_mtime; + uint64_t nfs_ctime; +}; + +/* + * Async stat() + * Function returns + * 0 : The operation was initiated. Once the operation finishes, the callback will be invoked. + * <0 : An error occured when trying to set up the operation. The callback will not be invoked. + * + * When the callback is invoked, status indicates the result: + * 0 : Success. + * data is struct nfs_stat_64 * + * -errno : An error occured. + * data is the error string. + */ +EXTERN int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data); +/* + * Sync stat() + * Function returns + * 0 : The operation was successfull. + * -errno : The command failed. + */ +EXTERN int nfs_stat64(struct nfs_context *nfs, const char *path, struct nfs_stat_64 *st); + /* * FSTAT() */ diff --git a/lib/libnfs-sync.c b/lib/libnfs-sync.c index 580f76d..7ba5222 100644 --- a/lib/libnfs-sync.c +++ b/lib/libnfs-sync.c @@ -236,6 +236,36 @@ int nfs_stat(struct nfs_context *nfs, const char *path, struct stat *st) return cb_data.status; } +static void stat64_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, "stat call failed with \"%s\"", (char *)data); + return; + } + memcpy(cb_data->return_data, data, sizeof(struct nfs_stat_64)); +} + +int nfs_stat64(struct nfs_context *nfs, const char *path, struct nfs_stat_64 *st) +{ + struct sync_cb_data cb_data; + + cb_data.is_finished = 0; + cb_data.return_data = st; + + if (nfs_stat64_async(nfs, path, stat64_cb, &cb_data) != 0) { + nfs_set_error(nfs, "nfs_stat64_async failed"); + return -1; + } + + wait_for_nfs_reply(nfs, &cb_data); + + return cb_data.status; +} /* * open() diff --git a/lib/libnfs-win32.def b/lib/libnfs-win32.def index 6461d5d..100f0cb 100644 --- a/lib/libnfs-win32.def +++ b/lib/libnfs-win32.def @@ -72,6 +72,8 @@ nfs_set_tcp_syncnt nfs_set_uid nfs_stat nfs_stat_async +nfs_stat64 +nfs_stat64_async nfs_statvfs nfs_statvfs_async nfs_symlink diff --git a/lib/libnfs.c b/lib/libnfs.c index 66f13a3..cfddf29 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -1230,6 +1230,84 @@ int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *p } +/* + * Async nfs_stat64() + */ +static void nfs_stat64_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + GETATTR3res *res; + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + struct nfs_stat_64 st; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR) { + data->cb(-EFAULT, nfs, command_data, data->private_data); + free_nfs_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); + free_nfs_cb_data(data); + return; + } + + res = command_data; + if (res->status != NFS3_OK) { + rpc_set_error(nfs->rpc, "NFS: GETATTR 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, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return; + } + + st.nfs_dev = -1; + 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 ; + } + 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_size = res->GETATTR3res_u.resok.obj_attributes.size; + 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; + + data->cb(0, nfs, &st, data->private_data); + free_nfs_cb_data(data); +} + +static int nfs_stat64_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +{ + struct GETATTR3args args; + + memset(&args, 0, sizeof(GETATTR3args)); + args.object = data->fh; + + if (rpc_nfs3_getattr_async(nfs->rpc, nfs_stat64_1_cb, &args, data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return -1; + } + return 0; +} + +int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) +{ + if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_stat64_continue_internal, NULL, NULL, 0) != 0) { + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; + } + + return 0; +} /* * Async open()