30 #include <glib/gi18n.h> 31 #include <glib/gprintf.h> 32 #include <glib/gstdio.h> 46 #include <sys/types.h> 56 #if defined (_MSC_VER) || defined (G_OS_WIN32) 57 #include <glib/gwin32.h> 59 #define PATH_MAX MAXPATHLEN 62 #ifdef MAC_INTEGRATION 63 #include <Foundation/Foundation.h> 66 #include "gnc-locale-utils.hpp" 67 #include <boost/filesystem.hpp> 68 #include <boost/locale.hpp> 91 using codecvt = std::codecvt_utf8<wchar_t, 0x10FFFF, std::little_endian>;
92 using string = std::wstring;
95 template<
class I,
class E,
class S>
101 using string = std::string;
104 static std::locale bfs_locale(std::locale(),
new codecvt);
106 namespace bfs = boost::filesystem;
107 namespace bst = boost::system;
108 namespace bl = boost::locale;
117 check_path_return_if_valid(gchar *path)
119 if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
157 gchar *fullpath = NULL, *tmp_path = NULL;
162 g_critical(
"filefrag is NULL");
170 if (g_path_is_absolute(filefrag))
171 return g_strdup (filefrag);
174 tmp_path = g_get_current_dir();
175 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL);
177 fullpath = check_path_return_if_valid(fullpath);
178 if (fullpath != NULL)
182 tmp_path = gnc_path_get_pkgdatadir();
183 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL);
185 fullpath = check_path_return_if_valid(fullpath);
186 if (fullpath != NULL)
190 tmp_path = gnc_path_get_accountsdir();
191 fullpath = g_build_filename(tmp_path, filefrag, (gchar *)NULL);
193 fullpath = check_path_return_if_valid(fullpath);
194 if (fullpath != NULL)
199 if (g_file_test(fullpath, G_FILE_TEST_IS_REGULAR))
204 g_warning(
"create new file %s", fullpath);
212 if (p.find(prefix) == 0)
213 return g_strdup(p.substr(strlen(prefix)).c_str());
214 return g_strdup(path);
231 gnc_path_find_localized_html_file_internal (
const gchar * file_name)
233 gchar *full_path = NULL;
235 const gchar *env_doc_path = g_getenv(
"GNC_DOC_PATH");
236 const gchar *default_dirs[] =
239 gnc_path_get_pkgdocdir (),
240 gnc_path_get_pkgdatadir (),
245 if (!file_name || *file_name ==
'\0')
250 dirs = g_strsplit (env_doc_path, G_SEARCHPATH_SEPARATOR_S, -1);
252 dirs = (gchar **)default_dirs;
254 for (i = 0; dirs[i]; i++)
256 full_path = g_build_filename (dirs[i], file_name, (gchar *)NULL);
257 g_debug (
"Checking for existence of %s", full_path);
258 full_path = check_path_return_if_valid (full_path);
259 if (full_path != NULL)
303 gchar *loc_file_name = NULL;
304 gchar *full_path = NULL;
305 const gchar *
const *lang;
307 if (!file_name || *file_name ==
'\0')
311 if (g_path_is_absolute (file_name))
312 return g_strdup (file_name);
317 for (lang = g_get_language_names (); *lang; lang++)
319 loc_file_name = g_build_filename (*lang, file_name, (gchar *)NULL);
320 full_path = gnc_path_find_localized_html_file_internal (loc_file_name);
321 g_free (loc_file_name);
322 if (full_path != NULL)
329 return gnc_path_find_localized_html_file_internal (file_name);
334 static auto gnc_userdata_home = bfs::path();
335 static auto gnc_userconfig_home = bfs::path();
336 static auto build_dir = bfs::path();
341 static std::string gnc_userdata_home_str;
342 static std::string gnc_userconfig_home_str;
344 static bool dir_is_descendant (
const bfs::path& path,
const bfs::path& base)
346 auto test_path = path;
347 if (bfs::exists (path))
348 test_path = bfs::canonical (path);
349 auto test_base = base;
350 if (bfs::exists (base))
351 test_base = bfs::canonical (base);
353 auto is_descendant = (test_path.string() == test_base.string());
354 while (!test_path.empty() && !is_descendant)
356 test_path = test_path.parent_path();
357 is_descendant = (test_path.string() == test_base.string());
359 return is_descendant;
368 gnc_validate_directory (
const bfs::path &dirname)
373 auto create_dirs =
true;
374 if (build_dir.empty() || !dir_is_descendant (dirname, build_dir))
383 bfs::path home_dir(g_get_home_dir(), cvt);
384 home_dir.imbue(bfs_locale);
385 auto homedir_exists = bfs::exists(home_dir);
386 auto is_descendant = dir_is_descendant (dirname, home_dir);
387 if (!homedir_exists && is_descendant)
399 bfs::create_directories(dirname);
401 throw (bfs::filesystem_error (
402 std::string (dirname.string() +
403 " is a descendant of a non-existing home directory. As " +
405 " will never create a home directory this path can't be used"),
406 dirname, bst::error_code(bst::errc::permission_denied, bst::generic_category())));
408 auto d = bfs::directory_entry (dirname);
409 auto perms = d.status().permissions();
414 #if PLATFORM(WINDOWS) 415 auto check_perms = bfs::owner_read | bfs::owner_write;
417 auto check_perms = bfs::owner_all;
419 if ((perms & check_perms) != check_perms)
420 throw (bfs::filesystem_error(
421 std::string(
"Insufficient permissions, at least write and access permissions required: ")
422 + dirname.string(), dirname,
423 bst::error_code(bst::errc::permission_denied, bst::generic_category())));
431 copy_recursive(
const bfs::path& src,
const bfs::path& dest)
433 if (!bfs::exists(src))
437 if (src.compare(dest) == 0)
440 auto old_str = src.string();
441 auto old_len = old_str.size();
447 for(
auto direntry = bfs::recursive_directory_iterator(src);
448 direntry != bfs::recursive_directory_iterator(); ++direntry)
451 string cur_str = direntry->path().wstring();
453 string cur_str = direntry->path().string();
455 auto cur_len = cur_str.size();
456 string rel_str(cur_str, old_len, cur_len - old_len);
457 bfs::path relpath(rel_str, cvt);
458 auto newpath = bfs::absolute (relpath.relative_path(), dest);
459 newpath.imbue(bfs_locale);
460 bfs::copy(direntry->path(), newpath);
463 catch(
const bfs::filesystem_error& ex)
465 g_warning(
"An error occurred while trying to migrate the user configation from\n%s to\n%s" 467 src.string().c_str(), gnc_userdata_home_str.c_str(),
484 wchar_t path[MAX_PATH+1];
486 LPITEMIDLIST pidl = NULL;
489 hr = SHGetSpecialFolderLocation (NULL, CSIDL_APPDATA, &pidl);
492 b = SHGetPathFromIDListW (pidl, path);
493 CoTaskMemFree (pidl);
495 bfs::path retval(path, cvt);
496 retval.imbue(bfs_locale);
499 #elif defined MAC_INTEGRATION 504 NSFileManager*fm = [NSFileManager defaultManager];
505 NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
506 inDomains:NSUserDomainMask];
507 NSString *dirPath =
nullptr;
508 if ([appSupportDir count] > 0)
510 NSURL* dirUrl = [appSupportDir objectAtIndex:0];
511 dirPath = [dirUrl path];
513 return [dirPath UTF8String];
519 return g_get_user_data_dir();
530 get_userdata_home(
void)
532 auto try_tmp_dir =
true;
533 auto userdata_home = get_user_data_dir();
538 if (!userdata_home.empty())
542 gnc_validate_directory(userdata_home);
545 catch (
const bfs::filesystem_error& ex)
547 auto path_string = userdata_home.string();
548 g_warning(
"%s is not a suitable base directory for the user data. " 549 "Trying temporary directory instead.\n(Error: %s)",
550 path_string.c_str(), ex.what());
558 bfs::path newpath(g_get_tmp_dir (), cvt);
559 userdata_home = newpath / g_get_user_name ();
560 userdata_home.imbue(bfs_locale);
562 g_assert(!userdata_home.empty());
564 return userdata_home;
574 get_userconfig_home(
void)
578 #if defined (G_OS_WIN32) || defined (MAC_INTEGRATION) 579 return get_user_data_dir();
581 return g_get_user_config_dir();
585 static std::string migrate_gnc_datahome()
587 auto success =
false;
589 bfs::path old_dir(g_get_home_dir(), cvt);
590 old_dir /=
".gnucash";
592 std::stringstream migration_msg;
593 migration_msg.imbue(gnc_get_boost_locale());
596 auto full_copy = copy_recursive (old_dir, gnc_userdata_home);
605 auto failed = std::vector<std::string>{};
606 auto succeeded = std::vector<std::string>{};
610 auto oldlogpath = gnc_userdata_home /
"log.conf";
611 auto newlogpath = gnc_userconfig_home /
"log.conf";
614 if (bfs::exists (oldlogpath) && gnc_validate_directory (gnc_userconfig_home) &&
615 (oldlogpath != newlogpath))
617 bfs::rename (oldlogpath, newlogpath);
618 succeeded.emplace_back (
"log.conf");
621 catch (
const bfs::filesystem_error& ex)
623 failed.emplace_back (
"log.conf");
629 auto user_config_files = std::vector<std::string>
631 "config-2.0.user",
"config-1.8.user",
632 "config-1.6.user",
"config.user" 634 auto conf_exist_vec = std::vector<std::string> {};
635 auto renamed_config = std::string();
636 for (
auto conf_file : user_config_files)
638 auto oldconfpath = gnc_userdata_home / conf_file;
641 if (bfs::exists (oldconfpath) && gnc_validate_directory (gnc_userconfig_home))
644 if (renamed_config.empty())
647 renamed_config = conf_file +
" (" + _(
"Renamed to:") +
" config-user.scm)";
648 auto newconfpath = gnc_userconfig_home /
"config-user.scm";
649 bfs::rename (oldconfpath, newconfpath);
654 conf_exist_vec.emplace_back (conf_file);
658 bfs::remove (oldconfpath);
662 catch (
const bfs::filesystem_error& ex)
664 failed.emplace_back (conf_file);
667 if (!renamed_config.empty())
668 succeeded.emplace_back (renamed_config);
671 if (full_copy || !succeeded.empty() || !conf_exist_vec.empty() || !failed.empty())
672 migration_msg << _(
"Notice") << std::endl << std::endl;
677 << _(
"Your gnucash metadata has been migrated.") << std::endl << std::endl
679 << _(
"Old location:") <<
" " << old_dir.string() << std::endl
681 << _(
"New location:") <<
" " << gnc_userdata_home.string() << std::endl << std::endl
683 << 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.")})
688 (!succeeded.empty() || !conf_exist_vec.empty() || !failed.empty()))
689 migration_msg << std::endl << std::endl
690 << _(
"In addition:");
692 if (!succeeded.empty())
694 migration_msg << std::endl << std::endl;
696 migration_msg << bl::format (std::string{ngettext(
"The following file has been copied to {1} instead:",
697 "The following files have been copied to {1} instead:",
698 succeeded.size())}) % gnc_userconfig_home.string().c_str();
700 migration_msg << bl::format (std::string{_(
"The following file in {1} has been renamed:")})
701 % gnc_userconfig_home.string().c_str();
703 migration_msg << std::endl;
704 for (
const auto& success_file : succeeded)
705 migration_msg <<
"- " << success_file << std::endl;
707 if (!conf_exist_vec.empty())
709 migration_msg <<
"\n\n" 710 << ngettext(
"The following file has become obsolete and will be ignored:",
711 "The following files have become obsolete and will be ignored:",
712 conf_exist_vec.size())
714 for (
const auto& obs_file : conf_exist_vec)
715 migration_msg <<
"- " << obs_file << std::endl;
719 migration_msg << std::endl << std::endl
720 << bl::format (std::string{ngettext(
"The following file could not be moved to {1}:",
721 "The following files could not be moved to {1}:",
722 failed.size())}) % gnc_userconfig_home.string().c_str()
724 for (
const auto& failed_file : failed)
725 migration_msg <<
"- " << failed_file << std::endl;
728 return migration_msg.str ();
733 #if defined G_OS_WIN32 ||defined MAC_INTEGRATION 734 constexpr
auto path_package = PACKAGE_NAME;
736 constexpr
auto path_package = PROJECT_NAME;
742 gnc_file_path_init_config_home (
void)
744 auto have_valid_userconfig_home =
false;
750 auto env_build_dir = g_getenv (
"GNC_BUILDDIR");
751 bfs::path new_dir(env_build_dir ? env_build_dir :
"", cvt);
752 new_dir.imbue(bfs_locale);
753 build_dir = std::move(new_dir);
754 auto running_uninstalled = (g_getenv (
"GNC_UNINSTALLED") != NULL);
755 if (running_uninstalled && !build_dir.empty())
757 gnc_userconfig_home = build_dir /
"gnc_config_home";
760 gnc_validate_directory (gnc_userconfig_home);
761 have_valid_userconfig_home =
true;
763 catch (
const bfs::filesystem_error& ex)
765 auto path_string = gnc_userconfig_home.string();
766 g_warning(
"%s (due to run during at build time) is not a suitable directory for user configuration files. " 767 "Trying another directory instead.\n(Error: %s)",
768 path_string.c_str(), ex.what());
772 if (!have_valid_userconfig_home)
776 auto gnc_userconfig_home_env = g_getenv (
"GNC_CONFIG_HOME");
777 if (gnc_userconfig_home_env)
779 bfs::path newdir(gnc_userconfig_home_env, cvt);
780 newdir.imbue(bfs_locale);
781 gnc_userconfig_home = std::move(newdir);
784 gnc_validate_directory (gnc_userconfig_home);
785 have_valid_userconfig_home =
true;
787 catch (
const bfs::filesystem_error& ex)
789 auto path_string = gnc_userconfig_home.string();
790 g_warning(
"%s (from environment variable 'GNC_CONFIG_HOME') is not a suitable directory for user configuration files. " 791 "Trying the default instead.\n(Error: %s)",
792 path_string.c_str(), ex.what());
797 if (!have_valid_userconfig_home)
801 auto userconfig_home = get_userconfig_home();
802 gnc_userconfig_home = userconfig_home / path_package;
805 gnc_validate_directory (gnc_userconfig_home);
807 catch (
const bfs::filesystem_error& ex)
809 g_warning (
"User configuration directory doesn't exist, yet could not be created. Proceed with caution.\n" 810 "(Error: %s)", ex.what());
813 gnc_userconfig_home_str = gnc_userconfig_home.string();
821 gnc_file_path_init_data_home (
void)
824 auto gnc_userdata_home_exists =
false;
825 auto have_valid_userdata_home =
false;
831 auto env_build_dir = g_getenv (
"GNC_BUILDDIR");
832 bfs::path new_dir(env_build_dir ? env_build_dir :
"", cvt);
833 new_dir.imbue(bfs_locale);
834 build_dir = std::move(new_dir);
835 auto running_uninstalled = (g_getenv (
"GNC_UNINSTALLED") != NULL);
836 if (running_uninstalled && !build_dir.empty())
838 gnc_userdata_home = build_dir /
"gnc_data_home";
841 gnc_validate_directory (gnc_userdata_home);
842 have_valid_userdata_home =
true;
843 gnc_userdata_home_exists =
true;
845 catch (
const bfs::filesystem_error& ex)
847 auto path_string = gnc_userdata_home.string();
848 g_warning(
"%s (due to run during at build time) is not a suitable directory for user data. " 849 "Trying another directory instead.\n(Error: %s)",
850 path_string.c_str(), ex.what());
854 if (!have_valid_userdata_home)
858 auto gnc_userdata_home_env = g_getenv (
"GNC_DATA_HOME");
859 if (gnc_userdata_home_env)
861 bfs::path newdir(gnc_userdata_home_env, cvt);
862 newdir.imbue(bfs_locale);
863 gnc_userdata_home = std::move(newdir);
866 gnc_userdata_home_exists = bfs::exists (gnc_userdata_home);
867 gnc_validate_directory (gnc_userdata_home);
868 have_valid_userdata_home =
true;
870 catch (
const bfs::filesystem_error& ex)
872 auto path_string = gnc_userdata_home.string();
873 g_warning(
"%s (from environment variable 'GNC_DATA_HOME') is not a suitable directory for user data. " 874 "Trying the default instead.\n(Error: %s)",
875 path_string.c_str(), ex.what());
880 if (!have_valid_userdata_home)
884 auto userdata_home = get_userdata_home();
885 gnc_userdata_home = userdata_home / path_package;
888 gnc_userdata_home_exists = bfs::exists (gnc_userdata_home);
889 gnc_validate_directory (gnc_userdata_home);
891 catch (
const bfs::filesystem_error& ex)
893 g_warning (
"User data directory doesn't exist, yet could not be created. Proceed with caution.\n" 894 "(Error: %s)", ex.what());
897 gnc_userdata_home_str = gnc_userdata_home.string();
898 return gnc_userdata_home_exists;
912 gnc_userconfig_home = get_userconfig_home() / path_package;
913 gnc_userconfig_home_str = gnc_userconfig_home.string();
915 gnc_file_path_init_config_home ();
916 auto gnc_userdata_home_exists = gnc_file_path_init_data_home ();
920 auto migration_notice = std::string ();
921 if (!gnc_userdata_home_exists)
922 migration_notice = migrate_gnc_datahome();
927 gnc_validate_directory (gnc_userdata_home /
"books");
928 gnc_validate_directory (gnc_userdata_home /
"checks");
929 gnc_validate_directory (gnc_userdata_home /
"translog");
931 catch (
const bfs::filesystem_error& ex)
933 g_warning (
"Default user data subdirectories don't exist, yet could not be created. Proceed with caution.\n" 934 "(Error: %s)", ex.what());
937 return migration_notice.empty() ? NULL : g_strdup (migration_notice.c_str());
981 if (gnc_userdata_home.empty())
983 return g_strdup(gnc_userdata_home_str.c_str());
1002 if (gnc_userdata_home.empty())
1005 return gnc_userconfig_home_str.c_str();
1008 static const bfs::path&
1009 gnc_userdata_dir_as_path (
void)
1011 if (gnc_userdata_home.empty())
1020 return gnc_userdata_home;
1023 static const bfs::path&
1024 gnc_userconfig_dir_as_path (
void)
1026 if (gnc_userdata_home.empty())
1035 return gnc_userconfig_home;
1040 bfs::path path_relative (relative);
1041 path_relative.imbue (bfs_locale);
1042 bfs::path path_absolute;
1043 bfs::path path_head;
1045 if (prefix ==
nullptr)
1047 const gchar *doc_dir = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
1048 if (doc_dir ==
nullptr)
1051 path_head = bfs::path (doc_dir);
1053 path_head.imbue (bfs_locale);
1054 path_absolute = absolute (path_relative, path_head);
1058 bfs::path path_head (prefix);
1059 path_head.imbue (bfs_locale);
1060 path_absolute = absolute (path_relative, path_head);
1062 path_absolute.imbue (bfs_locale);
1064 return g_strdup (path_absolute.string().c_str());
1079 return g_strdup((gnc_userdata_dir_as_path() / filename).
string().c_str());
1094 return g_strdup((gnc_userconfig_dir_as_path() / filename).
string().c_str());
1101 is_invalid_char (
char c)
1103 return (c ==
'/') || ( c ==
':');
1107 gnc_build_userdata_subdir_path (
const gchar *subdir,
const gchar *filename)
1109 auto fn = std::string(filename);
1111 std::replace_if (fn.begin(), fn.end(), is_invalid_char,
'_');
1112 auto result = (gnc_userdata_dir_as_path() / subdir) / fn;
1128 auto path = gnc_build_userdata_subdir_path(
"books", filename).string();
1129 return g_strdup(path.c_str());
1144 auto path = gnc_build_userdata_subdir_path(
"translog", filename).string();
1145 return g_strdup(path.c_str());
1160 auto path = gnc_build_userdata_subdir_path(
"data", filename).string();
1161 return g_strdup(path.c_str());
1176 gchar *scmdir = gnc_path_get_scmdir ();
1177 gchar *result = g_build_filename (scmdir, filename, (gchar *)NULL);
1194 gchar *rptdir = gnc_path_get_reportdir ();
1195 gchar *result = g_build_filename (rptdir, filename, (gchar *)NULL);
1212 gchar *rptsdir = gnc_path_get_reportsdir ();
1213 gchar *result = g_build_filename (rptsdir, dirname, (gchar *)NULL);
1230 gchar *stdrptdir = gnc_path_get_stdreportsdir ();
1231 gchar *result = g_build_filename (stdrptdir, filename, (gchar *)NULL);
1237 gnc_filepath_locate_file (
const gchar *default_path,
const gchar *name)
1241 g_return_val_if_fail (name != NULL, NULL);
1243 if (g_path_is_absolute (name))
1244 fullname = g_strdup (name);
1245 else if (default_path)
1246 fullname = g_build_filename (default_path, name,
nullptr);
1250 if (!g_file_test (fullname, G_FILE_TEST_IS_REGULAR))
1252 g_warning (
"Could not locate file %s", name);
1263 gchar *pkgdatadir = gnc_path_get_pkgdatadir ();
1264 gchar *result = gnc_filepath_locate_file (pkgdatadir, name);
1265 g_free (pkgdatadir);
1272 gchar *default_path;
1274 gchar* pkgdatadir = gnc_path_get_pkgdatadir ();
1276 default_path = g_build_filename (pkgdatadir,
"pixmaps",
nullptr);
1278 fullname = gnc_filepath_locate_file (default_path, name);
1279 g_free(default_path);
1287 gchar *default_path;
1289 gchar* pkgdatadir = gnc_path_get_pkgdatadir ();
1291 default_path = g_build_filename (pkgdatadir,
"ui",
nullptr);
1293 fullname = gnc_filepath_locate_file (default_path, name);
1294 g_free(default_path);
1302 gchar *docdir = gnc_path_get_pkgdocdir ();
1303 gchar *result = gnc_filepath_locate_file (docdir, name);
1311 if (gnc_userdata_home.empty())
1314 std::vector<EnvPaths> paths
1315 { {
"GNC_USERDATA_DIR", gnc_userdata_home_str.c_str(),
true},
1316 {
"GNC_USERCONFIG_DIR", gnc_userconfig_home_str.c_str(),
true },
1317 {
"GNC_BIN", g_getenv (
"GNC_BIN"),
false },
1318 {
"GNC_LIB", g_getenv (
"GNC_LIB"),
false },
1319 {
"GNC_CONF", g_getenv (
"GNC_CONF"),
false },
1320 {
"GNC_DATA", g_getenv (
"GNC_DATA"),
false },
1322 auto accum = [](
const auto& a,
const auto& b)
1326 return g_list_prepend (a, ep);
1328 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.