xref: /spdk/lib/util/file.c (revision 084afa9042243611b8306ec07896aea70e47d609)
1488570ebSJim Harris /*   SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse  *   Copyright (C) 2015 Intel Corporation.
3ad8bd8e3SChangpeng Liu  *   All rights reserved.
4ad8bd8e3SChangpeng Liu  */
5ad8bd8e3SChangpeng Liu 
6ad8bd8e3SChangpeng Liu #include "spdk/file.h"
74897a330SJim Harris #include "spdk/string.h"
8ad8bd8e3SChangpeng Liu 
9ad8bd8e3SChangpeng Liu void *
10ad8bd8e3SChangpeng Liu spdk_posix_file_load(FILE *file, size_t *size)
11ad8bd8e3SChangpeng Liu {
12075d422fSKonrad Sztyber 	uint8_t *newbuf, *buf = NULL;
13ad8bd8e3SChangpeng Liu 	size_t rc, buf_size, cur_size = 0;
14ad8bd8e3SChangpeng Liu 
15ad8bd8e3SChangpeng Liu 	*size = 0;
16ad8bd8e3SChangpeng Liu 	buf_size = 128 * 1024;
17ad8bd8e3SChangpeng Liu 
18ad8bd8e3SChangpeng Liu 	while (buf_size <= 1024 * 1024 * 1024) {
19ad8bd8e3SChangpeng Liu 		newbuf = realloc(buf, buf_size);
20ad8bd8e3SChangpeng Liu 		if (newbuf == NULL) {
21ad8bd8e3SChangpeng Liu 			free(buf);
22ad8bd8e3SChangpeng Liu 			return NULL;
23ad8bd8e3SChangpeng Liu 		}
24ad8bd8e3SChangpeng Liu 		buf = newbuf;
25ad8bd8e3SChangpeng Liu 
26ad8bd8e3SChangpeng Liu 		rc = fread(buf + cur_size, 1, buf_size - cur_size, file);
27ad8bd8e3SChangpeng Liu 		cur_size += rc;
28ad8bd8e3SChangpeng Liu 
29ad8bd8e3SChangpeng Liu 		if (feof(file)) {
30ad8bd8e3SChangpeng Liu 			*size = cur_size;
31ad8bd8e3SChangpeng Liu 			return buf;
32ad8bd8e3SChangpeng Liu 		}
33ad8bd8e3SChangpeng Liu 
34ad8bd8e3SChangpeng Liu 		if (ferror(file)) {
35ad8bd8e3SChangpeng Liu 			free(buf);
36ad8bd8e3SChangpeng Liu 			return NULL;
37ad8bd8e3SChangpeng Liu 		}
38ad8bd8e3SChangpeng Liu 
39ad8bd8e3SChangpeng Liu 		buf_size *= 2;
40ad8bd8e3SChangpeng Liu 	}
41ad8bd8e3SChangpeng Liu 
42ad8bd8e3SChangpeng Liu 	free(buf);
43ad8bd8e3SChangpeng Liu 	return NULL;
44ad8bd8e3SChangpeng Liu }
452284b56bSKrzysztof Karas 
462284b56bSKrzysztof Karas void *
472284b56bSKrzysztof Karas spdk_posix_file_load_from_name(const char *file_name, size_t *size)
482284b56bSKrzysztof Karas {
492284b56bSKrzysztof Karas 	FILE *file = fopen(file_name, "r");
502284b56bSKrzysztof Karas 	void *data;
512284b56bSKrzysztof Karas 
522284b56bSKrzysztof Karas 	if (file == NULL) {
532284b56bSKrzysztof Karas 		return NULL;
542284b56bSKrzysztof Karas 	}
552284b56bSKrzysztof Karas 
562284b56bSKrzysztof Karas 	data = spdk_posix_file_load(file, size);
572284b56bSKrzysztof Karas 	fclose(file);
582284b56bSKrzysztof Karas 
592284b56bSKrzysztof Karas 	return data;
602284b56bSKrzysztof Karas }
614897a330SJim Harris 
624897a330SJim Harris static int
634897a330SJim Harris read_sysfs_attribute(char **attribute_p, const char *format, va_list args)
644897a330SJim Harris {
654897a330SJim Harris 	char *attribute;
664897a330SJim Harris 	FILE *file;
674897a330SJim Harris 	char *path;
684897a330SJim Harris 	size_t len = 0;
694897a330SJim Harris 	ssize_t read;
70*084afa90SKonrad Sztyber 	int errsv;
714897a330SJim Harris 
724897a330SJim Harris 	path = spdk_vsprintf_alloc(format, args);
734897a330SJim Harris 	if (path == NULL) {
744897a330SJim Harris 		return -ENOMEM;
754897a330SJim Harris 	}
764897a330SJim Harris 
774897a330SJim Harris 	file = fopen(path, "r");
78*084afa90SKonrad Sztyber 	errsv = errno;
794897a330SJim Harris 	free(path);
804897a330SJim Harris 	if (file == NULL) {
81*084afa90SKonrad Sztyber 		assert(errsv != 0);
82*084afa90SKonrad Sztyber 		return -errsv;
834897a330SJim Harris 	}
844897a330SJim Harris 
854897a330SJim Harris 	*attribute_p = NULL;
864897a330SJim Harris 	read = getline(attribute_p, &len, file);
87*084afa90SKonrad Sztyber 	errsv = errno;
884897a330SJim Harris 	fclose(file);
894897a330SJim Harris 	attribute = *attribute_p;
904897a330SJim Harris 	if (read == -1) {
914897a330SJim Harris 		/* getline man page says line should be freed even on failure. */
924897a330SJim Harris 		free(attribute);
93*084afa90SKonrad Sztyber 		assert(errsv != 0);
94*084afa90SKonrad Sztyber 		return -errsv;
954897a330SJim Harris 	}
964897a330SJim Harris 
974897a330SJim Harris 	/* len is the length of the allocated buffer, which may be more than
984897a330SJim Harris 	 * the string's length. Reuse len to hold the actual strlen.
994897a330SJim Harris 	 */
1004897a330SJim Harris 	len = strlen(attribute);
1014897a330SJim Harris 	if (attribute[len - 1] == '\n') {
1024897a330SJim Harris 		attribute[len - 1] = '\0';
1034897a330SJim Harris 	}
1044897a330SJim Harris 
1054897a330SJim Harris 	return 0;
1064897a330SJim Harris }
1074897a330SJim Harris 
1084897a330SJim Harris int
1094897a330SJim Harris spdk_read_sysfs_attribute(char **attribute_p, const char *path_format, ...)
1104897a330SJim Harris {
1114897a330SJim Harris 	va_list args;
1124897a330SJim Harris 	int rc;
1134897a330SJim Harris 
1144897a330SJim Harris 	va_start(args, path_format);
1154897a330SJim Harris 	rc = read_sysfs_attribute(attribute_p, path_format, args);
1164897a330SJim Harris 	va_end(args);
1174897a330SJim Harris 
1184897a330SJim Harris 	return rc;
1194897a330SJim Harris }
1202276e22dSJim Harris 
1212276e22dSJim Harris int
1222276e22dSJim Harris spdk_read_sysfs_attribute_uint32(uint32_t *attribute, const char *path_format, ...)
1232276e22dSJim Harris {
1242276e22dSJim Harris 	char *attribute_str = NULL;
1252276e22dSJim Harris 	long long int val;
1262276e22dSJim Harris 	va_list args;
1272276e22dSJim Harris 	int rc;
1282276e22dSJim Harris 
1292276e22dSJim Harris 	va_start(args, path_format);
1302276e22dSJim Harris 	rc = read_sysfs_attribute(&attribute_str, path_format, args);
1312276e22dSJim Harris 	va_end(args);
1322276e22dSJim Harris 
1332276e22dSJim Harris 	if (rc != 0) {
1342276e22dSJim Harris 		return rc;
1352276e22dSJim Harris 	}
1362276e22dSJim Harris 
1372276e22dSJim Harris 	val = spdk_strtoll(attribute_str, 0);
1382276e22dSJim Harris 	free(attribute_str);
1392276e22dSJim Harris 	if (val < 0 || val > UINT32_MAX) {
1402276e22dSJim Harris 		return -EINVAL;
1412276e22dSJim Harris 	}
1422276e22dSJim Harris 
1432276e22dSJim Harris 	*attribute = (uint32_t)val;
1442276e22dSJim Harris 	return 0;
1452276e22dSJim Harris }
146