/* Utilities functions to read/parse Linux procfs and sysfs. Copyright (C) 2023-2024 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #include #include #include #include static int next_line (char **r, int fd, char *const buffer, char **cp, char **re, char *const buffer_end) { char *res = *cp; char *nl = memchr (*cp, '\n', *re - *cp); if (nl == NULL) { if (*cp != buffer) { if (*re == buffer_end) { memmove (buffer, *cp, *re - *cp); *re = buffer + (*re - *cp); *cp = buffer; ssize_t n = TEMP_FAILURE_RETRY ( __read_nocancel (fd, *re, buffer_end - *re)); if (n < 0) return -1; *re += n; nl = memchr (*cp, '\n', *re - *cp); if (nl == NULL) /* Line too long. */ return 0; } else nl = memchr (*cp, '\n', *re - *cp); res = *cp; } if (nl == NULL) nl = *re - 1; } *nl = '\0'; *cp = nl + 1; assert (*cp <= *re); if (res == *re) return 0; *r = res; return 1; } bool procutils_read_file (const char *filename, procutils_closure_t closure, void *arg) { enum { buffer_size = PROCUTILS_MAX_LINE_LEN }; char buffer[buffer_size]; char *buffer_end = buffer + buffer_size; char *cp = buffer_end; char *re = buffer_end; int fd = TEMP_FAILURE_RETRY ( __open64_nocancel (filename, O_RDONLY | O_CLOEXEC)); if (fd == -1) return false; char *l; int r; while ((r = next_line (&l, fd, buffer, &cp, &re, buffer_end)) > 0) if (closure (l, arg) != 0) break; __close_nocancel_nostatus (fd); return r == 1; }