[PATCH v2 1/2] libbb: add support for tallying with files

Hemmo Nieminen hemmo.nieminen at iki.fi
Mon May 17 12:22:41 UTC 2021


From: Hemmo Nieminen <hemmo.nieminen at kone.com>

Signed-off-by: Hemmo Nieminen <hemmo.nieminen at kone.com>
---
 include/libbb.h  |   4 ++
 libbb/Config.src |   6 +++
 libbb/Kbuild.src |   1 +
 libbb/bb_tally.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 148 insertions(+)
 create mode 100644 libbb/bb_tally.c

diff --git a/include/libbb.h b/include/libbb.h
index 03f9c35f3..50a302f17 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2587,6 +2587,10 @@ void bbunit_settestfailed(void);
 		} \
 	} while (0)
 
+#if ENABLE_FEATURE_TALLY
+int FAST_FUNC bb_tally_add(char const * const path);
+int FAST_FUNC bb_tally_reset(char const * const path);
+#endif
 
 POP_SAVED_FUNCTION_VISIBILITY
 
diff --git a/libbb/Config.src b/libbb/Config.src
index f97de8ef7..23d821916 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -395,3 +395,9 @@ config FEATURE_HWIB
 	default y
 	help
 	Support for printing infiniband addresses in network applets.
+
+config FEATURE_TALLY
+	bool "Support tallying with files"
+	default n
+	help
+	Add support to libbb for tallying e.g. events via files.
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 676300801..35448f805 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -153,6 +153,7 @@ lib-$(CONFIG_SULOGIN) += pw_encrypt.o correct_password.o
 lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o
 lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o
 lib-$(CONFIG_LOGIN) += pw_encrypt.o correct_password.o
+lib-$(CONFIG_FEATURE_TALLY) += bb_tally.o
 lib-$(CONFIG_FEATURE_HTTPD_AUTH_MD5) += pw_encrypt.o
 lib-$(CONFIG_FEATURE_FTP_AUTHENTICATION) += pw_encrypt.o
 
diff --git a/libbb/bb_tally.c b/libbb/bb_tally.c
new file mode 100644
index 000000000..05e06a0cf
--- /dev/null
+++ b/libbb/bb_tally.c
@@ -0,0 +1,137 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines to do tallying with files.
+ *
+ * Copyright (C) 2021 Hemmo Nieminen
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "libbb.h"
+
+int FAST_FUNC
+bb_tally_add(char const * const path)
+{
+	int retval = 0;
+	FILE * f;
+	struct stat buf;
+	int fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+
+	if (fd < 0)
+		return -1;;
+
+	f = fdopen(fd, "w+");
+	if (!f) {
+		close(fd);
+		return -1;
+	}
+
+	if (fstat(fd, &buf) < 0
+			|| buf.st_uid != getuid()
+			|| (buf.st_size != 0 && (fscanf(f, "%d", &retval) != 1 || retval < 0))
+			|| fseek(f, 0, SEEK_SET) < 0
+			|| fprintf(f, "%d", ++retval) < 1) {
+		fclose(f);
+		return -1;
+	}
+
+	if (fclose(f) < 0)
+		return -1;
+
+	return retval;
+}
+
+int FAST_FUNC
+bb_tally_reset(char const * const path)
+{
+	struct stat buf;
+
+	if (stat(path, &buf) == 0 && buf.st_uid == geteuid())
+		return remove(path);
+
+	return 0;
+}
+
+#if ENABLE_UNIT_TEST
+
+#define TALLY_FILE_PREFIX "tally_test."
+
+BBUNIT_DEFINE_TEST(test_tally_add)
+{
+	remove(TALLY_FILE_PREFIX "one");
+	remove(TALLY_FILE_PREFIX "two");
+	remove(TALLY_FILE_PREFIX "three");
+
+	for (int i = 0; i < 1000; i++) {
+		BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "one"), i + 1);
+		BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 2*i + 1);
+		BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "three"), i + 1);
+		BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 2*i + 2);
+	}
+
+	BBUNIT_ASSERT_EQ(bb_tally_reset(TALLY_FILE_PREFIX "three"), 0);
+	BBUNIT_ASSERT_EQ(bb_tally_reset(TALLY_FILE_PREFIX "one"), 0);
+
+	for (int i = 0; i < 1000; i++) {
+		BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "one"), i + 1);
+		BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 2000 + i + 1);
+		BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "three"), i + 1);
+	}
+
+	BBUNIT_ENDTEST;
+
+	remove(TALLY_FILE_PREFIX "one");
+	remove(TALLY_FILE_PREFIX "two");
+	remove(TALLY_FILE_PREFIX "three");
+}
+
+BBUNIT_DEFINE_TEST(test_tally_reset)
+{
+	remove(TALLY_FILE_PREFIX "one");
+	remove(TALLY_FILE_PREFIX "two");
+	remove(TALLY_FILE_PREFIX "three");
+
+	BBUNIT_ASSERT_EQ(bb_tally_reset(TALLY_FILE_PREFIX "two"), 0);
+
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "three"), 1);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 1);
+	BBUNIT_ASSERT_EQ(bb_tally_reset(TALLY_FILE_PREFIX "two"), 0);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "three"), 2);
+
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 1);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 2);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 3);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 4);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "one"), 1);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "one"), 2);
+	BBUNIT_ASSERT_EQ(bb_tally_reset(TALLY_FILE_PREFIX "two"), 0);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "one"), 3);
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "two"), 1);
+
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "three"), 3);
+	BBUNIT_ASSERT_EQ(bb_tally_reset(TALLY_FILE_PREFIX "three"), 0);
+	BBUNIT_ASSERT_EQ(bb_tally_reset(TALLY_FILE_PREFIX "three"), 0);
+
+	BBUNIT_ENDTEST;
+
+	remove(TALLY_FILE_PREFIX "one");
+	remove(TALLY_FILE_PREFIX "two");
+	remove(TALLY_FILE_PREFIX "three");
+}
+
+BBUNIT_DEFINE_TEST(test_nonexisting_file)
+{
+	remove(TALLY_FILE_PREFIX "non-existing-file");
+
+	BBUNIT_ASSERT_EQ(bb_tally_reset(TALLY_FILE_PREFIX "non-existing-file"), 0);
+	BBUNIT_ASSERT_EQ(remove(TALLY_FILE_PREFIX "non-existing-file"), -1);
+
+	BBUNIT_ASSERT_EQ(bb_tally_add(TALLY_FILE_PREFIX "non-existing-file"), 1);
+	BBUNIT_ASSERT_EQ(remove(TALLY_FILE_PREFIX "non-existing-file"), 0);
+
+	BBUNIT_ENDTEST;
+}
+
+#endif
-- 
2.31.1



More information about the busybox mailing list