]>
Commit | Line | Data |
---|---|---|
e7190fc7 | 1 | /* Utilities functions to read/parse Linux procfs and sysfs. |
dff8da6b | 2 | Copyright (C) 2023-2024 Free Software Foundation, Inc. |
e7190fc7 AZN |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <https://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include <assert.h> | |
20 | #include <not-cancel.h> | |
21 | #include <procutils.h> | |
22 | #include <string.h> | |
23 | ||
24 | static int | |
25 | next_line (char **r, int fd, char *const buffer, char **cp, char **re, | |
26 | char *const buffer_end) | |
27 | { | |
28 | char *res = *cp; | |
29 | char *nl = memchr (*cp, '\n', *re - *cp); | |
30 | if (nl == NULL) | |
31 | { | |
32 | if (*cp != buffer) | |
33 | { | |
34 | if (*re == buffer_end) | |
35 | { | |
36 | memmove (buffer, *cp, *re - *cp); | |
37 | *re = buffer + (*re - *cp); | |
38 | *cp = buffer; | |
39 | ||
40 | ssize_t n = TEMP_FAILURE_RETRY ( | |
41 | __read_nocancel (fd, *re, buffer_end - *re)); | |
42 | if (n < 0) | |
43 | return -1; | |
44 | ||
45 | *re += n; | |
46 | ||
47 | nl = memchr (*cp, '\n', *re - *cp); | |
48 | if (nl == NULL) | |
49 | /* Line too long. */ | |
50 | return 0; | |
51 | } | |
52 | else | |
53 | nl = memchr (*cp, '\n', *re - *cp); | |
54 | ||
55 | res = *cp; | |
56 | } | |
57 | ||
58 | if (nl == NULL) | |
59 | nl = *re - 1; | |
60 | } | |
61 | ||
62 | *nl = '\0'; | |
63 | *cp = nl + 1; | |
64 | assert (*cp <= *re); | |
65 | ||
66 | if (res == *re) | |
67 | return 0; | |
68 | ||
69 | *r = res; | |
70 | return 1; | |
71 | } | |
72 | ||
73 | bool | |
74 | procutils_read_file (const char *filename, procutils_closure_t closure, | |
75 | void *arg) | |
76 | { | |
77 | enum { buffer_size = PROCUTILS_MAX_LINE_LEN }; | |
78 | char buffer[buffer_size]; | |
79 | char *buffer_end = buffer + buffer_size; | |
80 | char *cp = buffer_end; | |
81 | char *re = buffer_end; | |
82 | ||
83 | int fd = TEMP_FAILURE_RETRY ( | |
84 | __open64_nocancel (filename, O_RDONLY | O_CLOEXEC)); | |
85 | if (fd == -1) | |
86 | return false; | |
87 | ||
88 | char *l; | |
89 | int r; | |
90 | while ((r = next_line (&l, fd, buffer, &cp, &re, buffer_end)) > 0) | |
91 | if (closure (l, arg) != 0) | |
92 | break; | |
93 | ||
94 | __close_nocancel_nostatus (fd); | |
95 | ||
96 | return r == 1; | |
97 | } |