Consolidate the creation of all file names under ~/.gnucash, and also

the checks for the existence of ~/.gnucash and ~/.gnucash/books.  Add
better error messages when there is a problem.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@12023 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
David Hampton 2005-11-23 22:40:03 +00:00
parent 323ad2bb92
commit 1b206fe862
10 changed files with 174 additions and 44 deletions

View File

@ -1,3 +1,18 @@
2005-11-23 David Hampton <hampton@employees.org>
* src/import-export/qif-import/qif-guess-map.scm:
* src/scm/command-line.scm:
* src/scm/main.scm:
* src/scm/main-window.scm:
* src/scm/path.scm:
* src/engine/gnc-filepath-utils.c:
* src/engine/gnc-filepath-utils.h:
* src/engine/gw-engine-spec.scm:
* src/app-utils/gnc-exp-parser.c: Consolidate the creation of all
file names under ~/.gnucash, and also consolidate checks for the
existence of ~/.gnucash and ~/.gnucash/books. Add better error
messages when there is a problem.
2005-11-22 David Hampton <hampton@employees.org>
* src/import-export/schemas/apps_gnucash_import_generic_matcher.schemas:

View File

@ -29,6 +29,7 @@
#include "finproto.h"
#include "fin_spl_protos.h"
#include "gnc-filepath-utils.h"
#include "gnc-gkeyfile-utils.h"
#include "gnc-exp-parser.h"
#include "gnc-ui-util.h"
@ -56,7 +57,7 @@ static gboolean parser_inited = FALSE;
static gchar *
gnc_exp_parser_filname (void)
{
return g_build_filename(g_get_home_dir(), ".gnucash", "expressions-2.0", NULL);
return gnc_build_dotgnucash_path("expressions-2.0");
}
void

View File

@ -32,13 +32,18 @@
#include "config.h"
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gprintf.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <glib.h>
#include "gnc-engine.h"
#include "gnc-filepath-utils.h"
@ -304,4 +309,118 @@ xaccResolveURL (const char * pathfrag)
return (xaccResolveFilePath (pathfrag));
}
/* ====================================================================== */
static void
gnc_validate_directory (const gchar *dirname)
{
struct stat statbuf;
gint rc;
rc = stat (dirname, &statbuf);
if (rc) {
switch (errno) {
case ENOENT:
rc = mkdir (dirname, S_IRWXU); /* perms = S_IRWXU = 0700 */
if (rc) {
g_fprintf(stderr,
_("An error occurred wile creating the directory:\n"
" %s\n"
"Please correct the problem and restart gnucash\n"
"The reported error was '%s' (errno %d).\n"),
dirname, strerror(errno), errno);
exit(1);
}
stat (dirname, &statbuf);
break;
case EACCES:
g_fprintf(stderr,
_("The directory\n"
" %s\n"
"exists but cannot be accessed. This program \n"
"must have full access (read/write/execute) to \n"
"the directory in order to function properly.\n"),
dirname);
exit(1);
case ENOTDIR:
g_fprintf(stderr,
_("The path\n"
" %s\n"
"exists but it is not a directory. Please delete\n"
"the file and start gnucash again.\n"),
dirname);
exit(1);
default:
g_fprintf(stderr,
_("An unknown error occurred when validating that the\n"
" %s\n"
"directory exists and is usable. Please correct the\n"
"problem and restart gnucash. The reported error \n"
"was '%s' (errno %d)."),
dirname, strerror(errno), errno);
exit(1);
}
}
if ((statbuf.st_mode & S_IFDIR) != S_IFDIR) {
g_fprintf(stderr,
_("The path\n"
" %s\n"
"exists but it is not a directory. Please delete\n"
"the file and start gnucash again.\n"),
dirname);
exit(1);
}
if ((statbuf.st_mode & S_IRWXU) != S_IRWXU) {
g_fprintf(stderr,
_("The permissions are wrong on the directory\n"
" %s\n"
"They must be at least 'rwx' for the user.\n"),
dirname);
exit(1);
}
}
const gchar *
gnc_dotgnucash_dir (void)
{
static gchar *dotgnucash = NULL, *books_dir;
const gchar *home;
if (dotgnucash)
return dotgnucash;
home = g_get_home_dir();
if (!home) {
g_warning("Cannot find home directory. Using tmp directory instead.");
home = g_get_tmp_dir();
}
g_assert(home);
dotgnucash = g_build_filename(home, ".gnucash", (gchar *)NULL);
gnc_validate_directory(dotgnucash);
/* Since we're in code that is only executed once.... */
books_dir = g_build_filename(dotgnucash, "books", (gchar *)NULL);
gnc_validate_directory(books_dir);
g_free(books_dir);
return dotgnucash;
}
gchar *
gnc_build_dotgnucash_path (const gchar *filename)
{
return g_build_filename(gnc_dotgnucash_dir(), filename, (gchar *)NULL);
}
gchar *
gnc_build_book_path (const gchar *filename)
{
return g_build_filename(gnc_dotgnucash_dir(), "books", filename, (gchar *)NULL);
}
/* =============================== END OF FILE ========================== */

View File

@ -46,4 +46,8 @@
char * xaccResolveFilePath (const char * filefrag);
char * xaccResolveURL (const char * pathfrag);
const gchar *gnc_dotgnucash_dir (void);
gchar *gnc_build_dotgnucash_path (const gchar *filename);
gchar *gnc_build_book_path (const gchar *filename);
#endif /* GNC_FILEPATH_UTILS_H */

View File

@ -29,6 +29,7 @@
"#include <gnc-budget.h>\n"
"#include <gnc-commodity.h>\n"
"#include <gnc-engine.h>\n"
"#include <gnc-filepath-utils.h>\n"
"#include <gnc-pricedb.h>\n"
"#include <gnc-lot.h>\n"
"#include <gnc-session-scm.h>\n"
@ -2419,6 +2420,26 @@ of having a parent transaction with which one is working...")
"Convert a timepair on a certain day (localtime) to\
the timepair representing midday on that day")
;;
;; gnc-filepath-utils.h
;;
(gw:wrap-function
ws
'gnc:build-dotgnucash-path
'(<gw:mchars> caller-owned)
"gnc_build_dotgnucash_path"
'(((<gw:mchars> caller-owned) filename))
"Convert a relative path name into a full path name in the .gnucash directory")
(gw:wrap-function
ws
'gnc:build-book-path
'(<gw:mchars> caller-owned)
"gnc_build_book_path"
'(((<gw:mchars> caller-owned) filename))
"Convert a relative path name into a full path name in the .gnucash/books directory")
;;
;; gnc-lot.h
;;

View File

@ -63,15 +63,12 @@
;; (older saved prefs may not have this one)
;; - a hash of QIF stock name to gnc-commodity*
;; (older saved prefs may not have this one)
(let* ((pref-dir (build-path (getenv "HOME") ".gnucash"))
(pref-filename (build-path pref-dir "qif-accounts-map"))
(let* ((pref-filename (gnc:build-dotgnucash-path "qif-accounts-map"))
(results '()))
;; first, read the account map and category map from the
;; user's qif-accounts-map file.
(if (and (access? pref-dir F_OK)
(access? pref-dir X_OK)
(access? pref-filename R_OK))
(if (access? pref-filename R_OK)
(with-input-from-file pref-filename
(lambda ()
(let ((qif-account-list #f)
@ -178,22 +175,10 @@
(define (qif-import:save-map-prefs acct-map cat-map memo-map stock-map)
(let* ((pref-dir (build-path (getenv "HOME") ".gnucash"))
(pref-filename (build-path pref-dir "qif-accounts-map"))
(save-ok #f))
(let* ((pref-filename (gnc:build-dotgnucash-path "qif-accounts-map")))
;; does the file exist? if not, create it; in either case,
;; make sure it's a directory and we have write and execute
;; permission.
(let ((perm (access? pref-dir F_OK)))
(if (not perm)
(mkdir pref-dir))
(let ((stats (stat pref-dir)))
(if (and (eq? (stat:type stats) 'directory)
(access? pref-dir X_OK)
(access? pref-dir W_OK))
(set! save-ok #t))))
(if save-ok
(with-output-to-file pref-filename
(lambda ()
(display ";;; qif-accounts-map\n")
@ -214,7 +199,7 @@
(display ";;; map from QIF stock name to GNC commodity") (newline)
(qif-import:write-commodities stock-map)
(newline))))))
(newline)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -145,7 +145,7 @@ Each element must be a string representing a directory or a symbol \
where 'default expands to the default path, and 'current expands to \
the current value of the path.")
(let ((result (cons
(build-path (getenv "HOME") ".gnucash" "html")
(gnc:build-dotgnucash-path "html")
gnc:_install-doc-path_)))
(lambda () result))))

View File

@ -101,20 +101,10 @@ the account instead of opening a register.") #f))
(define (gnc:main-window-save-state session)
(let* ((book-url (gnc:session-get-url session))
(conf-file-name (gnc:html-encode-string book-url))
(dotgnucash-dir (build-path (getenv "HOME") ".gnucash"))
(file-dir (build-path dotgnucash-dir "books"))
(save-file? #f)
(book-path #f))
;; make sure ~/.gnucash/books is there
(set! save-file? (and (gnc:make-dir dotgnucash-dir)
(gnc:make-dir file-dir)))
(if (not save-file?) (gnc:warn (_ "Can't save window state")))
(if (and save-file? conf-file-name)
(let ((book-path (build-path (getenv "HOME") ".gnucash" "books"
conf-file-name)))
(if (conf-file-name)
(let ((book-path (gnc:build-book-path conf-file-name)))
(with-output-to-port (open-output-file book-path)
(lambda ()
(hash-fold
@ -148,7 +138,7 @@ the account instead of opening a register.") #f))
(define (gnc:main-window-book-open-handler session)
(define (try-load file-suffix)
(let ((file (build-path (getenv "HOME") ".gnucash" "books" file-suffix)))
(let ((file (gnc:build-book-path file-suffix)))
;; make sure the books directory is there
(if (access? file F_OK)
(if (not (false-if-exception (primitive-load file)))

View File

@ -61,7 +61,6 @@
(re-export string-split)
;; from path.scm
(export gnc:make-home-dir)
(export gnc:current-config-auto)
(export gnc:current-saved-reports)
(export gnc:current-saved-stylesheets)

View File

@ -35,24 +35,20 @@
#t
(false-if-exception (mkdir dir #o700))))
(define (gnc:make-home-dir)
(let ((home-dir (build-path (getenv "HOME") ".gnucash")))
(gnc:make-dir home-dir)))
(define gnc:current-config-auto
(build-path (getenv "HOME") ".gnucash" "config-2.0.auto"))
(gnc:build-dotgnucash-path "config-2.0.auto"))
(define gnc:current-saved-reports
(build-path (getenv "HOME") ".gnucash" "saved-reports-2.0"))
(gnc:build-dotgnucash-path "saved-reports-2.0"))
(define gnc:current-saved-stylesheets
(build-path (getenv "HOME") ".gnucash" "stylesheets-2.0"))
(gnc:build-dotgnucash-path "stylesheets-2.0"))
(define gnc:load-user-config-if-needed
(let ((user-config-loaded? #f))
(define (try-load-no-set file-suffix)
(let ((file (build-path (getenv "HOME") ".gnucash" file-suffix)))
(let ((file (gnc:build-dotgnucash-path file-suffix)))
(gnc:debug "trying to load " file)
(if (access? file F_OK)
(if (false-if-exception (primitive-load file))