30 #include <glib/gi18n.h> 31 #include <glib/gprintf.h> 32 #include <glib/gstdio.h> 47 #include <sys/types.h> 57 #if defined (_MSC_VER) || defined (G_OS_WIN32) 58 #include <glib/gwin32.h> 60 #define PATH_MAX MAXPATHLEN 63 #ifdef MAC_INTEGRATION 64 #include <Foundation/Foundation.h> 68 #include "gnc-locale-utils.hpp" 69 #include <boost/filesystem.hpp> 70 #include <boost/locale.hpp> 93 using codecvt = std::codecvt_utf8<wchar_t, 0x10FFFF, std::little_endian>;
94 using string = std::wstring;
97 template<
class I,
class E,
class S>
103 using string = std::string;
106 static std::locale bfs_locale(std::locale(),
new codecvt);
108 namespace bfs = boost::filesystem;
109 namespace bst = boost::system;
110 namespace bl = boost::locale;
119 check_path_return_if_valid(gchar *path)
121 if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
159 gchar *fullpath = NULL, *tmp_path = NULL;
164 g_critical(
"filefrag is NULL");
172 if (g_path_is_absolute(filefrag))
173 return g_strdup (filefrag);
176 tmp_path = g_get_current_dir();
177 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL);
179 fullpath = check_path_return_if_valid(fullpath);
180 if (fullpath != NULL)
184 tmp_path = gnc_path_get_pkgdatadir();
185 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL);
187 fullpath = check_path_return_if_valid(fullpath);
188 if (fullpath != NULL)
192 tmp_path = gnc_path_get_accountsdir();
193 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL);
195 fullpath = check_path_return_if_valid(fullpath);
196 if (fullpath != NULL)
201 if (g_file_test(fullpath, G_FILE_TEST_IS_REGULAR))
206 g_warning(
"create new file %s", fullpath);
214 if (p.find(prefix) == 0)
215 return g_strdup(p.substr(strlen(prefix)).c_str());
216 return g_strdup(path);
233 gnc_path_find_localized_html_file_internal (
const gchar * file_name)
235 gchar *full_path = NULL;
237 const gchar *env_doc_path = g_getenv(
"GNC_DOC_PATH");
238 const gchar *default_dirs[] =
241 gnc_path_get_pkgdocdir (),
242 gnc_path_get_pkgdatadir (),
247 if (!file_name || *file_name ==
'\0')
252 dirs = g_strsplit (env_doc_path, G_SEARCHPATH_SEPARATOR_S, -1);
254 dirs = (gchar **)default_dirs;
256 for (i = 0; dirs[i]; i++)
258 full_path = g_build_filename (dirs[i], file_name, (gchar *)NULL);
259 g_debug (
"Checking for existence of %s", full_path);
260 full_path = check_path_return_if_valid (full_path);
261 if (full_path != NULL)
305 gchar *loc_file_name = NULL;
306 gchar *full_path = NULL;
307 const gchar *
const *lang;
309 if (!file_name || *file_name ==
'\0')
313 if (g_path_is_absolute (file_name))
314 return g_strdup (file_name);
319 for (lang = g_get_language_names (); *lang; lang++)
321 loc_file_name = g_build_filename (*lang, file_name, (gchar *)NULL);
322 full_path = gnc_path_find_localized_html_file_internal (loc_file_name);
323 g_free (loc_file_name);
324 if (full_path != NULL)
331 return gnc_path_find_localized_html_file_internal (file_name);
336 static auto gnc_userdata_home = bfs::path();
337 static auto gnc_userconfig_home = bfs::path();
338 static auto build_dir = bfs::path();
343 static std::string gnc_userdata_home_str;
344 static std::string gnc_userconfig_home_str;
346 static bool dir_is_descendant (
const bfs::path& path,
const bfs::path& base)
348 auto test_path = path;
349 if (bfs::exists (path))
350 test_path = bfs::canonical (path);
351 auto test_base = base;
352 if (bfs::exists (base))
353 test_base = bfs::canonical (base);
355 auto is_descendant = (test_path.string() == test_base.string());
356 while (!test_path.empty() && !is_descendant)
358 test_path = test_path.parent_path();
359 is_descendant = (test_path.string() == test_base.string());
361 return is_descendant;
370 gnc_validate_directory (
const bfs::path &dirname)
375 auto create_dirs =
true;
376 if (build_dir.empty() || !dir_is_descendant (dirname, build_dir))
385 bfs::path home_dir(g_get_home_dir(), cvt);
386 home_dir.imbue(bfs_locale);
387 auto homedir_exists = bfs::exists(home_dir);
388 auto is_descendant = dir_is_descendant (dirname, home_dir);
389 if (!homedir_exists && is_descendant)
401 bfs::create_directories(dirname);
403 throw (bfs::filesystem_error (
404 std::string (dirname.string() +
405 " is a descendant of a non-existing home directory. As " +
407 " will never create a home directory this path can't be used"),
408 dirname, bst::error_code(bst::errc::permission_denied, bst::generic_category())));
410 auto d = bfs::directory_entry (dirname);
411 auto perms = d.status().permissions();
416 #if PLATFORM(WINDOWS) 417 auto check_perms = bfs::owner_read | bfs::owner_write;
419 auto check_perms = bfs::owner_all;
421 if ((perms & check_perms) != check_perms)
422 throw (bfs::filesystem_error(
423 std::string(
"Insufficient permissions, at least write and access permissions required: ")
424 + dirname.string(), dirname,
425 bst::error_code(bst::errc::permission_denied, bst::generic_category())));
433 copy_recursive(
const bfs::path& src,
const bfs::path& dest)
435 if (!bfs::exists(src))
439 if (src.compare(dest) == 0)
442 auto old_str = src.string();
443 auto old_len = old_str.size();
449 for(
auto direntry = bfs::recursive_directory_iterator(src);
450 direntry != bfs::recursive_directory_iterator(); ++direntry)
453 string cur_str = direntry->path().wstring();
455 string cur_str = direntry->path().string();
457 auto cur_len = cur_str.size();
458 string rel_str(cur_str, old_len, cur_len - old_len);
459 bfs::path relpath(rel_str, cvt);
460 auto newpath = bfs::absolute (relpath.relative_path(), dest);
461 newpath.imbue(bfs_locale);
462 bfs::copy(direntry->path(), newpath);
465 catch(
const bfs::filesystem_error& ex)
467 g_warning(
"An error occurred while trying to migrate the user configation from\n%s to\n%s" 469 src.string().c_str(), gnc_userdata_home_str.c_str(),
486 wchar_t path[MAX_PATH+1];
488 LPITEMIDLIST pidl = NULL;
491 hr = SHGetSpecialFolderLocation (NULL, CSIDL_APPDATA, &pidl);
494 b = SHGetPathFromIDListW (pidl, path);
495 CoTaskMemFree (pidl);
497 bfs::path retval(path, cvt);
498 retval.imbue(bfs_locale);
501 #elif defined MAC_INTEGRATION 506 NSFileManager*fm = [NSFileManager defaultManager];
507 NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
508 inDomains:NSUserDomainMask];
509 NSString *dirPath =
nullptr;
510 if ([appSupportDir count] > 0)
512 NSURL* dirUrl = [appSupportDir objectAtIndex:0];
513 dirPath = [dirUrl path];
515 return [dirPath UTF8String];
521 return g_get_user_data_dir();
532 get_userdata_home(
void)
534 auto try_tmp_dir =
true;
535 auto userdata_home = get_user_data_dir();
540 if (!userdata_home.empty())
544 gnc_validate_directory(userdata_home);
547 catch (
const bfs::filesystem_error& ex)
549 auto path_string = userdata_home.string();
550 g_warning(
"%s is not a suitable base directory for the user data. " 551 "Trying temporary directory instead.\n(Error: %s)",
552 path_string.c_str(), ex.what());
560 bfs::path newpath(g_get_tmp_dir (), cvt);
561 userdata_home = newpath / g_get_user_name ();
562 userdata_home.imbue(bfs_locale);
564 g_assert(!userdata_home.empty());
566 return userdata_home;
576 get_userconfig_home(
void)
580 #if defined (G_OS_WIN32) || defined (MAC_INTEGRATION) 581 return get_user_data_dir();
583 return g_get_user_config_dir();
587 static std::string migrate_gnc_datahome()
589 auto success =
false;
591 bfs::path old_dir(g_get_home_dir(), cvt);
592 old_dir /=
".gnucash";
594 std::stringstream migration_msg;
595 migration_msg.imbue(gnc_get_boost_locale());
598 auto full_copy = copy_recursive (old_dir, gnc_userdata_home);
607 auto failed = std::vector<std::string>{};
608 auto succeeded = std::vector<std::string>{};
612 auto oldlogpath = gnc_userdata_home /
"log.conf";
613 auto newlogpath = gnc_userconfig_home /
"log.conf";
616 if (bfs::exists (oldlogpath) && gnc_validate_directory (gnc_userconfig_home) &&
617 (oldlogpath != newlogpath))
619 bfs::rename (oldlogpath, newlogpath);
620 succeeded.emplace_back (
"log.conf");
623 catch (
const bfs::filesystem_error& ex)
625 failed.emplace_back (
"log.conf");
631 auto user_config_files = std::vector<std::string>
633 "config-2.0.user",
"config-1.8.user",
634 "config-1.6.user",
"config.user" 636 auto conf_exist_vec = std::vector<std::string> {};
637 auto renamed_config = std::string();
638 for (
auto conf_file : user_config_files)
640 auto oldconfpath = gnc_userdata_home / conf_file;
643 if (bfs::exists (oldconfpath) && gnc_validate_directory (gnc_userconfig_home))
646 if (renamed_config.empty())
649 renamed_config = conf_file +
" (" + _(
"Renamed to:") +
" config-user.scm)";
650 auto newconfpath = gnc_userconfig_home /
"config-user.scm";
651 bfs::rename (oldconfpath, newconfpath);
656 conf_exist_vec.emplace_back (conf_file);
660 bfs::remove (oldconfpath);
664 catch (
const bfs::filesystem_error& ex)
666 failed.emplace_back (conf_file);
669 if (!renamed_config.empty())
670 succeeded.emplace_back (renamed_config);
673 if (full_copy || !succeeded.empty() || !conf_exist_vec.empty() || !failed.empty())
674 migration_msg << _(
"Notice") << std::endl << std::endl;
679 << _(
"Your gnucash metadata has been migrated.") << std::endl << std::endl
681 << _(
"Old location:") <<
" " << old_dir.string() << std::endl
683 << _(
"New location:") <<
" " << gnc_userdata_home.string() << std::endl << std::endl
685 << bl::format (std::string{_(
"If you no longer intend to run {1} 2.6.x or older on this system you can safely remove the old directory.")})
690 (!succeeded.empty() || !conf_exist_vec.empty() || !failed.empty()))
691 migration_msg << std::endl << std::endl
692 << _(
"In addition:");
694 if (!succeeded.empty())
696 migration_msg << std::endl << std::endl;
698 migration_msg << bl::format (std::string{ngettext(
"The following file has been copied to {1} instead:",
699 "The following files have been copied to {1} instead:",
700 succeeded.size())}) % gnc_userconfig_home.string().c_str();
702 migration_msg << bl::format (std::string{_(
"The following file in {1} has been renamed:")})
703 % gnc_userconfig_home.string().c_str();
705 migration_msg << std::endl;
706 for (
auto success_file : succeeded)
707 migration_msg <<
"- " << success_file << std::endl;
709 if (!conf_exist_vec.empty())
711 migration_msg <<
"\n\n" 712 << ngettext(
"The following file has become obsolete and will be ignored:",
713 "The following files have become obsolete and will be ignored:",
714 conf_exist_vec.size())
716 for (
auto obs_file : conf_exist_vec)
717 migration_msg <<
"- " << obs_file << std::endl;
721 migration_msg << std::endl << std::endl
722 << bl::format (std::string{ngettext(
"The following file could not be moved to {1}:",
723 "The following files could not be moved to {1}:",
724 failed.size())}) % gnc_userconfig_home.string().c_str()
726 for (
auto failed_file : failed)
727 migration_msg <<
"- " << failed_file << std::endl;
730 return migration_msg.str ();
735 #if defined G_OS_WIN32 ||defined MAC_INTEGRATION 736 constexpr
auto path_package = PACKAGE_NAME;
738 constexpr
auto path_package = PROJECT_NAME;
744 gnc_file_path_init_config_home (
void)
746 auto have_valid_userconfig_home =
false;
752 auto env_build_dir = g_getenv (
"GNC_BUILDDIR");
753 bfs::path new_dir(env_build_dir ? env_build_dir :
"", cvt);
754 new_dir.imbue(bfs_locale);
755 build_dir = std::move(new_dir);
756 auto running_uninstalled = (g_getenv (
"GNC_UNINSTALLED") != NULL);
757 if (running_uninstalled && !build_dir.empty())
759 gnc_userconfig_home = build_dir /
"gnc_config_home";
762 gnc_validate_directory (gnc_userconfig_home);
763 have_valid_userconfig_home =
true;
765 catch (
const bfs::filesystem_error& ex)
767 auto path_string = gnc_userconfig_home.string();
768 g_warning(
"%s (due to run during at build time) is not a suitable directory for user configuration files. " 769 "Trying another directory instead.\n(Error: %s)",
770 path_string.c_str(), ex.what());
774 if (!have_valid_userconfig_home)
778 auto gnc_userconfig_home_env = g_getenv (
"GNC_CONFIG_HOME");
779 if (gnc_userconfig_home_env)
781 bfs::path newdir(gnc_userconfig_home_env, cvt);
782 newdir.imbue(bfs_locale);
783 gnc_userconfig_home = std::move(newdir);
786 gnc_validate_directory (gnc_userconfig_home);
787 have_valid_userconfig_home =
true;
789 catch (
const bfs::filesystem_error& ex)
791 auto path_string = gnc_userconfig_home.string();
792 g_warning(
"%s (from environment variable 'GNC_CONFIG_HOME') is not a suitable directory for user configuration files. " 793 "Trying the default instead.\n(Error: %s)",
794 path_string.c_str(), ex.what());
799 if (!have_valid_userconfig_home)
803 auto userconfig_home = get_userconfig_home();
804 gnc_userconfig_home = userconfig_home / path_package;
807 gnc_validate_directory (gnc_userconfig_home);
809 catch (
const bfs::filesystem_error& ex)
811 g_warning (
"User configuration directory doesn't exist, yet could not be created. Proceed with caution.\n" 812 "(Error: %s)", ex.what());
815 gnc_userconfig_home_str = gnc_userconfig_home.string();
823 gnc_file_path_init_data_home (
void)
826 auto gnc_userdata_home_exists =
false;
827 auto have_valid_userdata_home =
false;
833 auto env_build_dir = g_getenv (
"GNC_BUILDDIR");
834 bfs::path new_dir(env_build_dir ? env_build_dir :
"", cvt);
835 new_dir.imbue(bfs_locale);
836 build_dir = std::move(new_dir);
837 auto running_uninstalled = (g_getenv (
"GNC_UNINSTALLED") != NULL);
838 if (running_uninstalled && !build_dir.empty())
840 gnc_userdata_home = build_dir /
"gnc_data_home";
843 gnc_validate_directory (gnc_userdata_home);
844 have_valid_userdata_home =
true;
845 gnc_userdata_home_exists =
true;
847 catch (
const bfs::filesystem_error& ex)
849 auto path_string = gnc_userdata_home.string();
850 g_warning(
"%s (due to run during at build time) is not a suitable directory for user data. " 851 "Trying another directory instead.\n(Error: %s)",
852 path_string.c_str(), ex.what());
856 if (!have_valid_userdata_home)
860 auto gnc_userdata_home_env = g_getenv (
"GNC_DATA_HOME");
861 if (gnc_userdata_home_env)
863 bfs::path newdir(gnc_userdata_home_env, cvt);
864 newdir.imbue(bfs_locale);
865 gnc_userdata_home = std::move(newdir);
868 gnc_userdata_home_exists = bfs::exists (gnc_userdata_home);
869 gnc_validate_directory (gnc_userdata_home);
870 have_valid_userdata_home =
true;
872 catch (
const bfs::filesystem_error& ex)
874 auto path_string = gnc_userdata_home.string();
875 g_warning(
"%s (from environment variable 'GNC_DATA_HOME') is not a suitable directory for user data. " 876 "Trying the default instead.\n(Error: %s)",
877 path_string.c_str(), ex.what());
882 if (!have_valid_userdata_home)
886 auto userdata_home = get_userdata_home();
887 gnc_userdata_home = userdata_home / path_package;
890 gnc_userdata_home_exists = bfs::exists (gnc_userdata_home);
891 gnc_validate_directory (gnc_userdata_home);
893 catch (
const bfs::filesystem_error& ex)
895 g_warning (
"User data directory doesn't exist, yet could not be created. Proceed with caution.\n" 896 "(Error: %s)", ex.what());
899 gnc_userdata_home_str = gnc_userdata_home.string();
900 return gnc_userdata_home_exists;
914 gnc_userconfig_home = get_userconfig_home() / path_package;
915 gnc_userconfig_home_str = gnc_userconfig_home.string();
917 gnc_file_path_init_config_home ();
918 auto gnc_userdata_home_exists = gnc_file_path_init_data_home ();
922 auto migration_notice = std::string ();
923 if (!gnc_userdata_home_exists)
924 migration_notice = migrate_gnc_datahome();
929 gnc_validate_directory (gnc_userdata_home /
"books");
930 gnc_validate_directory (gnc_userdata_home /
"checks");
931 gnc_validate_directory (gnc_userdata_home /
"translog");
933 catch (
const bfs::filesystem_error& ex)
935 g_warning (
"Default user data subdirectories don't exist, yet could not be created. Proceed with caution.\n" 936 "(Error: %s)", ex.what());
939 return migration_notice.empty() ? NULL : g_strdup (migration_notice.c_str());
983 if (gnc_userdata_home.empty())
985 return g_strdup(gnc_userdata_home_str.c_str());
1004 if (gnc_userdata_home.empty())
1007 return gnc_userconfig_home_str.c_str();
1010 static const bfs::path&
1011 gnc_userdata_dir_as_path (
void)
1013 if (gnc_userdata_home.empty())
1022 return gnc_userdata_home;
1025 static const bfs::path&
1026 gnc_userconfig_dir_as_path (
void)
1028 if (gnc_userdata_home.empty())
1037 return gnc_userconfig_home;
1042 bfs::path path_relative (relative);
1043 path_relative.imbue (bfs_locale);
1044 bfs::path path_absolute;
1045 bfs::path path_head;
1047 if (prefix ==
nullptr)
1049 const gchar *doc_dir = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
1050 if (doc_dir ==
nullptr)
1053 path_head = bfs::path (doc_dir);
1055 path_head.imbue (bfs_locale);
1056 path_absolute = absolute (path_relative, path_head);
1060 bfs::path path_head (prefix);
1061 path_head.imbue (bfs_locale);
1062 path_absolute = absolute (path_relative, path_head);
1064 path_absolute.imbue (bfs_locale);
1066 return g_strdup (path_absolute.string().c_str());
1081 return g_strdup((gnc_userdata_dir_as_path() / filename).
string().c_str());
1096 return g_strdup((gnc_userconfig_dir_as_path() / filename).
string().c_str());
1103 is_invalid_char (
char c)
1105 return (c ==
'/') || ( c ==
':');
1109 gnc_build_userdata_subdir_path (
const gchar *subdir,
const gchar *filename)
1111 auto fn = std::string(filename);
1113 std::replace_if (fn.begin(), fn.end(), is_invalid_char,
'_');
1114 auto result = (gnc_userdata_dir_as_path() / subdir) / fn;
1130 auto path = gnc_build_userdata_subdir_path(
"books", filename).string();
1131 return g_strdup(path.c_str());
1146 auto path = gnc_build_userdata_subdir_path(
"translog", filename).string();
1147 return g_strdup(path.c_str());
1162 auto path = gnc_build_userdata_subdir_path(
"data", filename).string();
1163 return g_strdup(path.c_str());
1178 gchar *scmdir = gnc_path_get_scmdir ();
1179 gchar *result = g_build_filename (scmdir, filename, (gchar *)NULL);
1196 gchar *rptdir = gnc_path_get_reportdir ();
1197 gchar *result = g_build_filename (rptdir, filename, (gchar *)NULL);
1214 gchar *rptsdir = gnc_path_get_reportsdir ();
1215 gchar *result = g_build_filename (rptsdir, dirname, (gchar *)NULL);
1232 gchar *stdrptdir = gnc_path_get_stdreportsdir ();
1233 gchar *result = g_build_filename (stdrptdir, filename, (gchar *)NULL);
1239 gnc_filepath_locate_file (
const gchar *default_path,
const gchar *name)
1243 g_return_val_if_fail (name != NULL, NULL);
1245 if (g_path_is_absolute (name))
1246 fullname = g_strdup (name);
1247 else if (default_path)
1248 fullname = g_build_filename (default_path, name,
nullptr);
1252 if (!g_file_test (fullname, G_FILE_TEST_IS_REGULAR))
1254 g_warning (
"Could not locate file %s", name);
1265 gchar *pkgdatadir = gnc_path_get_pkgdatadir ();
1266 gchar *result = gnc_filepath_locate_file (pkgdatadir, name);
1267 g_free (pkgdatadir);
1274 gchar *default_path;
1276 gchar* pkgdatadir = gnc_path_get_pkgdatadir ();
1278 default_path = g_build_filename (pkgdatadir,
"pixmaps",
nullptr);
1280 fullname = gnc_filepath_locate_file (default_path, name);
1281 g_free(default_path);
1289 gchar *default_path;
1291 gchar* pkgdatadir = gnc_path_get_pkgdatadir ();
1293 default_path = g_build_filename (pkgdatadir,
"ui",
nullptr);
1295 fullname = gnc_filepath_locate_file (default_path, name);
1296 g_free(default_path);
1304 gchar *docdir = gnc_path_get_pkgdocdir ();
1305 gchar *result = gnc_filepath_locate_file (docdir, name);
1313 if (gnc_userdata_home.empty())
1316 std::vector<EnvPaths> paths
1317 { {
"GNC_USERDATA_DIR", gnc_userdata_home_str.c_str(),
true},
1318 {
"GNC_USERCONFIG_DIR", gnc_userconfig_home_str.c_str(),
true },
1319 {
"GNC_BIN", g_getenv (
"GNC_BIN"),
false },
1320 {
"GNC_LIB", g_getenv (
"GNC_LIB"),
false },
1321 {
"GNC_CONF", g_getenv (
"GNC_CONF"),
false },
1322 {
"GNC_DATA", g_getenv (
"GNC_DATA"),
false },
1324 auto accum = [](
const auto& a,
const auto& b)
1328 return g_list_prepend (a, ep);
1330 return std::accumulate (paths.rbegin(), paths.rend(), (GList*)
nullptr, accum);
gchar * gnc_filepath_locate_data_file(const gchar *name)
Given a file name, find the file in the directories associated with this application.
gchar * gnc_build_reports_path(const gchar *dirname)
Make a path to dirname in the reports directory.
gchar * gnc_build_book_path(const gchar *filename)
Make a path to filename in the book subdirectory of the user's configuration directory.
gchar * gnc_file_path_absolute(const gchar *prefix, const gchar *relative)
Given a prefix and a relative path, return the absolute path.
gchar * gnc_build_userdata_path(const gchar *filename)
Make a path to filename in the user's gnucash data directory.
gchar * gnc_build_data_path(const gchar *filename)
Make a path to filename in the data subdirectory of the user's configuration directory.
gchar * gnc_filepath_locate_ui_file(const gchar *name)
Given a ui file name, find the file in the ui directory associated with this application.
const gchar * gnc_userdata_dir(void)
Ensure that the user's configuration directory exists and is minimally populated. ...
gchar * gnc_resolve_file_path(const gchar *filefrag)
The gnc_resolve_file_path() routine is a utility that will accept a fragmentary filename as input...
gchar * gnc_build_stdreports_path(const gchar *filename)
Make a path to filename in the standard reports directory.
gchar * gnc_build_scm_path(const gchar *filename)
Make a path to filename in the scm directory.
gchar * gnc_filepath_locate_doc_file(const gchar *name)
Given a documentation file name, find the file in the doc directory associated with this application...
gchar * gnc_build_report_path(const gchar *filename)
Make a path to filename in the report directory.
char * gnc_filepath_init(void)
Initializes the gnucash user data directory.
gchar * gnc_file_path_relative_part(const gchar *prefix, const gchar *path)
Given a prefix and a path return the relative portion of the path.
gchar * gnc_filepath_locate_pixmap(const gchar *name)
Given a pixmap/pixbuf file name, find the file in the pixmap directory associated with this applicati...
gchar * gnc_build_translog_path(const gchar *filename)
Make a path to filename in the translog subdirectory of the user's configuration directory.
GList * gnc_list_all_paths(void)
Returns a GList* of the environment variables used by GnuCash.
gchar * gnc_build_userconfig_path(const gchar *filename)
Make a path to filename in the user's configuration directory.
gchar * gnc_path_find_localized_html_file(const gchar *file_name)
Find an absolute path to a localized version of a given relative path to a html or html related file...
const gchar * gnc_userconfig_dir(void)
Return the user's config directory for gnucash.
File path resolution utility functions.