1 #include <alloca.h>
2 #include <errno.h>
3 #include <stdbool.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #if CPUINFO_MOCK
14 #include <cpuinfo-mock.h>
15 #endif
16 #include <cpuinfo/log.h>
17 #include <linux/api.h>
18
cpuinfo_linux_parse_small_file(const char * filename,size_t buffer_size,cpuinfo_smallfile_callback callback,void * context)19 bool cpuinfo_linux_parse_small_file(
20 const char* filename,
21 size_t buffer_size,
22 cpuinfo_smallfile_callback callback,
23 void* context) {
24 int file = -1;
25 bool status = false;
26 char* buffer = (char*)alloca(buffer_size);
27
28 #if CPUINFO_LOG_DEBUG_PARSERS
29 cpuinfo_log_debug("parsing small file %s", filename);
30 #endif
31
32 #if CPUINFO_MOCK
33 file = cpuinfo_mock_open(filename, O_RDONLY);
34 #else
35 file = open(filename, O_RDONLY);
36 #endif
37 if (file == -1) {
38 cpuinfo_log_info("failed to open %s: %s", filename, strerror(errno));
39 goto cleanup;
40 }
41
42 size_t buffer_position = 0;
43 ssize_t bytes_read;
44 do {
45 #if CPUINFO_MOCK
46 bytes_read = cpuinfo_mock_read(file, &buffer[buffer_position], buffer_size - buffer_position);
47 #else
48 bytes_read = read(file, &buffer[buffer_position], buffer_size - buffer_position);
49 #endif
50 if (bytes_read < 0) {
51 cpuinfo_log_info(
52 "failed to read file %s at position %zu: %s",
53 filename,
54 buffer_position,
55 strerror(errno));
56 goto cleanup;
57 }
58 buffer_position += (size_t)bytes_read;
59 if (buffer_position >= buffer_size) {
60 cpuinfo_log_error(
61 "failed to read file %s: insufficient buffer of size %zu", filename, buffer_size);
62 goto cleanup;
63 }
64 } while (bytes_read != 0);
65
66 status = callback(filename, buffer, &buffer[buffer_position], context);
67
68 cleanup:
69 if (file != -1) {
70 #if CPUINFO_MOCK
71 cpuinfo_mock_close(file);
72 #else
73 close(file);
74 #endif
75 file = -1;
76 }
77 return status;
78 }
79