From bf769f960dc086ca35e60a1ecf88ebc385e1c222 Mon Sep 17 00:00:00 2001
From: Ross Lagerwall <rosslagerwall@gmail.com>
Date: Sun, 27 Jul 2014 21:00:26 +0100
Subject: [PATCH] libnfs: Add lstat

Add lstat which is like stat but operates on the symbolic link itself if
the destination is a symbolic link.

Signed-off-by: Ross Lagerwall <rosslagerwall@gmail.com>
---
 include/nfsc/libnfs.h | 29 +++++++++++++++++++++++++++++
 lib/libnfs-sync.c     | 17 +++++++++++++++++
 lib/libnfs.c          | 14 ++++++++++++--
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/include/nfsc/libnfs.h b/include/nfsc/libnfs.h
index a806fdb..48a70ba 100644
--- a/include/nfsc/libnfs.h
+++ b/include/nfsc/libnfs.h
@@ -297,6 +297,35 @@ EXTERN int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb
  */
 EXTERN int nfs_stat64(struct nfs_context *nfs, const char *path, struct nfs_stat_64 *st);
 
+/*
+ * Async stat(<filename>)
+ *
+ * Like stat except if the destination is a symbolic link, it acts on the
+ * symbolic link itself.
+ *
+ * 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_lstat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data);
+/*
+ * Sync stat(<filename>)
+ *
+ * Like stat except if the destination is a symbolic link, it acts on the
+ * symbolic link itself.
+ *
+ * Function returns
+ *      0 : The operation was successfull.
+ * -errno : The command failed.
+ */
+EXTERN int nfs_lstat64(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 a31a607..8b57cb4 100644
--- a/lib/libnfs-sync.c
+++ b/lib/libnfs-sync.c
@@ -268,6 +268,23 @@ int nfs_stat64(struct nfs_context *nfs, const char *path, struct nfs_stat_64 *st
 	return cb_data.status;
 }
 
+int nfs_lstat64(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_lstat64_async(nfs, path, stat64_cb, &cb_data) != 0) {
+		nfs_set_error(nfs, "nfs_lstat64_async failed");
+		return -1;
+	}
+
+	wait_for_nfs_reply(nfs, &cb_data);
+
+	return cb_data.status;
+}
+
 /*
  * open()
  */
diff --git a/lib/libnfs.c b/lib/libnfs.c
index a7ac3ef..290360e 100644
--- a/lib/libnfs.c
+++ b/lib/libnfs.c
@@ -1548,9 +1548,9 @@ static int nfs_stat64_continue_internal(struct nfs_context *nfs, fattr3 *attr _U
 	return 0;
 }
 
-int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
+int nfs_stat64_async_internal(struct nfs_context *nfs, const char *path, int no_follow, nfs_cb cb, void *private_data)
 {
-	if (nfs_lookuppath_async(nfs, path, 0, cb, private_data, nfs_stat64_continue_internal, NULL, NULL, 0) != 0) {
+	if (nfs_lookuppath_async(nfs, path, no_follow, 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;
 	}
@@ -1558,6 +1558,16 @@ int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void
 	return 0;
 }
 
+int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
+{
+	return nfs_stat64_async_internal(nfs, path, 0, cb, private_data);
+}
+
+int nfs_lstat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
+{
+	return nfs_stat64_async_internal(nfs, path, 1, cb, private_data);
+}
+
 /*
  * Async open()
  */
-- 
2.43.0