blob: ab12e0bbc51d15d34441a90880b6b1a7271d89de [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "file_utils.h"
#if defined(_MSC_VER)
#define _CRT_SECURE_NO_WARNINGS // squelch fopen()
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
// Close a FILE descriptor, preserving errno to properly report previous
// I/O errors.
static void
file_close(FILE * f)
{
int saved_errno = errno;
(void)fclose(f);
errno = saved_errno;
}
// Retrieve file size from a FILE decriptor.
// On success, return true and sets |*file_size|, false/errno otherwise.
// NOTE: This rewinds the descriptor to the start of the file on success!
static bool
file_get_size(FILE * const file, size_t * const file_size)
{
if (fseek(file, 0, SEEK_END) != 0)
return false;
long size = ftell(file);
if (size < 0)
return false;
if (fseek(file, 0, SEEK_SET) != 0)
return false;
*file_size = (size_t)size;
return true;
}
// Read |file_size| bytes from |file| into heap-allocated memory.
// On success, return true and sets |*file_data|, false/errno otherwise.
static bool
file_read_data_from(FILE * file, size_t file_size, void ** file_data)
{
*file_data = NULL;
if (file_size == 0)
return true;
void * data = malloc(file_size);
if (!data)
return false;
size_t bytes_read = fread(data, 1, file_size, file);
if (bytes_read != file_size)
{
free(data);
return false;
}
*file_data = data;
return true;
}
bool
file_read(const char * const file_path, void ** const file_data, size_t * const file_size)
{
*file_data = NULL;
*file_size = 0;
FILE * f = fopen(file_path, "rb");
if (!f)
return false;
bool success = file_get_size(f, file_size) && file_read_data_from(f, *file_size, file_data);
file_close(f);
return success;
}
bool
file_write(const char * const file_path, const void * const file_data, size_t file_size)
{
FILE * file = fopen(file_path, "wb");
if (!file)
return false;
size_t bytes_written = fwrite(file_data, 1, file_size, file);
file_close(file);
return bytes_written == file_size;
}