1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
/*
* Copyright 2005-2019 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
*
* Copyright 2005-2010 Ned Ludd - <solar@gentoo.org>
* Copyright 2005-2014 Mike Frysinger - <vapier@gentoo.org>
*/
#include "main.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "xalloc.h"
#include "eat_file.h"
bool
eat_file_fd(int fd, char **bufptr, size_t *bufsize)
{
bool ret = true;
struct stat s;
char *buf;
size_t read_size;
/* First figure out how much data we should read from the fd. */
if (fd == -1 || fstat(fd, &s) != 0) {
ret = false;
read_size = 0;
/* Fall through so we set the first byte 0 */
} else if (!s.st_size) {
/* We might be trying to eat a virtual file like in /proc, so
* read an arbitrary size that should be "enough". */
read_size = BUFSIZE;
} else
read_size = (size_t)s.st_size;
/* Now allocate enough space (at least 1 byte). */
if (!*bufptr || *bufsize < read_size) {
/* We assume a min allocation size so that repeat calls don't
* hit ugly ramp ups -- if you read a file that is 1 byte, then
* 5 bytes, then 10 bytes, then 20 bytes, ... you'll allocate
* constantly. So we round up a few pages as wasting virtual
* memory is cheap when it is unused. */
*bufsize = ((read_size + 1) + BUFSIZE - 1) & -BUFSIZE;
*bufptr = xrealloc(*bufptr, *bufsize);
}
buf = *bufptr;
/* Finally do the actual read. */
buf[0] = '\0';
if (read_size) {
if (s.st_size) {
if (read(fd, buf, read_size) != (ssize_t)read_size)
return false;
buf[read_size] = '\0';
} else {
if ((read_size = read(fd, buf, read_size)) <= 0)
return false;
buf[read_size] = '\0';
}
}
return ret;
}
bool
eat_file_at(int dfd, const char *file, char **bufptr, size_t *bufsize)
{
bool ret;
int fd;
fd = openat(dfd, file, O_CLOEXEC|O_RDONLY);
ret = eat_file_fd(fd, bufptr, bufsize);
if (fd != -1)
close(fd);
return ret;
}
bool
eat_file(const char *file, char **bufptr, size_t *bufsize)
{
return eat_file_at(AT_FDCWD, file, bufptr, bufsize);
}
|