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;
491 hr = SHGetSpecialFolderLocation (NULL, CSIDL_APPDATA, &pidl);
494 [[maybe_unused]]
auto b = SHGetPathFromIDListW (pidl, path);
495 CoTaskMemFree (pidl);
497 bfs::path retval(path, cvt);
498 retval.imbue(bfs_locale);
501 #elif defined MAC_INTEGRATION 505 NSFileManager*fm = [NSFileManager defaultManager];
506 NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
507 inDomains:NSUserDomainMask];
508 NSString *dirPath =
nullptr;
509 if ([appSupportDir count] > 0)
511 NSURL* dirUrl = [appSupportDir objectAtIndex:0];
512 dirPath = [dirUrl path];
514 return [dirPath UTF8String];
520 return g_get_user_data_dir();
531 get_userdata_home(
void)
533 auto try_tmp_dir =
true;
534 auto userdata_home = get_user_data_dir();
539 if (!userdata_home.empty())
543 gnc_validate_directory(userdata_home);
546 catch (
const bfs::filesystem_error& ex)
548 auto path_string = userdata_home.string();
549 g_warning(
"%s is not a suitable base directory for the user data. " 550 "Trying temporary directory instead.\n(Error: %s)",
551 path_string.c_str(), ex.what());
559 bfs::path newpath(g_get_tmp_dir (), cvt);
560 userdata_home = newpath / g_get_user_name ();
561 userdata_home.imbue(bfs_locale);
563 g_assert(!userdata_home.empty());
565 return userdata_home;
575 get_userconfig_home(
void)
579 #if defined (G_OS_WIN32) || defined (MAC_INTEGRATION) 580 return get_user_data_dir();
582 return g_get_user_config_dir();
586 static std::string migrate_gnc_datahome()
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);
1308 std::vector<EnvPaths>
1309 gnc_list_all_paths ()
1311 if (gnc_userdata_home.empty())
1315 {
"GNC_DATA_HOME", gnc_userdata_home_str.c_str(),
true},
1316 {
"GNC_CONFIG_HOME", 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 },
1324 static const std::regex
1325 backup_regex (
".*[.](?:xac|gnucash)[.][0-9]{14}[.](?:xac|gnucash)$");
1327 gboolean gnc_filename_is_backup (
const char *filename)
1329 return std::regex_match (filename, backup_regex);
1332 static const std::regex
1333 datafile_regex (
".*[.](?:xac|gnucash)$");
1335 gboolean gnc_filename_is_datafile (
const char *filename)
1337 return !gnc_filename_is_backup (filename) &&
1338 std::regex_match (filename, datafile_regex);
1342 gnc_open_filestream(
const char* path)
1344 bfs::path bfs_path(path, cvt);
1345 bfs_path.imbue(bfs_locale);
1346 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.