diff --git a/mx_util.c b/mx_util.c index 199bcd5c..612e9fee 100644 --- a/mx_util.c +++ b/mx_util.c @@ -752,6 +752,34 @@ int mx_open_newfile(char *fname) return fh; } +int mx_read_first_line_from_file(char *fname, char **line) +{ + _mx_cleanup_fclose_ FILE *fp; + char *buf = NULL; + size_t n = 0; + ssize_t res; + + fp = fopen(fname, "r"); + if (!fp) + return -errno; + + res = getline(&buf, &n, fp); + if (res == -1) + return -errno; + + *line = buf; + + if (!res) + return res; + + res--; + + if (buf[res] == '\n') + buf[res] = 0; + + return res; +} + int mx_sleep(unsigned int seconds) { if (seconds) diff --git a/mx_util.h b/mx_util.h index d805aef3..7cd10d01 100644 --- a/mx_util.h +++ b/mx_util.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "mx_log.h" @@ -46,9 +47,17 @@ static inline void __mx_free(void *ptr) { free(*(void **)ptr); } +static inline void __mx_fclose(FILE **ptr) { + if (*ptr) + fclose(*ptr); +} + #undef _mx_cleanup_free_ #define _mx_cleanup_free_ _mx_cleanup_(__mx_free) +#undef _mx_cleanup_fclose_ +#define _mx_cleanup_fclose_ _mx_cleanup_(__mx_fclose) + #undef likely #define likely(x) __builtin_expect((x),1) @@ -106,6 +115,8 @@ int mx_setenvf_forever(const char *name, char *fmt, ...) __attribute__ ((format( int mx_open_newfile(char *fname); +int mx_read_first_line_from_file(char *fname, char **line); + int mx_sleep(unsigned int seconds); int mx_sleep_nofail(unsigned int seconds); diff --git a/test_mx_util.c b/test_mx_util.c index 66dd7766..6e956f3f 100644 --- a/test_mx_util.c +++ b/test_mx_util.c @@ -44,6 +44,7 @@ static void test_mx_strtoul(void) assert(mx_strtoul("-1", &l) == -ERANGE); assert(mx_strtoul(" -1", &l) == -ERANGE); + assert(mx_strtoul("123 123", &l) == -EINVAL); assert(mx_strtoul("123s", &l) == -EINVAL); assert(mx_strtoul("0888", &l) == -EINVAL); assert(mx_strtoul("1.2", &l) == -EINVAL); @@ -271,6 +272,26 @@ static void test_mx_strtobytes(void) assert(mx_strtobytes("test", &l) == -EINVAL); } +static void test_mx_read_first_line_from_file(void) +{ + char *str; + + assert(mx_read_first_line_from_file("/proc/sys/kernel/random/boot_id", &str) == 36); + assert(str); + mx_free_null(str); + + assert(mx_read_first_line_from_file("/proc/sys/kernel/random/uuid", &str) == 36); + assert(str); + mx_free_null(str); + + assert(mx_read_first_line_from_file("/proc/no_such_file", &str) == -ENOENT); + assert(str == NULL); + + assert(mx_read_first_line_from_file("/proc/self/stat", &str) > 0); + assert(str); + mx_free_null(str); +} + int main(int argc, char *argv[]) { test_mx_strskipwhitespaces(); @@ -284,5 +305,6 @@ int main(int argc, char *argv[]) test_mx_strtoseconds(); test_mx_strtominutes(); test_mx_strtobytes(); + test_mx_read_first_line_from_file(); return 0; }