From: Hemmo Nieminen <[email protected]>

Signed-off-by: Hemmo Nieminen <[email protected]>
---
 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

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to