1/* open-po - search for .po file along search path list and open for reading 2 Copyright (C) 1995-1996, 2000-2003, 2005-2007 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 <http://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 "xalloc.h" 34#include "xvasprintf.h" 35#include "po-xerror.h" 36#include "gettext.h" 37 38#define _(str) gettext (str) 39 40/* This macro is used to determine the number of elements in an erray. */ 41#define SIZEOF(a) (sizeof(a)/sizeof(a[0])) 42 43static FILE * 44try_open_catalog_file (const char *input_name, char **real_file_name_p) 45{ 46 static const char *extension[] = { "", ".po", ".pot", }; 47 char *file_name; 48 FILE *ret_val; 49 int j; 50 size_t k; 51 const char *dir; 52 53 if (strcmp (input_name, "-") == 0 || strcmp (input_name, "/dev/stdin") == 0) 54 { 55 *real_file_name_p = xstrdup (_("<stdin>")); 56 return stdin; 57 } 58 59 /* We have a real name for the input file. If the name is absolute, 60 try the various extensions, but ignore the directory search list. */ 61 if (IS_ABSOLUTE_PATH (input_name)) 62 { 63 for (k = 0; k < SIZEOF (extension); ++k) 64 { 65 file_name = concatenated_filename ("", input_name, extension[k]); 66 67 ret_val = fopen (file_name, "r"); 68 if (ret_val != NULL || errno != ENOENT) 69 { 70 /* We found the file. */ 71 *real_file_name_p = file_name; 72 return ret_val; 73 } 74 75 free (file_name); 76 } 77 } 78 else 79 { 80 /* For relative file names, look through the directory search list, 81 trying the various extensions. If no directory search list is 82 specified, the current directory is used. */ 83 for (j = 0; (dir = dir_list_nth (j)) != NULL; ++j) 84 for (k = 0; k < SIZEOF (extension); ++k) 85 { 86 file_name = concatenated_filename (dir, input_name, extension[k]); 87 88 ret_val = fopen (file_name, "r"); 89 if (ret_val != NULL || errno != ENOENT) 90 { 91 *real_file_name_p = file_name; 92 return ret_val; 93 } 94 95 free (file_name); 96 } 97 } 98 99 /* File does not exist. */ 100 *real_file_name_p = xstrdup (input_name); 101 errno = ENOENT; 102 return NULL; 103} 104 105/* Open the input file with the name INPUT_NAME. The ending .po is added 106 if necessary. If INPUT_NAME is not an absolute file name and the file is 107 not found, the list of directories in "dir-list.h" is searched. The 108 file's pathname is returned in *REAL_FILE_NAME_P, for error message 109 purposes. */ 110FILE * 111open_catalog_file (const char *input_name, char **real_file_name_p, 112 bool exit_on_error) 113{ 114 FILE *fp = try_open_catalog_file (input_name, real_file_name_p); 115 116 if (fp == NULL && exit_on_error) 117 { 118 const char *errno_description = strerror (errno); 119 po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false, 120 xasprintf ("%s: %s", 121 xasprintf (_("error while opening \"%s\" for reading"), 122 *real_file_name_p), 123 errno_description)); 124 } 125 126 return fp; 127} 128