summaryrefslogtreecommitdiff
path: root/src/shared/fileio.c
diff options
context:
space:
mode:
authorShawn Landden <shawn@churchofgit.com>2013-11-30 16:09:26 -0800
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2013-11-30 22:20:20 -0500
commite93c33d4aadb41427f215d43545e7fadc6bcec6f (patch)
tree6964e793e232cce6d03349d73a83fe23da45e252 /src/shared/fileio.c
parentf74294c1dabb41faaaa0e03777f0dd33b979eed6 (diff)
systemctl: add "systemctl cat"
Diffstat (limited to 'src/shared/fileio.c')
-rw-r--r--src/shared/fileio.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 733b320388..ac1b409a1c 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -20,6 +20,7 @@
***/
#include <unistd.h>
+#include <sys/sendfile.h>
#include "fileio.h"
#include "util.h"
#include "strv.h"
@@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) {
return 0;
}
+ssize_t sendfile_full(int out_fd, const char *fn) {
+ _cleanup_fclose_ FILE *f;
+ struct stat st;
+ int r;
+ ssize_t s;
+
+ size_t n, l;
+ _cleanup_free_ char *buf = NULL;
+
+ assert(out_fd > 0);
+ assert(fn);
+
+ f = fopen(fn, "r");
+ if (!f)
+ return -errno;
+
+ r = fstat(fileno(f), &st);
+ if (r < 0)
+ return -errno;
+
+ s = sendfile(out_fd, fileno(f), NULL, st.st_size);
+ if (s < 0)
+ if (errno == EINVAL || errno == ENOSYS) {
+ /* continue below */
+ } else
+ return -errno;
+ else
+ return s;
+
+ /* sendfile() failed, fall back to read/write */
+
+ /* Safety check */
+ if (st.st_size > 4*1024*1024)
+ return -E2BIG;
+
+ n = st.st_size > 0 ? st.st_size : LINE_MAX;
+ l = 0;
+
+ while (true) {
+ char *t;
+ size_t k;
+
+ t = realloc(buf, n);
+ if (!t)
+ return -ENOMEM;
+
+ buf = t;
+ k = fread(buf + l, 1, n - l, f);
+
+ if (k <= 0) {
+ if (ferror(f))
+ return -errno;
+
+ break;
+ }
+
+ l += k;
+ n *= 2;
+
+ /* Safety check */
+ if (n > 4*1024*1024)
+ return -E2BIG;
+ }
+
+ r = write(out_fd, buf, l);
+ if (r < 0)
+ return -errno;
+
+ return (ssize_t) l;
+}
+
int read_full_file(const char *fn, char **contents, size_t *size) {
_cleanup_fclose_ FILE *f = NULL;
size_t n, l;
@@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
buf[l] = 0;
*contents = buf;
- buf = NULL;
if (size)
*size = l;