(root)/
gettext-0.22.4/
gettext-tools/
src/
open-catalog.c
       1  /* open-po - search for .po file along search path list and open for reading
       2     Copyright (C) 1995-1996, 2000-2003, 2005-2009, 2020 Free Software Foundation, Inc.
       3     Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifdef HAVE_CONFIG_H
      19  # include <config.h>
      20  #endif
      21  
      22  /* Specification.  */
      23  #include "open-catalog.h"
      24  
      25  #include <errno.h>
      26  #include <stdbool.h>
      27  #include <stdio.h>
      28  #include <stdlib.h>
      29  #include <string.h>
      30  
      31  #include "dir-list.h"
      32  #include "filename.h"
      33  #include "concat-filename.h"
      34  #include "xalloc.h"
      35  #include "xvasprintf.h"
      36  #include "po-xerror.h"
      37  #include "gettext.h"
      38  
      39  #define _(str) gettext (str)
      40  
      41  /* This macro is used to determine the number of elements in an array.  */
      42  #define SIZEOF(a) (sizeof(a)/sizeof(a[0]))
      43  
      44  static FILE *
      45  try_open_catalog_file (const char *input_name, char **real_file_name_p)
      46  {
      47    static const char *extension[] = { "", ".po", ".pot", };
      48    char *file_name;
      49    FILE *ret_val;
      50    int j;
      51    size_t k;
      52    const char *dir;
      53  
      54    if (strcmp (input_name, "-") == 0 || strcmp (input_name, "/dev/stdin") == 0)
      55      {
      56        *real_file_name_p = xstrdup (_("<stdin>"));
      57        return stdin;
      58      }
      59  
      60    /* We have a real name for the input file.  */
      61    if (IS_RELATIVE_FILE_NAME (input_name))
      62      {
      63        /* For relative file names, look through the directory search list,
      64           trying the various extensions.  If no directory search list is
      65           specified, the current directory is used.  */
      66        for (j = 0; (dir = dir_list_nth (j)) != NULL; ++j)
      67          for (k = 0; k < SIZEOF (extension); ++k)
      68            {
      69              file_name = xconcatenated_filename (dir, input_name, extension[k]);
      70  
      71              ret_val = fopen (file_name, "r");
      72              if (ret_val != NULL || errno != ENOENT)
      73                {
      74                  /* We found the file.  */
      75                  *real_file_name_p = file_name;
      76                  return ret_val;
      77                }
      78  
      79              free (file_name);
      80            }
      81      }
      82    else
      83      {
      84        /* The name is not relative.  Try the various extensions, but ignore the
      85           directory search list.  */
      86        for (k = 0; k < SIZEOF (extension); ++k)
      87          {
      88            file_name = xconcatenated_filename ("", input_name, extension[k]);
      89  
      90            ret_val = fopen (file_name, "r");
      91            if (ret_val != NULL || errno != ENOENT)
      92              {
      93                /* We found the file.  */
      94                *real_file_name_p = file_name;
      95                return ret_val;
      96              }
      97  
      98            free (file_name);
      99          }
     100      }
     101  
     102    /* File does not exist.  */
     103    *real_file_name_p = xstrdup (input_name);
     104    errno = ENOENT;
     105    return NULL;
     106  }
     107  
     108  /* Open the input file with the name INPUT_NAME.  The ending .po is added
     109     if necessary.  If INPUT_NAME is not an absolute file name and the file is
     110     not found, the list of directories in "dir-list.h" is searched.  The
     111     file's pathname is returned in *REAL_FILE_NAME_P, for error message
     112     purposes.  */
     113  FILE *
     114  open_catalog_file (const char *input_name, char **real_file_name_p,
     115                     bool exit_on_error)
     116  {
     117    FILE *fp = try_open_catalog_file (input_name, real_file_name_p);
     118  
     119    if (fp == NULL && exit_on_error)
     120      {
     121        const char *errno_description = strerror (errno);
     122        po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false,
     123                   xasprintf ("%s: %s",
     124                              xasprintf (_("error while opening \"%s\" for reading"),
     125                                         *real_file_name_p),
     126                              errno_description));
     127      }
     128  
     129    return fp;
     130  }