os_file.c revision 8a1362ad
18a1362adSmaya/* 28a1362adSmaya * Copyright 2019 Intel Corporation 38a1362adSmaya * SPDX-License-Identifier: MIT 48a1362adSmaya */ 58a1362adSmaya 68a1362adSmaya#include "os_file.h" 78a1362adSmaya 88a1362adSmaya#include <errno.h> 98a1362adSmaya#include <stdlib.h> 108a1362adSmaya 118a1362adSmaya#if defined(__linux__) 128a1362adSmaya 138a1362adSmaya#include <fcntl.h> 148a1362adSmaya#include <sys/stat.h> 158a1362adSmaya#include <unistd.h> 168a1362adSmaya 178a1362adSmaya 188a1362adSmayastatic ssize_t 198a1362adSmayareadN(int fd, char *buf, size_t len) 208a1362adSmaya{ 218a1362adSmaya int err = -ENODATA; 228a1362adSmaya size_t total = 0; 238a1362adSmaya do { 248a1362adSmaya ssize_t ret = read(fd, buf + total, len - total); 258a1362adSmaya 268a1362adSmaya if (ret < 0) 278a1362adSmaya ret = -errno; 288a1362adSmaya 298a1362adSmaya if (ret == -EINTR || ret == -EAGAIN) 308a1362adSmaya continue; 318a1362adSmaya 328a1362adSmaya if (ret <= 0) { 338a1362adSmaya err = ret; 348a1362adSmaya break; 358a1362adSmaya } 368a1362adSmaya 378a1362adSmaya total += ret; 388a1362adSmaya } while (total != len); 398a1362adSmaya 408a1362adSmaya return total ? total : err; 418a1362adSmaya} 428a1362adSmaya 438a1362adSmayachar * 448a1362adSmayaos_read_file(const char *filename) 458a1362adSmaya{ 468a1362adSmaya /* Note that this also serves as a slight margin to avoid a 2x grow when 478a1362adSmaya * the file is just a few bytes larger when we read it than when we 488a1362adSmaya * fstat'ed it. 498a1362adSmaya * The string's NULL terminator is also included in here. 508a1362adSmaya */ 518a1362adSmaya size_t len = 64; 528a1362adSmaya 538a1362adSmaya int fd = open(filename, O_RDONLY); 548a1362adSmaya if (fd == -1) { 558a1362adSmaya /* errno set by open() */ 568a1362adSmaya return NULL; 578a1362adSmaya } 588a1362adSmaya 598a1362adSmaya /* Pre-allocate a buffer at least the size of the file if we can read 608a1362adSmaya * that information. 618a1362adSmaya */ 628a1362adSmaya struct stat stat; 638a1362adSmaya if (fstat(fd, &stat) == 0) 648a1362adSmaya len += stat.st_size; 658a1362adSmaya 668a1362adSmaya char *buf = malloc(len); 678a1362adSmaya if (!buf) { 688a1362adSmaya close(fd); 698a1362adSmaya errno = -ENOMEM; 708a1362adSmaya return NULL; 718a1362adSmaya } 728a1362adSmaya 738a1362adSmaya ssize_t read; 748a1362adSmaya size_t offset = 0, remaining = len - 1; 758a1362adSmaya while ((read = readN(fd, buf + offset, remaining)) == remaining) { 768a1362adSmaya char *newbuf = realloc(buf, 2 * len); 778a1362adSmaya if (!newbuf) { 788a1362adSmaya free(buf); 798a1362adSmaya close(fd); 808a1362adSmaya errno = -ENOMEM; 818a1362adSmaya return NULL; 828a1362adSmaya } 838a1362adSmaya 848a1362adSmaya buf = newbuf; 858a1362adSmaya len *= 2; 868a1362adSmaya offset += read; 878a1362adSmaya remaining = len - offset - 1; 888a1362adSmaya } 898a1362adSmaya 908a1362adSmaya close(fd); 918a1362adSmaya 928a1362adSmaya if (read > 0) 938a1362adSmaya offset += read; 948a1362adSmaya 958a1362adSmaya /* Final resize to actual size */ 968a1362adSmaya len = offset + 1; 978a1362adSmaya char *newbuf = realloc(buf, len); 988a1362adSmaya if (!newbuf) { 998a1362adSmaya free(buf); 1008a1362adSmaya errno = -ENOMEM; 1018a1362adSmaya return NULL; 1028a1362adSmaya } 1038a1362adSmaya buf = newbuf; 1048a1362adSmaya 1058a1362adSmaya buf[offset] = '\0'; 1068a1362adSmaya 1078a1362adSmaya return buf; 1088a1362adSmaya} 1098a1362adSmaya 1108a1362adSmaya#else 1118a1362adSmaya 1128a1362adSmayachar * 1138a1362adSmayaos_read_file(const char *filename) 1148a1362adSmaya{ 1158a1362adSmaya errno = -ENOSYS; 1168a1362adSmaya return NULL; 1178a1362adSmaya} 1188a1362adSmaya 1198a1362adSmaya#endif 120