xref: /spdk/lib/util/file.c (revision 084afa9042243611b8306ec07896aea70e47d609)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2015 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/file.h"
7 #include "spdk/string.h"
8 
9 void *
10 spdk_posix_file_load(FILE *file, size_t *size)
11 {
12 	uint8_t *newbuf, *buf = NULL;
13 	size_t rc, buf_size, cur_size = 0;
14 
15 	*size = 0;
16 	buf_size = 128 * 1024;
17 
18 	while (buf_size <= 1024 * 1024 * 1024) {
19 		newbuf = realloc(buf, buf_size);
20 		if (newbuf == NULL) {
21 			free(buf);
22 			return NULL;
23 		}
24 		buf = newbuf;
25 
26 		rc = fread(buf + cur_size, 1, buf_size - cur_size, file);
27 		cur_size += rc;
28 
29 		if (feof(file)) {
30 			*size = cur_size;
31 			return buf;
32 		}
33 
34 		if (ferror(file)) {
35 			free(buf);
36 			return NULL;
37 		}
38 
39 		buf_size *= 2;
40 	}
41 
42 	free(buf);
43 	return NULL;
44 }
45 
46 void *
47 spdk_posix_file_load_from_name(const char *file_name, size_t *size)
48 {
49 	FILE *file = fopen(file_name, "r");
50 	void *data;
51 
52 	if (file == NULL) {
53 		return NULL;
54 	}
55 
56 	data = spdk_posix_file_load(file, size);
57 	fclose(file);
58 
59 	return data;
60 }
61 
62 static int
63 read_sysfs_attribute(char **attribute_p, const char *format, va_list args)
64 {
65 	char *attribute;
66 	FILE *file;
67 	char *path;
68 	size_t len = 0;
69 	ssize_t read;
70 	int errsv;
71 
72 	path = spdk_vsprintf_alloc(format, args);
73 	if (path == NULL) {
74 		return -ENOMEM;
75 	}
76 
77 	file = fopen(path, "r");
78 	errsv = errno;
79 	free(path);
80 	if (file == NULL) {
81 		assert(errsv != 0);
82 		return -errsv;
83 	}
84 
85 	*attribute_p = NULL;
86 	read = getline(attribute_p, &len, file);
87 	errsv = errno;
88 	fclose(file);
89 	attribute = *attribute_p;
90 	if (read == -1) {
91 		/* getline man page says line should be freed even on failure. */
92 		free(attribute);
93 		assert(errsv != 0);
94 		return -errsv;
95 	}
96 
97 	/* len is the length of the allocated buffer, which may be more than
98 	 * the string's length. Reuse len to hold the actual strlen.
99 	 */
100 	len = strlen(attribute);
101 	if (attribute[len - 1] == '\n') {
102 		attribute[len - 1] = '\0';
103 	}
104 
105 	return 0;
106 }
107 
108 int
109 spdk_read_sysfs_attribute(char **attribute_p, const char *path_format, ...)
110 {
111 	va_list args;
112 	int rc;
113 
114 	va_start(args, path_format);
115 	rc = read_sysfs_attribute(attribute_p, path_format, args);
116 	va_end(args);
117 
118 	return rc;
119 }
120 
121 int
122 spdk_read_sysfs_attribute_uint32(uint32_t *attribute, const char *path_format, ...)
123 {
124 	char *attribute_str = NULL;
125 	long long int val;
126 	va_list args;
127 	int rc;
128 
129 	va_start(args, path_format);
130 	rc = read_sysfs_attribute(&attribute_str, path_format, args);
131 	va_end(args);
132 
133 	if (rc != 0) {
134 		return rc;
135 	}
136 
137 	val = spdk_strtoll(attribute_str, 0);
138 	free(attribute_str);
139 	if (val < 0 || val > UINT32_MAX) {
140 		return -EINVAL;
141 	}
142 
143 	*attribute = (uint32_t)val;
144 	return 0;
145 }
146