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)
214 auto str = p.substr(strlen(prefix));
215 return g_strdup(str.c_str());
217 return g_strdup(path);
234 gnc_path_find_localized_html_file_internal (
const gchar * file_name)
236 gchar *full_path = NULL;
238 const gchar *env_doc_path = g_getenv(
"GNC_DOC_PATH");
239 const gchar *default_dirs[] =
242 gnc_path_get_pkgdocdir (),
243 gnc_path_get_pkgdatadir (),
248 if (!file_name || *file_name ==
'\0')
253 dirs = g_strsplit (env_doc_path, G_SEARCHPATH_SEPARATOR_S, -1);
255 dirs = (gchar **)default_dirs;
257 for (i = 0; dirs[i]; i++)
259 full_path = g_build_filename (dirs[i], file_name, (gchar *)NULL);
260 g_debug (
"Checking for existence of %s", full_path);
261 full_path = check_path_return_if_valid (full_path);
262 if (full_path != NULL)
306 gchar *loc_file_name = NULL;
307 gchar *full_path = NULL;
308 const gchar *
const *lang;
310 if (!file_name || *file_name ==
'\0')
314 if (g_path_is_absolute (file_name))
315 return g_strdup (file_name);
320 for (lang = g_get_language_names (); *lang; lang++)
322 loc_file_name = g_build_filename (*lang, file_name, (gchar *)NULL);
323 full_path = gnc_path_find_localized_html_file_internal (loc_file_name);
324 g_free (loc_file_name);
325 if (full_path != NULL)
332 return gnc_path_find_localized_html_file_internal (file_name);
337 static auto gnc_userdata_home = bfs::path();
338 static auto gnc_userconfig_home = bfs::path();
339 static auto build_dir = bfs::path();
344 static std::string gnc_userdata_home_str;
345 static std::string gnc_userconfig_home_str;
347 static bool dir_is_descendant (
const bfs::path& path,
const bfs::path& base)
349 auto test_path = path;
350 if (bfs::exists (path))
351 test_path = bfs::canonical (path);
352 auto test_base = base;
353 if (bfs::exists (base))
354 test_base = bfs::canonical (base);
356 auto is_descendant = (test_path.string() == test_base.string());
357 while (!test_path.empty() && !is_descendant)
359 test_path = test_path.parent_path();
360 is_descendant = (test_path.string() == test_base.string());
362 return is_descendant;
371 gnc_validate_directory (
const bfs::path &dirname)
376 auto create_dirs =
true;
377 if (build_dir.empty() || !dir_is_descendant (dirname, build_dir))
386 bfs::path home_dir(g_get_home_dir(), cvt);
387 home_dir.imbue(bfs_locale);
388 auto homedir_exists = bfs::exists(home_dir);
389 auto is_descendant = dir_is_descendant (dirname, home_dir);
390 if (!homedir_exists && is_descendant)
402 bfs::create_directories(dirname);
404 throw (bfs::filesystem_error (
405 std::string (dirname.string() +
406 " is a descendant of a non-existing home directory. As " +
408 " will never create a home directory this path can't be used"),
409 dirname, bst::error_code(bst::errc::permission_denied, bst::generic_category())));
411 auto d = bfs::directory_entry (dirname);
412 auto perms = d.status().permissions();
417 #if PLATFORM(WINDOWS) 418 auto check_perms = bfs::owner_read | bfs::owner_write;
420 auto check_perms = bfs::owner_all;
422 if ((perms & check_perms) != check_perms)
423 throw (bfs::filesystem_error(
424 std::string(
"Insufficient permissions, at least write and access permissions required: ")
425 + dirname.string(), dirname,
426 bst::error_code(bst::errc::permission_denied, bst::generic_category())));
434 copy_recursive(
const bfs::path& src,
const bfs::path& dest)
436 if (!bfs::exists(src))
440 if (src.compare(dest) == 0)
443 auto old_str = src.string();
444 auto old_len = old_str.size();
450 for(
auto direntry = bfs::recursive_directory_iterator(src);
451 direntry != bfs::recursive_directory_iterator(); ++direntry)
454 string cur_str = direntry->path().wstring();
456 string cur_str = direntry->path().string();
458 auto cur_len = cur_str.size();
459 string rel_str(cur_str, old_len, cur_len - old_len);
460 bfs::path relpath(rel_str, cvt);
461 auto newpath = bfs::absolute (relpath.relative_path(), dest);
462 newpath.imbue(bfs_locale);
463 bfs::copy(direntry->path(), newpath);
466 catch(
const bfs::filesystem_error& ex)
468 g_warning(
"An error occurred while trying to migrate the user configation from\n%s to\n%s" 470 src.string().c_str(), gnc_userdata_home_str.c_str(),
487 wchar_t path[MAX_PATH+1];
489 LPITEMIDLIST pidl = NULL;
492 hr = SHGetSpecialFolderLocation (NULL, CSIDL_APPDATA, &pidl);
495 b = SHGetPathFromIDListW (pidl, path);
496 CoTaskMemFree (pidl);
498 bfs::path retval(path, cvt);
499 retval.imbue(bfs_locale);
502 #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()
590 bfs::path old_dir(g_get_home_dir(), cvt);
591 old_dir /=
".gnucash";
593 std::stringstream migration_msg;
594 migration_msg.imbue(gnc_get_boost_locale());
597 auto full_copy = copy_recursive (old_dir, gnc_userdata_home);
606 auto failed = std::vector<std::string>{};
607 auto succeeded = std::vector<std::string>{};
611 auto oldlogpath = gnc_userdata_home /
"log.conf";
612 auto newlogpath = gnc_userconfig_home /
"log.conf";
615 if (bfs::exists (oldlogpath) && gnc_validate_directory (gnc_userconfig_home) &&
616 (oldlogpath != newlogpath))
618 bfs::rename (oldlogpath, newlogpath);
619 succeeded.emplace_back (
"log.conf");
622 catch (
const bfs::filesystem_error& ex)
624 failed.emplace_back (
"log.conf");
630 auto user_config_files = std::vector<std::string>
632 "config-2.0.user",
"config-1.8.user",
633 "config-1.6.user",
"config.user" 635 auto conf_exist_vec = std::vector<std::string> {};
636 auto renamed_config = std::string();
637 for (
auto conf_file : user_config_files)
639 auto oldconfpath = gnc_userdata_home / conf_file;
642 if (bfs::exists (oldconfpath) && gnc_validate_directory (gnc_userconfig_home))
645 if (renamed_config.empty())
648 renamed_config = conf_file +
" (" + _(
"Renamed to:") +
" config-user.scm)";
649 auto newconfpath = gnc_userconfig_home /
"config-user.scm";
650 bfs::rename (oldconfpath, newconfpath);
655 conf_exist_vec.emplace_back (conf_file);
659 bfs::remove (oldconfpath);
663 catch (
const bfs::filesystem_error& ex)
665 failed.emplace_back (conf_file);
668 if (!renamed_config.empty())
669 succeeded.emplace_back (renamed_config);
672 if (full_copy || !succeeded.empty() || !conf_exist_vec.empty() || !failed.empty())
673 migration_msg << _(
"Notice") << std::endl << std::endl;
678 << _(
"Your gnucash metadata has been migrated.") << std::endl << std::endl
680 << _(
"Old location:") <<
" " << old_dir.string() << std::endl
682 << _(
"New location:") <<
" " << gnc_userdata_home.string() << std::endl << std::endl
684 << 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.")})
689 (!succeeded.empty() || !conf_exist_vec.empty() || !failed.empty()))
690 migration_msg << std::endl << std::endl
691 << _(
"In addition:");
693 if (!succeeded.empty())
695 migration_msg << std::endl << std::endl;
697 migration_msg << bl::format (std::string{ngettext(
"The following file has been copied to {1} instead:",
698 "The following files have been copied to {1} instead:",
699 succeeded.size())}) % gnc_userconfig_home.string().c_str();
701 migration_msg << bl::format (std::string{_(
"The following file in {1} has been renamed:")})
702 % gnc_userconfig_home.string().c_str();
704 migration_msg << std::endl;
705 for (
const auto& success_file : succeeded)
706 migration_msg <<
"- " << success_file << std::endl;
708 if (!conf_exist_vec.empty())
710 migration_msg <<
"\n\n" 711 << ngettext(
"The following file has become obsolete and will be ignored:",
712 "The following files have become obsolete and will be ignored:",
713 conf_exist_vec.size())
715 for (
const auto& obs_file : conf_exist_vec)
716 migration_msg <<
"- " << obs_file << std::endl;
720 migration_msg << std::endl << std::endl
721 << bl::format (std::string{ngettext(
"The following file could not be moved to {1}:",
722 "The following files could not be moved to {1}:",
723 failed.size())}) % gnc_userconfig_home.string().c_str()
725 for (
const auto& failed_file : failed)
726 migration_msg <<
"- " << failed_file << std::endl;
729 return migration_msg.str ();
734 #if defined G_OS_WIN32 ||defined MAC_INTEGRATION 735 constexpr
auto path_package = PACKAGE_NAME;
737 constexpr
auto path_package = PROJECT_NAME;
743 gnc_file_path_init_config_home (
void)
745 auto have_valid_userconfig_home =
false;
751 auto env_build_dir = g_getenv (
"GNC_BUILDDIR");
752 bfs::path new_dir(env_build_dir ? env_build_dir :
"", cvt);
753 new_dir.imbue(bfs_locale);
754 build_dir = std::move(new_dir);
755 auto running_uninstalled = (g_getenv (
"GNC_UNINSTALLED") != NULL);
756 if (running_uninstalled && !build_dir.empty())
758 gnc_userconfig_home = build_dir /
"gnc_config_home";
761 gnc_validate_directory (gnc_userconfig_home);
762 have_valid_userconfig_home =
true;
764 catch (
const bfs::filesystem_error& ex)
766 auto path_string = gnc_userconfig_home.string();
767 g_warning(
"%s (due to run during at build time) is not a suitable directory for user configuration files. " 768 "Trying another directory instead.\n(Error: %s)",
769 path_string.c_str(), ex.what());
773 if (!have_valid_userconfig_home)
777 auto gnc_userconfig_home_env = g_getenv (
"GNC_CONFIG_HOME");
778 if (gnc_userconfig_home_env)
780 bfs::path newdir(gnc_userconfig_home_env, cvt);
781 newdir.imbue(bfs_locale);
782 gnc_userconfig_home = std::move(newdir);
785 gnc_validate_directory (gnc_userconfig_home);
786 have_valid_userconfig_home =
true;
788 catch (
const bfs::filesystem_error& ex)
790 auto path_string = gnc_userconfig_home.string();
791 g_warning(
"%s (from environment variable 'GNC_CONFIG_HOME') is not a suitable directory for user configuration files. " 792 "Trying the default instead.\n(Error: %s)",
793 path_string.c_str(), ex.what());
798 if (!have_valid_userconfig_home)
802 auto userconfig_home = get_userconfig_home();
803 gnc_userconfig_home = userconfig_home / path_package;
806 gnc_validate_directory (gnc_userconfig_home);
808 catch (
const bfs::filesystem_error& ex)
810 g_warning (
"User configuration directory doesn't exist, yet could not be created. Proceed with caution.\n" 811 "(Error: %s)", ex.what());
814 gnc_userconfig_home_str = gnc_userconfig_home.string();
822 gnc_file_path_init_data_home (
void)
825 auto gnc_userdata_home_exists =
false;
826 auto have_valid_userdata_home =
false;
832 auto env_build_dir = g_getenv (
"GNC_BUILDDIR");
833 bfs::path new_dir(env_build_dir ? env_build_dir :
"", cvt);
834 new_dir.imbue(bfs_locale);
835 build_dir = std::move(new_dir);
836 auto running_uninstalled = (g_getenv (
"GNC_UNINSTALLED") != NULL);
837 if (running_uninstalled && !build_dir.empty())
839 gnc_userdata_home = build_dir /
"gnc_data_home";
842 gnc_validate_directory (gnc_userdata_home);
843 have_valid_userdata_home =
true;
844 gnc_userdata_home_exists =
true;
846 catch (
const bfs::filesystem_error& ex)
848 auto path_string = gnc_userdata_home.string();
849 g_warning(
"%s (due to run during at build time) is not a suitable directory for user data. " 850 "Trying another directory instead.\n(Error: %s)",
851 path_string.c_str(), ex.what());
855 if (!have_valid_userdata_home)
859 auto gnc_userdata_home_env = g_getenv (
"GNC_DATA_HOME");
860 if (gnc_userdata_home_env)
862 bfs::path newdir(gnc_userdata_home_env, cvt);
863 newdir.imbue(bfs_locale);
864 gnc_userdata_home = std::move(newdir);
867 gnc_userdata_home_exists = bfs::exists (gnc_userdata_home);
868 gnc_validate_directory (gnc_userdata_home);
869 have_valid_userdata_home =
true;
871 catch (
const bfs::filesystem_error& ex)
873 auto path_string = gnc_userdata_home.string();
874 g_warning(
"%s (from environment variable 'GNC_DATA_HOME') is not a suitable directory for user data. " 875 "Trying the default instead.\n(Error: %s)",
876 path_string.c_str(), ex.what());
881 if (!have_valid_userdata_home)
885 auto userdata_home = get_userdata_home();
886 gnc_userdata_home = userdata_home / path_package;
889 gnc_userdata_home_exists = bfs::exists (gnc_userdata_home);
890 gnc_validate_directory (gnc_userdata_home);
892 catch (
const bfs::filesystem_error& ex)
894 g_warning (
"User data directory doesn't exist, yet could not be created. Proceed with caution.\n" 895 "(Error: %s)", ex.what());
898 gnc_userdata_home_str = gnc_userdata_home.string();
899 return gnc_userdata_home_exists;
913 gnc_userconfig_home = get_userconfig_home() / path_package;
914 gnc_userconfig_home_str = gnc_userconfig_home.string();
916 gnc_file_path_init_config_home ();
917 auto gnc_userdata_home_exists = gnc_file_path_init_data_home ();
921 auto migration_notice = std::string ();
922 if (!gnc_userdata_home_exists)
923 migration_notice = migrate_gnc_datahome();
928 gnc_validate_directory (gnc_userdata_home /
"books");
929 gnc_validate_directory (gnc_userdata_home /
"checks");
930 gnc_validate_directory (gnc_userdata_home /
"translog");
932 catch (
const bfs::filesystem_error& ex)
934 g_warning (
"Default user data subdirectories don't exist, yet could not be created. Proceed with caution.\n" 935 "(Error: %s)", ex.what());
938 return migration_notice.empty() ? NULL : g_strdup (migration_notice.c_str());
982 if (gnc_userdata_home.empty())
984 return g_strdup(gnc_userdata_home_str.c_str());
1003 if (gnc_userdata_home.empty())
1006 return gnc_userconfig_home_str.c_str();
1009 static const bfs::path&
1010 gnc_userdata_dir_as_path (
void)
1012 if (gnc_userdata_home.empty())
1021 return gnc_userdata_home;
1024 static const bfs::path&
1025 gnc_userconfig_dir_as_path (
void)
1027 if (gnc_userdata_home.empty())
1036 return gnc_userconfig_home;
1041 bfs::path path_relative (relative);
1042 path_relative.imbue (bfs_locale);
1043 bfs::path path_absolute;
1044 bfs::path path_head;
1046 if (prefix ==
nullptr)
1048 const gchar *doc_dir = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
1049 if (doc_dir ==
nullptr)
1052 path_head = bfs::path (doc_dir);
1054 path_head.imbue (bfs_locale);
1055 path_absolute = absolute (path_relative, path_head);
1059 bfs::path path_head (prefix);
1060 path_head.imbue (bfs_locale);
1061 path_absolute = absolute (path_relative, path_head);
1063 path_absolute.imbue (bfs_locale);
1065 return g_strdup (path_absolute.string().c_str());
1080 return g_strdup((gnc_userdata_dir_as_path() / filename).
string().c_str());
1095 return g_strdup((gnc_userconfig_dir_as_path() / filename).
string().c_str());
1102 is_invalid_char (
char c)
1104 return (c ==
'/') || ( c ==
':');
1108 gnc_build_userdata_subdir_path (
const gchar *subdir,
const gchar *filename)
1110 auto fn = std::string(filename);
1112 std::replace_if (fn.begin(), fn.end(), is_invalid_char,
'_');
1113 auto result = (gnc_userdata_dir_as_path() / subdir) / fn;
1129 auto path = gnc_build_userdata_subdir_path(
"books", filename).string();
1130 return g_strdup(path.c_str());
1145 auto path = gnc_build_userdata_subdir_path(
"translog", filename).string();
1146 return g_strdup(path.c_str());
1161 auto path = gnc_build_userdata_subdir_path(
"data", filename).string();
1162 return g_strdup(path.c_str());
1177 gchar *scmdir = gnc_path_get_scmdir ();
1178 gchar *result = g_build_filename (scmdir, filename, (gchar *)NULL);
1195 gchar *rptdir = gnc_path_get_reportdir ();
1196 gchar *result = g_build_filename (rptdir, filename, (gchar *)NULL);
1213 gchar *rptsdir = gnc_path_get_reportsdir ();
1214 gchar *result = g_build_filename (rptsdir, dirname, (gchar *)NULL);
1231 gchar *stdrptdir = gnc_path_get_stdreportsdir ();
1232 gchar *result = g_build_filename (stdrptdir, filename, (gchar *)NULL);
1238 gnc_filepath_locate_file (
const gchar *default_path,
const gchar *name)
1242 g_return_val_if_fail (name != NULL, NULL);
1244 if (g_path_is_absolute (name))
1245 fullname = g_strdup (name);
1246 else if (default_path)
1247 fullname = g_build_filename (default_path, name,
nullptr);
1251 if (!g_file_test (fullname, G_FILE_TEST_IS_REGULAR))
1253 g_warning (
"Could not locate file %s", name);
1264 gchar *pkgdatadir = gnc_path_get_pkgdatadir ();
1265 gchar *result = gnc_filepath_locate_file (pkgdatadir, name);
1266 g_free (pkgdatadir);
1273 gchar *default_path;
1275 gchar* pkgdatadir = gnc_path_get_pkgdatadir ();
1277 default_path = g_build_filename (pkgdatadir,
"pixmaps",
nullptr);
1279 fullname = gnc_filepath_locate_file (default_path, name);
1280 g_free(default_path);
1288 gchar *default_path;
1290 gchar* pkgdatadir = gnc_path_get_pkgdatadir ();
1292 default_path = g_build_filename (pkgdatadir,
"ui",
nullptr);
1294 fullname = gnc_filepath_locate_file (default_path, name);
1295 g_free(default_path);
1303 gchar *docdir = gnc_path_get_pkgdocdir ();
1304 gchar *result = gnc_filepath_locate_file (docdir, name);
1309 std::vector<EnvPaths>
1310 gnc_list_all_paths ()
1312 if (gnc_userdata_home.empty())
1316 {
"GNC_USERDATA_DIR", gnc_userdata_home_str.c_str(),
true},
1317 {
"GNC_USERCONFIG_DIR", gnc_userconfig_home_str.c_str(),
true },
1318 {
"GNC_BIN", g_getenv (
"GNC_BIN"),
false },
1319 {
"GNC_LIB", g_getenv (
"GNC_LIB"),
false },
1320 {
"GNC_CONF", g_getenv (
"GNC_CONF"),
false },
1321 {
"GNC_DATA", g_getenv (
"GNC_DATA"),
false },
1325 static const std::regex
1326 backup_regex (
".*[.](?:xac|gnucash)[.][0-9]{14}[.](?:xac|gnucash)$");
1328 gboolean gnc_filename_is_backup (
const char *filename)
1330 return std::regex_match (filename, backup_regex);
1333 static const std::regex
1334 datafile_regex (
".*[.](?:xac|gnucash)$");
1336 gboolean gnc_filename_is_datafile (
const char *filename)
1338 return !gnc_filename_is_backup (filename) &&
1339 std::regex_match (filename, datafile_regex);
1343 gnc_open_filestream(
const char* path)
1345 bfs::path bfs_path(path, cvt);
1346 bfs_path.imbue(bfs_locale);
1347 return std::ofstream(bfs_path.c_str());
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.
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.