diff --git a/src/librc/librc-misc.c b/src/librc/librc-misc.c index 7244deef..97fa54c8 100644 --- a/src/librc/librc-misc.c +++ b/src/librc/librc-misc.c @@ -54,6 +54,54 @@ rc_yesno(const char *value) } librc_hidden_def(rc_yesno) + +/** + * Read the entire @file into the buffer and set @len to the + * size of the buffer when finished. For C strings, this will + * be strlen(buffer) + 1. + * Don't forget to free the buffer afterwards! + */ +bool +rc_getfile(const char *file, char **buffer, size_t *len) +{ + bool ret = false; + FILE *fp; + int fd; + struct stat st; + size_t done, left; + + fp = fopen(file, "re"); + if (!fp) + return false; + + /* assume fileno() never fails */ + fd = fileno(fp); + + if (fstat(fd, &st)) + goto finished; + + left = st.st_size; + *len = left + 1; /* NUL terminator */ + *buffer = xrealloc(*buffer, *len); + while (left) { + done = fread(*buffer, sizeof(*buffer[0]), left, fp); + if (done == 0 && ferror(fp)) + goto finished; + left -= done; + } + ret = true; + + finished: + if (!ret) { + free(*buffer); + *len = 0; + } else + (*buffer)[*len - 1] = '\0'; + fclose(fp); + return ret; +} +librc_hidden_def(rc_getfile) + ssize_t rc_getline(char **line, size_t *len, FILE *fp) { diff --git a/src/librc/librc.h b/src/librc/librc.h index 43b01570..876c0472 100644 --- a/src/librc/librc.h +++ b/src/librc/librc.h @@ -84,6 +84,7 @@ librc_hidden_proto(rc_deptree_order) librc_hidden_proto(rc_deptree_update) librc_hidden_proto(rc_deptree_update_needed) librc_hidden_proto(rc_find_pids) +librc_hidden_proto(rc_getfile) librc_hidden_proto(rc_getline) librc_hidden_proto(rc_newer_than) librc_hidden_proto(rc_older_than) diff --git a/src/librc/rc.h.in b/src/librc/rc.h.in index 2a7c054a..350f518e 100644 --- a/src/librc/rc.h.in +++ b/src/librc/rc.h.in @@ -544,6 +544,9 @@ typedef LIST_HEAD(rc_pidlist, rc_pid) RC_PIDLIST; * @return NULL terminated list of pids */ RC_PIDLIST *rc_find_pids(const char *, const char *const *, uid_t, pid_t); +/* Basically the same as rc_getline() below, it just returns multiple lines */ +bool rc_getfile(const char *, char **, size_t *); + /* getline is a handy glibc function that not all libcs have, so * we have our own */ ssize_t rc_getline(char **, size_t *, FILE *); diff --git a/src/librc/rc.map b/src/librc/rc.map index c5f10ade..0f45cdfe 100644 --- a/src/librc/rc.map +++ b/src/librc/rc.map @@ -14,6 +14,7 @@ global: rc_deptree_update_needed; rc_environ_fd; rc_find_pids; + rc_getfile; rc_getline; rc_newer_than; rc_older_than; diff --git a/src/test/rc.funcs.list b/src/test/rc.funcs.list index a8b011ff..f0416b7d 100644 --- a/src/test/rc.funcs.list +++ b/src/test/rc.funcs.list @@ -24,6 +24,8 @@ rc_deptree_update_needed rc_deptree_update_needed@@RC_1.0 rc_find_pids rc_find_pids@@RC_1.0 +rc_getfile +rc_getfile@@RC_1.0 rc_getline rc_getline@@RC_1.0 rc_newer_than