[LTP] [PATCH 2/5] Add safe readv()/writev() functions

Martin Doucha mdoucha@suse.cz
Fri Nov 1 15:11:07 CET 2024


Add safe macros for vectorized I/O functions:
- SAFE_READV()
- SAFE_PREADV()
- SAFE_WRITEV()
- SAFE_PWRITEV()

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 include/lapi/uio.h        |  1 +
 include/tst_safe_macros.h | 13 +++++++++
 include/tst_safe_prw.h    | 58 +++++++++++++++++++++++++++++++++++++++
 lib/tst_safe_macros.c     | 45 ++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+)

diff --git a/include/lapi/uio.h b/include/lapi/uio.h
index a78103d99..0ad2faacf 100644
--- a/include/lapi/uio.h
+++ b/include/lapi/uio.h
@@ -7,6 +7,7 @@
 #ifndef LAPI_PREADV2_H__
 #define LAPI_PREADV2_H__
 
+#include <sys/uio.h>
 #include "config.h"
 #include "lapi/syscalls.h"
 
diff --git a/include/tst_safe_macros.h b/include/tst_safe_macros.h
index 4df23e602..a9fa7dbe1 100644
--- a/include/tst_safe_macros.h
+++ b/include/tst_safe_macros.h
@@ -14,6 +14,7 @@
 #include <sys/stat.h>
 #include <sys/vfs.h>
 #include <sys/sysinfo.h>
+#include <sys/uio.h>
 #include <fcntl.h>
 #include <libgen.h>
 #include <signal.h>
@@ -515,4 +516,16 @@ int safe_symlinkat(const char *file, const int lineno,
 #define SAFE_SYMLINKAT(oldpath, newdirfd, newpath) \
 	safe_symlinkat(__FILE__, __LINE__, (oldpath), (newdirfd), (newpath))
 
+ssize_t safe_readv(const char *file, const int lineno, char len_strict,
+	int fildes, const struct iovec *iov, int iovcnt);
+#define SAFE_READV(len_strict, fildes, iov, iovcnt) \
+	safe_readv(__FILE__, __LINE__, (len_strict), (fildes), \
+		(iov), (iovcnt))
+
+ssize_t safe_writev(const char *file, const int lineno, char len_strict,
+	int fildes, const struct iovec *iov, int iovcnt);
+#define SAFE_WRITEV(len_strict, fildes, iov, iovcnt) \
+	safe_writev(__FILE__, __LINE__, (len_strict), (fildes), \
+		(iov), (iovcnt))
+
 #endif /* TST_SAFE_MACROS_H__ */
diff --git a/include/tst_safe_prw.h b/include/tst_safe_prw.h
index 2e506cb41..349fb46b4 100644
--- a/include/tst_safe_prw.h
+++ b/include/tst_safe_prw.h
@@ -5,6 +5,8 @@
 #ifndef TST_SAFE_PRW_H__
 #define TST_SAFE_PRW_H__
 
+#include "lapi/uio.h"
+
 static inline ssize_t safe_pread(const char *file, const int lineno,
 		char len_strict, int fildes, void *buf, size_t nbyte,
 		off_t offset)
@@ -52,4 +54,60 @@ static inline ssize_t safe_pwrite(const char *file, const int lineno,
 	safe_pwrite(__FILE__, __LINE__, (len_strict), (fildes), \
 	            (buf), (nbyte), (offset))
 
+static inline ssize_t safe_preadv(const char *file, const int lineno,
+	char len_strict, int fildes, const struct iovec *iov, int iovcnt,
+	off_t offset)
+{
+	ssize_t rval, nbyte;
+	int i;
+
+	for (i = 0, nbyte = 0; i < iovcnt; i++)
+		nbyte += iov[i].iov_len;
+
+	rval = preadv(fildes, iov, iovcnt, offset);
+
+	if (rval == -1 || (len_strict && rval != nbyte)) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"preadv(%d,%p,%d,%lld) failed",
+			fildes, iov, iovcnt, (long long)offset);
+	} else if (rval < 0) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid preadv(%d,%p,%d,%lld) return value %zd",
+			fildes, iov, iovcnt, (long long)offset, rval);
+	}
+
+	return rval;
+}
+#define SAFE_PREADV(len_strict, fildes, iov, iovcnt, offset) \
+	safe_preadv(__FILE__, __LINE__, (len_strict), (fildes), \
+		(iov), (iovcnt), (offset))
+
+static inline ssize_t safe_pwritev(const char *file, const int lineno,
+	char len_strict, int fildes, const struct iovec *iov, int iovcnt,
+	off_t offset)
+{
+	ssize_t rval, nbyte;
+	int i;
+
+	for (i = 0, nbyte = 0; i < iovcnt; i++)
+		nbyte += iov[i].iov_len;
+
+	rval = pwritev(fildes, iov, iovcnt, offset);
+
+	if (rval == -1 || (len_strict && rval != nbyte)) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"pwritev(%d,%p,%d,%lld) failed",
+			fildes, iov, iovcnt, (long long)offset);
+	} else if (rval < 0) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid pwritev(%d,%p,%d,%lld) return value %zd",
+			fildes, iov, iovcnt, (long long)offset, rval);
+	}
+
+	return rval;
+}
+#define SAFE_PWRITEV(len_strict, fildes, iov, iovcnt, offset) \
+	safe_pwritev(__FILE__, __LINE__, (len_strict), (fildes), \
+		(iov), (iovcnt), (offset))
+
 #endif /* SAFE_PRW_H__ */
diff --git a/lib/tst_safe_macros.c b/lib/tst_safe_macros.c
index 868ebc08e..633b00404 100644
--- a/lib/tst_safe_macros.c
+++ b/lib/tst_safe_macros.c
@@ -732,6 +732,29 @@ int safe_prctl(const char *file, const int lineno,
 	return rval;
 }
 
+ssize_t safe_readv(const char *file, const int lineno, char len_strict,
+	int fildes, const struct iovec *iov, int iovcnt)
+{
+	ssize_t rval, nbyte;
+	int i;
+
+	for (i = 0, nbyte = 0; i < iovcnt; i++)
+		nbyte += iov[i].iov_len;
+
+	rval = readv(fildes, iov, iovcnt);
+
+	if (rval == -1 || (len_strict && rval != nbyte)) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"readv(%d,%p,%d) failed", fildes, iov, iovcnt);
+	} else if (rval < 0) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid readv(%d,%p,%d) return value %zd",
+			fildes, iov, iovcnt, rval);
+	}
+
+	return rval;
+}
+
 int safe_symlinkat(const char *file, const int lineno,
                  const char *oldpath, const int newdirfd, const char *newpath)
 {
@@ -751,3 +774,25 @@ int safe_symlinkat(const char *file, const int lineno,
 	return rval;
 }
 
+ssize_t safe_writev(const char *file, const int lineno, char len_strict,
+	int fildes, const struct iovec *iov, int iovcnt)
+{
+	ssize_t rval, nbyte;
+	int i;
+
+	for (i = 0, nbyte = 0; i < iovcnt; i++)
+		nbyte += iov[i].iov_len;
+
+	rval = writev(fildes, iov, iovcnt);
+
+	if (rval == -1 || (len_strict && rval != nbyte)) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"writev(%d,%p,%d) failed", fildes, iov, iovcnt);
+	} else if (rval < 0) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			"Invalid writev(%d,%p,%d) return value %zd",
+			fildes, iov, iovcnt, rval);
+	}
+
+	return rval;
+}
-- 
2.46.0



More information about the ltp mailing list