|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * gnc-filepath-utils.c -- file path resolutin utilitie * 00003 * * 00004 * This program is free software; you can redistribute it and/or * 00005 * modify it under the terms of the GNU General Public License as * 00006 * published by the Free Software Foundation; either version 2 of * 00007 * the License, or (at your option) any later version. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License* 00015 * along with this program; if not, contact: * 00016 * * 00017 * Free Software Foundation Voice: +1-617-542-5942 * 00018 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00019 * Boston, MA 02110-1301, USA gnu@gnu.org * 00020 \********************************************************************/ 00021 00022 /* 00023 * @file gnc-filepath-utils.c 00024 * @brief file path resolution utilities 00025 * @author Copyright (c) 1998-2004 Linas Vepstas <linas@linas.org> 00026 * @author Copyright (c) 2000 Dave Peticolas 00027 */ 00028 00029 #include "config.h" 00030 00031 #include <glib.h> 00032 #include <glib/gi18n.h> 00033 #include <glib/gprintf.h> 00034 #include <glib/gstdio.h> 00035 00036 #include <stdlib.h> 00037 #include <stdio.h> 00038 #include <string.h> 00039 #include <sys/types.h> 00040 #include <sys/stat.h> 00041 #ifdef HAVE_UNISTD_H 00042 # include <unistd.h> 00043 #endif 00044 #include <errno.h> 00045 00046 #include "gnc-path.h" 00047 #include "gnc-filepath-utils.h" 00048 00049 #ifdef _MSC_VER 00050 #include <glib/gwin32.h> 00051 #define PATH_MAX MAXPATHLEN 00052 #endif 00053 00054 00061 static void 00062 scrub_filename(char* filename) 00063 { 00064 char* p; 00065 00066 #define STRANGE_CHARS "/:" 00067 p = strpbrk(filename, STRANGE_CHARS); 00068 while (p) 00069 { 00070 *p = '_'; 00071 p = strpbrk(filename, STRANGE_CHARS); 00072 } 00073 } 00074 00081 static gchar * 00082 check_path_return_if_valid(gchar *path) 00083 { 00084 if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) 00085 { 00086 return path; 00087 } 00088 g_free (path); 00089 return NULL; 00090 } 00091 00119 gchar * 00120 gnc_resolve_file_path (const gchar * filefrag) 00121 { 00122 int namelen; 00123 gchar *fullpath = NULL, *tmp_path = NULL; 00124 00125 /* seriously invalid */ 00126 if (!filefrag) 00127 { 00128 g_critical("filefrag is NULL"); 00129 return NULL; 00130 } 00131 00132 /* ---------------------------------------------------- */ 00133 /* OK, now we try to find or build an absolute file path */ 00134 00135 /* check for an absolute file path */ 00136 if (g_path_is_absolute(filefrag)) 00137 return g_strdup (filefrag); 00138 00139 /* get conservative on the length so that sprintf(getpid()) works ... */ 00140 /* strlen ("/.LCK") + sprintf (%x%d) */ 00141 namelen = strlen (filefrag) + 25; 00142 00143 /* Look in the current working directory */ 00144 tmp_path = g_get_current_dir(); 00145 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL); 00146 g_free(tmp_path); 00147 fullpath = check_path_return_if_valid(fullpath); 00148 if (fullpath != NULL) 00149 return fullpath; 00150 00151 /* Look in the data dir (e.g. $PREFIX/share/gnucash) */ 00152 tmp_path = gnc_path_get_pkgdatadir(); 00153 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL); 00154 g_free(tmp_path); 00155 fullpath = check_path_return_if_valid(fullpath); 00156 if (fullpath != NULL) 00157 return fullpath; 00158 00159 /* Look in the config dir (e.g. $PREFIX/share/gnucash/accounts) */ 00160 tmp_path = gnc_path_get_accountsdir(); 00161 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL); 00162 g_free(tmp_path); 00163 fullpath = check_path_return_if_valid(fullpath); 00164 if (fullpath != NULL) 00165 return fullpath; 00166 00167 /* Look in the users config dir (e.g. $HOME/.gnucash/data) */ 00168 fullpath = gnc_build_data_path(filefrag); 00169 if (g_file_test(fullpath, G_FILE_TEST_IS_REGULAR)) 00170 return fullpath; 00171 00172 /* OK, it's not there. Note that it needs to be created and pass it 00173 * back anyway */ 00174 g_warning("create new file %s", fullpath); 00175 return fullpath; 00176 00177 } 00178 00179 /* ====================================================================== */ 00180 00186 static void 00187 gnc_validate_directory (const gchar *dirname) 00188 { 00189 struct stat statbuf; 00190 gint rc; 00191 00192 rc = g_stat (dirname, &statbuf); 00193 if (rc) 00194 { 00195 switch (errno) 00196 { 00197 case ENOENT: 00198 rc = g_mkdir (dirname, 00199 #ifdef G_OS_WIN32 00200 0 /* The mode argument is ignored on windows */ 00201 #else 00202 S_IRWXU /* perms = S_IRWXU = 0700 */ 00203 #endif 00204 ); 00205 if (rc) 00206 { 00207 g_fprintf(stderr, 00208 _("An error occurred while creating the directory:\n" 00209 " %s\n" 00210 "Please correct the problem and restart GnuCash.\n" 00211 "The reported error was '%s' (errno %d).\n"), 00212 dirname, g_strerror(errno) ? g_strerror(errno) : "", errno); 00213 exit(1); 00214 } 00215 g_stat (dirname, &statbuf); 00216 break; 00217 00218 case EACCES: 00219 g_fprintf(stderr, 00220 _("The directory\n" 00221 " %s\n" 00222 "exists but cannot be accessed. This program \n" 00223 "must have full access (read/write/execute) to \n" 00224 "the directory in order to function properly.\n"), 00225 dirname); 00226 exit(1); 00227 00228 case ENOTDIR: 00229 g_fprintf(stderr, 00230 _("The path\n" 00231 " %s\n" 00232 "exists but it is not a directory. Please delete\n" 00233 "the file and start GnuCash again.\n"), 00234 dirname); 00235 exit(1); 00236 00237 default: 00238 g_fprintf(stderr, 00239 _("An unknown error occurred when validating that the\n" 00240 " %s\n" 00241 "directory exists and is usable. Please correct the\n" 00242 "problem and restart GnuCash. The reported error \n" 00243 "was '%s' (errno %d)."), 00244 dirname, g_strerror(errno) ? g_strerror(errno) : "", errno); 00245 exit(1); 00246 } 00247 } 00248 00249 if ((statbuf.st_mode & S_IFDIR) != S_IFDIR) 00250 { 00251 g_fprintf(stderr, 00252 _("The path\n" 00253 " %s\n" 00254 "exists but it is not a directory. Please delete\n" 00255 "the file and start GnuCash again.\n"), 00256 dirname); 00257 exit(1); 00258 } 00259 #ifndef G_OS_WIN32 00260 /* The mode argument is ignored on windows anyway */ 00261 if ((statbuf.st_mode & S_IRWXU) != S_IRWXU) 00262 { 00263 g_fprintf(stderr, 00264 _("The permissions are wrong on the directory\n" 00265 " %s\n" 00266 "They must be at least 'rwx' for the user.\n"), 00267 dirname); 00268 exit(1); 00269 } 00270 #endif 00271 } 00272 00281 const gchar * 00282 gnc_dotgnucash_dir (void) 00283 { 00284 static gchar *dotgnucash = NULL; 00285 gchar *tmp_dir; 00286 00287 if (dotgnucash) 00288 return dotgnucash; 00289 00290 dotgnucash = g_strdup(g_getenv("GNC_DOT_DIR")); 00291 00292 if (!dotgnucash) 00293 { 00294 const gchar *home = g_get_home_dir(); 00295 if (!home) 00296 { 00297 g_warning("Cannot find home directory. Using tmp directory instead."); 00298 home = g_get_tmp_dir(); 00299 } 00300 g_assert(home); 00301 00302 dotgnucash = g_build_filename(home, ".gnucash", (gchar *)NULL); 00303 } 00304 gnc_validate_directory(dotgnucash); 00305 00306 /* Since we're in code that is only executed once.... */ 00307 tmp_dir = g_build_filename(dotgnucash, "books", (gchar *)NULL); 00308 gnc_validate_directory(tmp_dir); 00309 g_free(tmp_dir); 00310 tmp_dir = g_build_filename(dotgnucash, "checks", (gchar *)NULL); 00311 gnc_validate_directory(tmp_dir); 00312 g_free(tmp_dir); 00313 tmp_dir = g_build_filename(dotgnucash, "translog", (gchar *)NULL); 00314 gnc_validate_directory(tmp_dir); 00315 g_free(tmp_dir); 00316 00317 return dotgnucash; 00318 } 00319 00328 gchar * 00329 gnc_build_dotgnucash_path (const gchar *filename) 00330 { 00331 return g_build_filename(gnc_dotgnucash_dir(), filename, (gchar *)NULL); 00332 } 00333 00342 gchar * 00343 gnc_build_book_path (const gchar *filename) 00344 { 00345 gchar* filename_dup = g_strdup(filename); 00346 gchar* result = NULL; 00347 00348 scrub_filename(filename_dup); 00349 result = g_build_filename(gnc_dotgnucash_dir(), "books", 00350 filename_dup, (gchar *)NULL); 00351 g_free(filename_dup); 00352 return result; 00353 } 00354 00363 gchar * 00364 gnc_build_translog_path (const gchar *filename) 00365 { 00366 gchar* filename_dup = g_strdup(filename); 00367 gchar* result = NULL; 00368 00369 scrub_filename(filename_dup); 00370 result = g_build_filename(gnc_dotgnucash_dir(), "translog", 00371 filename_dup, (gchar *)NULL); 00372 g_free(filename_dup); 00373 return result; 00374 } 00375 00384 gchar * 00385 gnc_build_data_path (const gchar *filename) 00386 { 00387 gchar* filename_dup = g_strdup(filename); 00388 gchar* result; 00389 00390 scrub_filename(filename_dup); 00391 result = g_build_filename(gnc_dotgnucash_dir(), "data", filename_dup, (gchar *)NULL); 00392 g_free(filename_dup); 00393 return result; 00394 } 00395 00404 gchar * 00405 gnc_build_report_path (const gchar *filename) 00406 { 00407 gchar *result = g_build_filename(gnc_path_get_reportdir(), filename, (gchar *)NULL); 00408 return result; 00409 } 00410 00419 gchar * 00420 gnc_build_stdreports_path (const gchar *filename) 00421 { 00422 gchar *result = g_build_filename(gnc_path_get_stdreportsdir(), filename, (gchar *)NULL); 00423 return result; 00424 } 00425 00426 00427 /* =============================== END OF FILE ========================== */
1.7.4