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