199ca880aSopenharmony_ci/***
299ca880aSopenharmony_ci  This file is part of eudev, forked from systemd.
399ca880aSopenharmony_ci
499ca880aSopenharmony_ci  Copyright 2010 Lennart Poettering
599ca880aSopenharmony_ci
699ca880aSopenharmony_ci  systemd is free software; you can redistribute it and/or modify it
799ca880aSopenharmony_ci  under the terms of the GNU Lesser General Public License as published by
899ca880aSopenharmony_ci  the Free Software Foundation; either version 2.1 of the License, or
999ca880aSopenharmony_ci  (at your option) any later version.
1099ca880aSopenharmony_ci
1199ca880aSopenharmony_ci  systemd is distributed in the hope that it will be useful, but
1299ca880aSopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1399ca880aSopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1499ca880aSopenharmony_ci  Lesser General Public License for more details.
1599ca880aSopenharmony_ci
1699ca880aSopenharmony_ci  You should have received a copy of the GNU Lesser General Public License
1799ca880aSopenharmony_ci  along with systemd; If not, see <http://www.gnu.org/licenses/>.
1899ca880aSopenharmony_ci***/
1999ca880aSopenharmony_ci
2099ca880aSopenharmony_ci#include <unistd.h>
2199ca880aSopenharmony_ci#include <sys/sendfile.h>
2299ca880aSopenharmony_ci#include "fileio.h"
2399ca880aSopenharmony_ci#include "util.h"
2499ca880aSopenharmony_ci#include "strv.h"
2599ca880aSopenharmony_ci#include "utf8.h"
2699ca880aSopenharmony_ci#include "ctype.h"
2799ca880aSopenharmony_ci
2899ca880aSopenharmony_ciint write_string_stream(FILE *f, const char *line) {
2999ca880aSopenharmony_ci        assert(f);
3099ca880aSopenharmony_ci        assert(line);
3199ca880aSopenharmony_ci
3299ca880aSopenharmony_ci        errno = 0;
3399ca880aSopenharmony_ci
3499ca880aSopenharmony_ci        fputs(line, f);
3599ca880aSopenharmony_ci        if (!endswith(line, "\n"))
3699ca880aSopenharmony_ci                fputc('\n', f);
3799ca880aSopenharmony_ci
3899ca880aSopenharmony_ci        fflush(f);
3999ca880aSopenharmony_ci
4099ca880aSopenharmony_ci        if (ferror(f))
4199ca880aSopenharmony_ci                return errno ? -errno : -EIO;
4299ca880aSopenharmony_ci
4399ca880aSopenharmony_ci        return 0;
4499ca880aSopenharmony_ci}
4599ca880aSopenharmony_ci
4699ca880aSopenharmony_ciint write_string_file(const char *fn, const char *line) {
4799ca880aSopenharmony_ci        _cleanup_fclose_ FILE *f = NULL;
4899ca880aSopenharmony_ci
4999ca880aSopenharmony_ci        assert(fn);
5099ca880aSopenharmony_ci        assert(line);
5199ca880aSopenharmony_ci
5299ca880aSopenharmony_ci        f = fopen(fn, "we");
5399ca880aSopenharmony_ci        if (!f)
5499ca880aSopenharmony_ci                return -errno;
5599ca880aSopenharmony_ci
5699ca880aSopenharmony_ci        return write_string_stream(f, line);
5799ca880aSopenharmony_ci}
5899ca880aSopenharmony_ciint read_one_line_file(const char *fn, char **line) {
5999ca880aSopenharmony_ci        _cleanup_fclose_ FILE *f = NULL;
6099ca880aSopenharmony_ci        char t[LINE_MAX], *c;
6199ca880aSopenharmony_ci
6299ca880aSopenharmony_ci        assert(fn);
6399ca880aSopenharmony_ci        assert(line);
6499ca880aSopenharmony_ci
6599ca880aSopenharmony_ci        f = fopen(fn, "re");
6699ca880aSopenharmony_ci        if (!f)
6799ca880aSopenharmony_ci                return -errno;
6899ca880aSopenharmony_ci
6999ca880aSopenharmony_ci        if (!fgets(t, sizeof(t), f)) {
7099ca880aSopenharmony_ci
7199ca880aSopenharmony_ci                if (ferror(f))
7299ca880aSopenharmony_ci                        return errno ? -errno : -EIO;
7399ca880aSopenharmony_ci
7499ca880aSopenharmony_ci                t[0] = 0;
7599ca880aSopenharmony_ci        }
7699ca880aSopenharmony_ci
7799ca880aSopenharmony_ci        c = strdup(t);
7899ca880aSopenharmony_ci        if (!c)
7999ca880aSopenharmony_ci                return -ENOMEM;
8099ca880aSopenharmony_ci        truncate_nl(c);
8199ca880aSopenharmony_ci
8299ca880aSopenharmony_ci        *line = c;
8399ca880aSopenharmony_ci        return 0;
8499ca880aSopenharmony_ci}
8599ca880aSopenharmony_ci
8699ca880aSopenharmony_ciint read_full_stream(FILE *f, char **contents, size_t *size) {
8799ca880aSopenharmony_ci        size_t n, l;
8899ca880aSopenharmony_ci        _cleanup_free_ char *buf = NULL;
8999ca880aSopenharmony_ci        struct stat st;
9099ca880aSopenharmony_ci
9199ca880aSopenharmony_ci        assert(f);
9299ca880aSopenharmony_ci        assert(contents);
9399ca880aSopenharmony_ci
9499ca880aSopenharmony_ci        if (fstat(fileno(f), &st) < 0)
9599ca880aSopenharmony_ci                return -errno;
9699ca880aSopenharmony_ci
9799ca880aSopenharmony_ci        n = LINE_MAX;
9899ca880aSopenharmony_ci
9999ca880aSopenharmony_ci        if (S_ISREG(st.st_mode)) {
10099ca880aSopenharmony_ci
10199ca880aSopenharmony_ci                /* Safety check */
10299ca880aSopenharmony_ci                if (st.st_size > 4*1024*1024)
10399ca880aSopenharmony_ci                        return -E2BIG;
10499ca880aSopenharmony_ci
10599ca880aSopenharmony_ci                /* Start with the right file size, but be prepared for
10699ca880aSopenharmony_ci                 * files from /proc which generally report a file size
10799ca880aSopenharmony_ci                 * of 0 */
10899ca880aSopenharmony_ci                if (st.st_size > 0)
10999ca880aSopenharmony_ci                        n = st.st_size;
11099ca880aSopenharmony_ci        }
11199ca880aSopenharmony_ci
11299ca880aSopenharmony_ci        l = 0;
11399ca880aSopenharmony_ci        for (;;) {
11499ca880aSopenharmony_ci                char *t;
11599ca880aSopenharmony_ci                size_t k;
11699ca880aSopenharmony_ci
11799ca880aSopenharmony_ci                t = realloc(buf, n+1);
11899ca880aSopenharmony_ci                if (!t)
11999ca880aSopenharmony_ci                        return -ENOMEM;
12099ca880aSopenharmony_ci
12199ca880aSopenharmony_ci                buf = t;
12299ca880aSopenharmony_ci                k = fread(buf + l, 1, n - l, f);
12399ca880aSopenharmony_ci
12499ca880aSopenharmony_ci                if (k <= 0) {
12599ca880aSopenharmony_ci                        if (ferror(f))
12699ca880aSopenharmony_ci                                return -errno;
12799ca880aSopenharmony_ci
12899ca880aSopenharmony_ci                        break;
12999ca880aSopenharmony_ci                }
13099ca880aSopenharmony_ci
13199ca880aSopenharmony_ci                l += k;
13299ca880aSopenharmony_ci                n *= 2;
13399ca880aSopenharmony_ci
13499ca880aSopenharmony_ci                /* Safety check */
13599ca880aSopenharmony_ci                if (n > 4*1024*1024)
13699ca880aSopenharmony_ci                        return -E2BIG;
13799ca880aSopenharmony_ci        }
13899ca880aSopenharmony_ci
13999ca880aSopenharmony_ci        buf[l] = 0;
14099ca880aSopenharmony_ci        *contents = buf;
14199ca880aSopenharmony_ci        buf = NULL; /* do not free */
14299ca880aSopenharmony_ci
14399ca880aSopenharmony_ci        if (size)
14499ca880aSopenharmony_ci                *size = l;
14599ca880aSopenharmony_ci
14699ca880aSopenharmony_ci        return 0;
14799ca880aSopenharmony_ci}
14899ca880aSopenharmony_ci
14999ca880aSopenharmony_ciint read_full_file(const char *fn, char **contents, size_t *size) {
15099ca880aSopenharmony_ci        _cleanup_fclose_ FILE *f = NULL;
15199ca880aSopenharmony_ci
15299ca880aSopenharmony_ci        assert(fn);
15399ca880aSopenharmony_ci        assert(contents);
15499ca880aSopenharmony_ci
15599ca880aSopenharmony_ci        f = fopen(fn, "re");
15699ca880aSopenharmony_ci        if (!f)
15799ca880aSopenharmony_ci                return -errno;
15899ca880aSopenharmony_ci
15999ca880aSopenharmony_ci        return read_full_stream(f, contents, size);
16099ca880aSopenharmony_ci}
161