2 * @brief load a file into a std::string.
4 /* Copyright (C) 2006,2010,2012,2015,2018 Olly Betts
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "safefcntl.h"
30 #include <sys/types.h>
31 #include "safesysstat.h"
32 #include "safeunistd.h"
37 load_file_from_fd(int fd
, string
& output
)
42 ssize_t c
= read(fd
, blk
, sizeof(blk
));
45 if (errno
== EINTR
) continue;
48 output
.append(blk
, c
);
55 load_file(const string
& file_name
, size_t max_to_read
, int flags
,
56 string
& output
, bool* truncated
)
58 mode_t mode
= O_BINARY
| O_RDONLY
;
59 #if defined O_NOATIME && O_NOATIME != 0
60 if (flags
& NOATIME
) mode
|= O_NOATIME
;
63 int fd
= open(file_name
.c_str(), mode
);
64 #if defined O_NOATIME && O_NOATIME != 0
65 if (fd
< 0 && (mode
& O_NOATIME
)) {
67 fd
= open(file_name
.c_str(), mode
);
70 if (fd
< 0) return false;
72 #ifdef HAVE_POSIX_FADVISE
74 // On Linux, POSIX_FADV_NOREUSE has been a no-op since 2.6.18 (released
75 // 2006) and before that it was incorrectly implemented as an alias for
76 // POSIX_FADV_WILLNEED. There have been a few attempts to make
77 // POSIX_FADV_NOREUSE actually work on Linux but nothing has been merged so
78 // for now let's not waste effort making a syscall we know to currently be
79 // a no-op. We can revise this conditional if it gets usefully
82 posix_fadvise(fd
, 0, 0, POSIX_FADV_NOREUSE
);
87 if (fstat(fd
, &st
) < 0) {
88 int errno_save
= errno
;
94 if (!S_ISREG(st
.st_mode
)) {
100 size_t n
= st
.st_size
;
101 if (max_to_read
&& max_to_read
< n
) {
103 if (truncated
) *truncated
= true;
105 if (truncated
) *truncated
= false;
112 int c
= read(fd
, blk
, min(n
, sizeof(blk
)));
115 if (errno
== EINTR
) continue;
118 output
.append(blk
, c
);
122 if (flags
& NOCACHE
) {
123 #ifdef HAVE_POSIX_FADVISE
125 // Linux doesn't implement POSIX_FADV_NOREUSE so instead we use
126 // POSIX_FADV_DONTNEED just before closing the fd. This is a bit more
127 // aggressive than we ideally want - really we just want to stop our
128 // reads from pushing other pages out of the OS cache, but if the
129 // pages we read are already cached it would probably be better to
130 // leave them cached after the read.
131 posix_fadvise(fd
, 0, 0, POSIX_FADV_DONTNEED
);