1/* open-po - search for .po file along search path list and open for reading
2   Copyright (C) 1995-1996, 2000-2003, 2005-2006 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 2, or (at your option)
8   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, write to the Free Software Foundation,
17   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
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 "pathname.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 erray.  */
42#define SIZEOF(a) (sizeof(a)/sizeof(a[0]))
43
44static FILE *
45try_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.  If the name is absolute,
61     try the various extensions, but ignore the directory search list.  */
62  if (IS_ABSOLUTE_PATH (input_name))
63    {
64      for (k = 0; k < SIZEOF (extension); ++k)
65	{
66	  file_name = concatenated_pathname ("", input_name, extension[k]);
67
68	  ret_val = fopen (file_name, "r");
69	  if (ret_val != NULL || errno != ENOENT)
70	    {
71	      /* We found the file.  */
72	      *real_file_name_p = file_name;
73	      return ret_val;
74	    }
75
76	  free (file_name);
77	}
78    }
79  else
80    {
81      /* For relative file names, look through the directory search list,
82	 trying the various extensions.  If no directory search list is
83	 specified, the current directory is used.  */
84      for (j = 0; (dir = dir_list_nth (j)) != NULL; ++j)
85	for (k = 0; k < SIZEOF (extension); ++k)
86	  {
87	    file_name = concatenated_pathname (dir, input_name, extension[k]);
88
89	    ret_val = fopen (file_name, "r");
90	    if (ret_val != NULL || errno != ENOENT)
91	      {
92		*real_file_name_p = file_name;
93		return ret_val;
94	      }
95
96	    free (file_name);
97	  }
98    }
99
100  /* File does not exist.  */
101  *real_file_name_p = xstrdup (input_name);
102  errno = ENOENT;
103  return NULL;
104}
105
106/* Open the input file with the name INPUT_NAME.  The ending .po is added
107   if necessary.  If INPUT_NAME is not an absolute file name and the file is
108   not found, the list of directories in "dir-list.h" is searched.  The
109   file's pathname is returned in *REAL_FILE_NAME_P, for error message
110   purposes.  */
111FILE *
112open_catalog_file (const char *input_name, char **real_file_name_p,
113		   bool exit_on_error)
114{
115  FILE *fp = try_open_catalog_file (input_name, real_file_name_p);
116
117  if (fp == NULL && exit_on_error)
118    {
119      const char *errno_description = strerror (errno);
120      po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false,
121		 xasprintf ("%s: %s",
122			    xasprintf (_("error while opening \"%s\" for reading"),
123				       *real_file_name_p),
124			    errno_description));
125    }
126
127  return fp;
128}
129