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