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