linux/tools/power/acpi/tools/acpidump/apfiles.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: apfiles - File-related functions for acpidump utility
   5 *
   6 * Copyright (C) 2000 - 2021, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include "acpidump.h"
  11
  12/* Local prototypes */
  13
  14static int ap_is_existing_file(char *pathname);
  15
  16/******************************************************************************
  17 *
  18 * FUNCTION:    ap_is_existing_file
  19 *
  20 * PARAMETERS:  pathname            - Output filename
  21 *
  22 * RETURN:      0 on success
  23 *
  24 * DESCRIPTION: Query for file overwrite if it already exists.
  25 *
  26 ******************************************************************************/
  27
  28static int ap_is_existing_file(char *pathname)
  29{
  30#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
  31        struct stat stat_info;
  32        int in_char;
  33
  34        if (!stat(pathname, &stat_info)) {
  35                fprintf(stderr,
  36                        "Target path already exists, overwrite? [y|n] ");
  37
  38                in_char = fgetc(stdin);
  39                if (in_char == '\n') {
  40                        in_char = fgetc(stdin);
  41                }
  42
  43                if (in_char != 'y' && in_char != 'Y') {
  44                        return (-1);
  45                }
  46        }
  47#endif
  48
  49        return (0);
  50}
  51
  52/******************************************************************************
  53 *
  54 * FUNCTION:    ap_open_output_file
  55 *
  56 * PARAMETERS:  pathname            - Output filename
  57 *
  58 * RETURN:      Open file handle
  59 *
  60 * DESCRIPTION: Open a text output file for acpidump. Checks if file already
  61 *              exists.
  62 *
  63 ******************************************************************************/
  64
  65int ap_open_output_file(char *pathname)
  66{
  67        ACPI_FILE file;
  68
  69        /* If file exists, prompt for overwrite */
  70
  71        if (ap_is_existing_file(pathname) != 0) {
  72                return (-1);
  73        }
  74
  75        /* Point stdout to the file */
  76
  77        file = fopen(pathname, "w");
  78        if (!file) {
  79                fprintf(stderr, "Could not open output file: %s\n", pathname);
  80                return (-1);
  81        }
  82
  83        /* Save the file and path */
  84
  85        gbl_output_file = file;
  86        gbl_output_filename = pathname;
  87        return (0);
  88}
  89
  90/******************************************************************************
  91 *
  92 * FUNCTION:    ap_write_to_binary_file
  93 *
  94 * PARAMETERS:  table               - ACPI table to be written
  95 *              instance            - ACPI table instance no. to be written
  96 *
  97 * RETURN:      Status
  98 *
  99 * DESCRIPTION: Write an ACPI table to a binary file. Builds the output
 100 *              filename from the table signature.
 101 *
 102 ******************************************************************************/
 103
 104int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
 105{
 106        char filename[ACPI_NAMESEG_SIZE + 16];
 107        char instance_str[16];
 108        ACPI_FILE file;
 109        acpi_size actual;
 110        u32 table_length;
 111
 112        /* Obtain table length */
 113
 114        table_length = ap_get_table_length(table);
 115
 116        /* Construct lower-case filename from the table local signature */
 117
 118        if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
 119                ACPI_COPY_NAMESEG(filename, ACPI_RSDP_NAME);
 120        } else {
 121                ACPI_COPY_NAMESEG(filename, table->signature);
 122        }
 123
 124        filename[0] = (char)tolower((int)filename[0]);
 125        filename[1] = (char)tolower((int)filename[1]);
 126        filename[2] = (char)tolower((int)filename[2]);
 127        filename[3] = (char)tolower((int)filename[3]);
 128        filename[ACPI_NAMESEG_SIZE] = 0;
 129
 130        /* Handle multiple SSDts - create different filenames for each */
 131
 132        if (instance > 0) {
 133                snprintf(instance_str, sizeof(instance_str), "%u", instance);
 134                strcat(filename, instance_str);
 135        }
 136
 137        strcat(filename, FILE_SUFFIX_BINARY_TABLE);
 138
 139        if (gbl_verbose_mode) {
 140                fprintf(stderr,
 141                        "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n",
 142                        table->signature, filename, table->length,
 143                        table->length);
 144        }
 145
 146        /* Open the file and dump the entire table in binary mode */
 147
 148        file = fopen(filename, "wb");
 149        if (!file) {
 150                fprintf(stderr, "Could not open output file: %s\n", filename);
 151                return (-1);
 152        }
 153
 154        actual = fwrite(table, 1, table_length, file);
 155        if (actual != table_length) {
 156                fprintf(stderr, "Error writing binary output file: %s\n",
 157                        filename);
 158                fclose(file);
 159                return (-1);
 160        }
 161
 162        fclose(file);
 163        return (0);
 164}
 165
 166/******************************************************************************
 167 *
 168 * FUNCTION:    ap_get_table_from_file
 169 *
 170 * PARAMETERS:  pathname            - File containing the binary ACPI table
 171 *              out_file_size       - Where the file size is returned
 172 *
 173 * RETURN:      Buffer containing the ACPI table. NULL on error.
 174 *
 175 * DESCRIPTION: Open a file and read it entirely into a new buffer
 176 *
 177 ******************************************************************************/
 178
 179struct acpi_table_header *ap_get_table_from_file(char *pathname,
 180                                                 u32 *out_file_size)
 181{
 182        struct acpi_table_header *buffer = NULL;
 183        ACPI_FILE file;
 184        u32 file_size;
 185        acpi_size actual;
 186
 187        /* Must use binary mode */
 188
 189        file = fopen(pathname, "rb");
 190        if (!file) {
 191                fprintf(stderr, "Could not open input file: %s\n", pathname);
 192                return (NULL);
 193        }
 194
 195        /* Need file size to allocate a buffer */
 196
 197        file_size = cm_get_file_size(file);
 198        if (file_size == ACPI_UINT32_MAX) {
 199                fprintf(stderr,
 200                        "Could not get input file size: %s\n", pathname);
 201                goto cleanup;
 202        }
 203
 204        /* Allocate a buffer for the entire file */
 205
 206        buffer = ACPI_ALLOCATE_ZEROED(file_size);
 207        if (!buffer) {
 208                fprintf(stderr,
 209                        "Could not allocate file buffer of size: %u\n",
 210                        file_size);
 211                goto cleanup;
 212        }
 213
 214        /* Read the entire file */
 215
 216        actual = fread(buffer, 1, file_size, file);
 217        if (actual != file_size) {
 218                fprintf(stderr, "Could not read input file: %s\n", pathname);
 219                ACPI_FREE(buffer);
 220                buffer = NULL;
 221                goto cleanup;
 222        }
 223
 224        *out_file_size = file_size;
 225
 226cleanup:
 227        fclose(file);
 228        return (buffer);
 229}
 230