All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH] lib: add [SAFE_]FILE_LINES_SCANF
@ 2016-07-14 10:35 Jan Stancek
  2016-07-18 11:36 ` Cyril Hrubis
  0 siblings, 1 reply; 3+ messages in thread
From: Jan Stancek @ 2016-07-14 10:35 UTC (permalink / raw)
  To: ltp

This patch adds 2 macros that try to parse each line from
a file according to user-supplied (scanf) format. First line
that matches all format directives ends the search. If EOF
is reached, SAFE_ version triggers TBROK, non-SAFE_ returns
non-zero retcode to user.

Main motivation is parsing various /proc files, for example:
  if (FILE_LINES_SCANF("/proc/meminfo", "MemFree: %ld", &free))
      do_something();

  SAFE_FILE_LINES_SCANF("/proc/meminfo", "MemFree: %ld", &free);
      // automatically calls TBROK if all directives can't be matched

Signed-off-by: Jan Stancek <jstancek@redhat.com>
---
 .gitignore                      |  1 +
 include/old/old_safe_file_ops.h |  8 +++++++
 include/safe_file_ops_fn.h      |  5 +++++
 include/tst_safe_file_ops.h     |  8 +++++++
 lib/safe_file_ops.c             | 47 +++++++++++++++++++++++++++++++++++++++++
 lib/tests/tst_safe_fileops.c    | 40 +++++++++++++++++++++++++++++++++++
 6 files changed, 109 insertions(+)
 create mode 100644 lib/tests/tst_safe_fileops.c

diff --git a/.gitignore b/.gitignore
index 1b4ac3e46249..2775c2a656e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,3 +73,4 @@ logfile.*
 /lib/tests/tst_dataroot01
 /lib/tests/tst_dataroot02
 /lib/tests/tst_dataroot03
+/lib/tests/tst_safe_fileops
diff --git a/include/old/old_safe_file_ops.h b/include/old/old_safe_file_ops.h
index d656823e46fa..d6e2d29a9690 100644
--- a/include/old/old_safe_file_ops.h
+++ b/include/old/old_safe_file_ops.h
@@ -38,6 +38,14 @@
 	safe_file_scanf(__FILE__, __LINE__, (cleanup_fn), \
 	                (path), (fmt), ## __VA_ARGS__)
 
+#define FILE_LINES_SCANF(cleanup_fn, path, fmt, ...) \
+	file_lines_scanf(__FILE__, __LINE__, (cleanup_fn), 0, \
+			(path), (fmt), ## __VA_ARGS__)
+
+#define SAFE_FILE_LINES_SCANF(cleanup_fn, path, fmt, ...) \
+	file_lines_scanf(__FILE__, __LINE__, (cleanup_fn), 1, \
+			(path), (fmt), ## __VA_ARGS__)
+
 #define FILE_PRINTF(path, fmt, ...) \
 	file_printf(__FILE__, __LINE__, \
 	            (path), (fmt), ## __VA_ARGS__)
diff --git a/include/safe_file_ops_fn.h b/include/safe_file_ops_fn.h
index cdb0f7436909..35ec4fb1f8ee 100644
--- a/include/safe_file_ops_fn.h
+++ b/include/safe_file_ops_fn.h
@@ -35,6 +35,11 @@ void safe_file_scanf(const char *file, const int lineno,
 		     const char *path, const char *fmt, ...)
 		     __attribute__ ((format (scanf, 5, 6)));
 
+int file_lines_scanf(const char *file, const int lineno,
+		     void (*cleanup_fn)(void), int strict,
+		     const char *path, const char *fmt, ...)
+		     __attribute__ ((format (scanf, 6, 7)));
+
 /*
  * All-in-one function that lets you printf directly into a file.
  */
diff --git a/include/tst_safe_file_ops.h b/include/tst_safe_file_ops.h
index 74e679153d8a..2e4067ca15fd 100644
--- a/include/tst_safe_file_ops.h
+++ b/include/tst_safe_file_ops.h
@@ -30,6 +30,14 @@
 	safe_file_scanf(__FILE__, __LINE__, NULL, \
 	                (path), (fmt), ## __VA_ARGS__)
 
+#define FILE_LINES_SCANF(path, fmt, ...) \
+	file_lines_scanf(__FILE__, __LINE__, NULL, 0,\
+			(path), (fmt), ## __VA_ARGS__)
+
+#define SAFE_FILE_LINES_SCANF(path, fmt, ...) \
+	file_lines_scanf(__FILE__, __LINE__, NULL, 1,\
+			(path), (fmt), ## __VA_ARGS__)
+
 #define SAFE_FILE_PRINTF(path, fmt, ...) \
 	safe_file_printf(__FILE__, __LINE__, NULL, \
 	                 (path), (fmt), ## __VA_ARGS__)
diff --git a/lib/safe_file_ops.c b/lib/safe_file_ops.c
index dff85cd83fec..01f64ed3251b 100644
--- a/lib/safe_file_ops.c
+++ b/lib/safe_file_ops.c
@@ -169,6 +169,53 @@ void safe_file_scanf(const char *file, const int lineno,
 	}
 }
 
+
+/*
+ * Try to parse each line from file specified by 'path' according
+ * to scanf format 'fmt'. If all fields could be parsed, stop and
+ * return 0, otherwise continue or return 1 if EOF is reached.
+ */
+int file_lines_scanf(const char *file, const int lineno,
+		     void (*cleanup_fn)(void), int strict,
+		     const char *path, const char *fmt, ...)
+{
+	FILE *fp;
+	int ret = 0;
+	int arg_count = 0;
+	char line[BUFSIZ];
+	va_list ap;
+
+	if (!fmt) {
+		tst_brkm(TBROK, cleanup_fn, "pattern is NULL, %s:%d",
+			file, lineno);
+	}
+
+	fp = fopen(path, "r");
+	if (fp == NULL) {
+		tst_brkm(TBROK | TERRNO, cleanup_fn,
+			"Failed to open FILE '%s' for reading at %s:%d",
+			path, file, lineno);
+	}
+
+	arg_count = count_scanf_conversions(fmt);
+
+	while (fgets(line, BUFSIZ, fp) != NULL) {
+		va_start(ap, fmt);
+		ret = vsscanf(line, fmt, ap);
+		va_end(ap);
+
+		if (ret == arg_count)
+			break;
+	}
+	fclose(fp);
+
+	if (strict && ret != arg_count)
+		tst_brkm(TBROK, cleanup_fn, "Expected %i conversions got %i"
+			" at %s:%d", arg_count, ret, file, lineno);
+
+	return !(ret == arg_count);
+}
+
 int file_printf(const char *file, const int lineno,
 		      const char *path, const char *fmt, ...)
 {
diff --git a/lib/tests/tst_safe_fileops.c b/lib/tests/tst_safe_fileops.c
new file mode 100644
index 000000000000..bdf4e9d07027
--- /dev/null
+++ b/lib/tests/tst_safe_fileops.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Linux Test Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include "tst_test.h"
+
+static void do_test(void)
+{
+	long free;
+	long nproc;
+	long dummy;
+
+	SAFE_FILE_LINES_SCANF("/proc/meminfo", "MemFree: %ld", &free);
+	if (FILE_LINES_SCANF("/proc/stat", "processes %ld", &nproc))
+		tst_brk(TBROK, "Could not parse processes");
+	tst_res(TPASS, "Free: %ld, nproc: %ld", free, nproc);
+
+	if (FILE_LINES_SCANF("/proc/stat", "non-existent %ld", &dummy))
+		tst_res(TPASS, "non-existent not found");
+	SAFE_FILE_LINES_SCANF("/proc/stat", "non-existent %ld", &dummy);
+}
+
+static struct tst_test test = {
+	.tid = "tst_safe_fileops",
+	.test_all = do_test,
+};
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [LTP] [PATCH] lib: add [SAFE_]FILE_LINES_SCANF
  2016-07-14 10:35 [LTP] [PATCH] lib: add [SAFE_]FILE_LINES_SCANF Jan Stancek
@ 2016-07-18 11:36 ` Cyril Hrubis
  2016-07-18 13:52   ` Jan Stancek
  0 siblings, 1 reply; 3+ messages in thread
From: Cyril Hrubis @ 2016-07-18 11:36 UTC (permalink / raw)
  To: ltp

Hi!
>  lib/tests/tst_safe_fileops.c    | 40 +++++++++++++++++++++++++++++++++++

The last minor nitpick is that the lib/tests/ directory is full of
oldlib tests and this is a newlib test. It may be better to add this
file to the lib/newlib_tests/.

Anyway this version looks fine, acked.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [LTP] [PATCH] lib: add [SAFE_]FILE_LINES_SCANF
  2016-07-18 11:36 ` Cyril Hrubis
@ 2016-07-18 13:52   ` Jan Stancek
  0 siblings, 0 replies; 3+ messages in thread
From: Jan Stancek @ 2016-07-18 13:52 UTC (permalink / raw)
  To: ltp





----- Original Message -----
> From: "Cyril Hrubis" <chrubis@suse.cz>
> To: "Jan Stancek" <jstancek@redhat.com>
> Cc: ltp@lists.linux.it
> Sent: Monday, 18 July, 2016 1:36:44 PM
> Subject: Re: [LTP] [PATCH] lib: add [SAFE_]FILE_LINES_SCANF
> 
> Hi!
> >  lib/tests/tst_safe_fileops.c    | 40 +++++++++++++++++++++++++++++++++++
> 
> The last minor nitpick is that the lib/tests/ directory is full of
> oldlib tests and this is a newlib test. It may be better to add this
> file to the lib/newlib_tests/.

Moved and pushed.

Regards,
Jan

> 
> Anyway this version looks fine, acked.
> 
> --
> Cyril Hrubis
> chrubis@suse.cz
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-07-18 13:52 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-14 10:35 [LTP] [PATCH] lib: add [SAFE_]FILE_LINES_SCANF Jan Stancek
2016-07-18 11:36 ` Cyril Hrubis
2016-07-18 13:52   ` Jan Stancek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.