mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Allow the user to open a file if the lock wasn't obtained
after going through a dialog. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2962 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
7842e38587
commit
ce05f4893d
227
src/FileDialog.c
227
src/FileDialog.c
@ -37,78 +37,86 @@
|
||||
#include "file-history.h"
|
||||
|
||||
/* This static indicates the debugging module that this .o belongs to. */
|
||||
// static short module = MOD_GUI;
|
||||
/* static short module = MOD_GUI; */
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
static Session *current_session = NULL;
|
||||
static AccountGroup *topgroup = NULL; /* the current top of the hierarchy */
|
||||
|
||||
/********************************************************************\
|
||||
* fileMenubarCB -- handles file menubar choices *
|
||||
\********************************************************************/
|
||||
|
||||
#define SHOW_IO_ERR_MSG(io_error) { \
|
||||
switch (io_error) { \
|
||||
case ERR_FILEIO_NO_ERROR: \
|
||||
break; \
|
||||
case ERR_FILEIO_FILE_NOT_FOUND: \
|
||||
sprintf (buf, FILE_NOT_FOUND_MSG, newfile); \
|
||||
gnc_error_dialog (buf); \
|
||||
uh_oh = 1; \
|
||||
break; \
|
||||
case ERR_FILEIO_FILE_EMPTY: \
|
||||
sprintf (buf, FILE_EMPTY_MSG, newfile); \
|
||||
gnc_error_dialog (buf); \
|
||||
uh_oh = 1; \
|
||||
break; \
|
||||
case ERR_FILEIO_FILE_TOO_NEW: \
|
||||
gnc_error_dialog ( FILE_TOO_NEW_MSG); \
|
||||
uh_oh = 1; \
|
||||
break; \
|
||||
case ERR_FILEIO_FILE_TOO_OLD: \
|
||||
if (!gnc_verify_dialog( FILE_TOO_OLD_MSG, TRUE )) { \
|
||||
xaccFreeAccountGroup (newgrp); \
|
||||
newgrp = NULL; \
|
||||
uh_oh = 1; \
|
||||
} \
|
||||
break; \
|
||||
case ERR_FILEIO_FILE_BAD_READ: \
|
||||
if (!gnc_verify_dialog( FILE_BAD_READ_MSG, TRUE )) { \
|
||||
xaccFreeAccountGroup (newgrp); \
|
||||
newgrp = NULL; \
|
||||
uh_oh = 1; \
|
||||
} \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
/* ======================================================== */
|
||||
|
||||
static gboolean
|
||||
show_file_error (int io_error, char *newfile)
|
||||
{
|
||||
gboolean uh_oh = FALSE;
|
||||
char *buf = NULL;
|
||||
|
||||
switch (io_error)
|
||||
{
|
||||
case ERR_FILEIO_NO_ERROR:
|
||||
break;
|
||||
case ERR_FILEIO_FILE_NOT_FOUND:
|
||||
buf = g_strdup_printf (FILE_NOT_FOUND_MSG, newfile);
|
||||
gnc_error_dialog (buf);
|
||||
uh_oh = TRUE;
|
||||
break;
|
||||
case ERR_FILEIO_FILE_EMPTY:
|
||||
buf = g_strdup_printf (FILE_EMPTY_MSG, newfile);
|
||||
gnc_error_dialog (buf);
|
||||
uh_oh = TRUE;
|
||||
break;
|
||||
case ERR_FILEIO_FILE_TOO_NEW:
|
||||
gnc_error_dialog (FILE_TOO_NEW_MSG);
|
||||
uh_oh = TRUE;
|
||||
break;
|
||||
case ERR_FILEIO_FILE_TOO_OLD:
|
||||
if (!gnc_verify_dialog (FILE_TOO_OLD_MSG, TRUE))
|
||||
uh_oh = TRUE;
|
||||
break;
|
||||
case ERR_FILEIO_FILE_BAD_READ:
|
||||
if (!gnc_verify_dialog (FILE_BAD_READ_MSG, TRUE))
|
||||
uh_oh = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (buf);
|
||||
|
||||
return uh_oh;
|
||||
}
|
||||
|
||||
|
||||
#define SHOW_LOCK_ERR_MSG(session) \
|
||||
{ \
|
||||
int norr = xaccSessionGetError (session); \
|
||||
if (ETXTBSY == norr) \
|
||||
{ \
|
||||
sprintf (buf, FMB_LOCKED_MSG, newfile); \
|
||||
gnc_error_dialog (buf); \
|
||||
uh_oh = 1; \
|
||||
} \
|
||||
else \
|
||||
if (ERANGE == norr) \
|
||||
{ \
|
||||
sprintf (buf, FILE_NOT_FOUND_MSG, newfile); \
|
||||
gnc_error_dialog (buf); \
|
||||
uh_oh = 1; \
|
||||
} \
|
||||
else \
|
||||
if (norr) \
|
||||
{ \
|
||||
sprintf (buf, FMB_INVALID_MSG, newfile); \
|
||||
gnc_error_dialog (buf); \
|
||||
uh_oh = 1; \
|
||||
} \
|
||||
} \
|
||||
/* ======================================================== */
|
||||
|
||||
static gboolean
|
||||
show_session_error(Session *session, char *newfile)
|
||||
{
|
||||
int norr = xaccSessionGetError (session);
|
||||
gboolean uh_oh = FALSE;
|
||||
char *buf = NULL;
|
||||
|
||||
if (ETXTBSY == norr)
|
||||
{
|
||||
uh_oh = TRUE;
|
||||
}
|
||||
else if (ERANGE == norr)
|
||||
{
|
||||
buf = g_strdup_printf (FILE_NOT_FOUND_MSG, newfile);
|
||||
gnc_error_dialog (buf);
|
||||
uh_oh = TRUE;
|
||||
}
|
||||
else if (norr)
|
||||
{
|
||||
buf = (FMB_INVALID_MSG, newfile);
|
||||
gnc_error_dialog (buf);
|
||||
uh_oh = TRUE;
|
||||
}
|
||||
|
||||
g_free(buf);
|
||||
|
||||
return uh_oh;
|
||||
}
|
||||
|
||||
/* ======================================================== */
|
||||
|
||||
@ -191,6 +199,29 @@ gncFileQuerySave (void)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ======================================================== */
|
||||
|
||||
static gboolean
|
||||
gncLockFailHandler (const char *file)
|
||||
{
|
||||
const char *format = _("Gnucash could not obtain the lock for\n"
|
||||
" %s.\n"
|
||||
"That file may be in use by another user,\n"
|
||||
"in which case you should not open the file.\n"
|
||||
"\nDo you want to proceed with opening the file?");
|
||||
char *message;
|
||||
gboolean result;
|
||||
|
||||
if (file == NULL)
|
||||
return FALSE;
|
||||
|
||||
message = g_strdup_printf (format, file);
|
||||
result = gnc_verify_dialog (message, FALSE);
|
||||
g_free (message);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ======================================================== */
|
||||
/* private utilities for file open; done in two stages */
|
||||
|
||||
@ -199,16 +230,17 @@ gncPostFileOpen (const char * filename)
|
||||
{
|
||||
Session *newsess;
|
||||
AccountGroup *oldgrp;
|
||||
int io_error, uh_oh=0;
|
||||
char buf[BUFSIZE];
|
||||
gboolean uh_oh = FALSE;
|
||||
int io_error;
|
||||
AccountGroup *newgrp;
|
||||
char * newfile;
|
||||
|
||||
if (!filename) return;
|
||||
newfile = xaccResolveFilePath (filename);
|
||||
if (!newfile) {
|
||||
sprintf (buf, FILE_NOT_FOUND_MSG, filename);
|
||||
char *buf = g_strdup_printf (FILE_NOT_FOUND_MSG, filename);
|
||||
gnc_error_dialog (buf);
|
||||
g_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -227,26 +259,32 @@ gncPostFileOpen (const char * filename)
|
||||
* switchover is not something we want to keep in a journal. */
|
||||
gnc_set_busy_cursor(NULL);
|
||||
xaccLogDisable();
|
||||
newgrp = xaccSessionBeginFile (newsess, newfile);
|
||||
newgrp = xaccSessionBeginFile (newsess, newfile, gncLockFailHandler);
|
||||
xaccLogEnable();
|
||||
gnc_unset_busy_cursor(NULL);
|
||||
|
||||
/* check for session errors, put up appropriate dialog */
|
||||
SHOW_LOCK_ERR_MSG (newsess);
|
||||
uh_oh = show_session_error (newsess, newfile);
|
||||
|
||||
if (!uh_oh)
|
||||
{
|
||||
/* check for i/o error, put up appropriate error message */
|
||||
io_error = xaccGetFileIOError();
|
||||
SHOW_IO_ERR_MSG(io_error);
|
||||
uh_oh = show_file_error (io_error, newfile);
|
||||
if (uh_oh)
|
||||
{
|
||||
xaccFreeAccountGroup (newgrp);
|
||||
newgrp = NULL;
|
||||
}
|
||||
|
||||
/* Umm, came up empty-handed, i.e. the file was not found. */
|
||||
/* This is almost certainly not what the user wanted. */
|
||||
if (!uh_oh && !newgrp && !io_error)
|
||||
{
|
||||
sprintf (buf, FILE_NOT_FOUND_MSG, newfile);
|
||||
gnc_error_dialog ( buf);
|
||||
uh_oh = 1;
|
||||
char *buf = g_strdup_printf (FILE_NOT_FOUND_MSG, newfile);
|
||||
gnc_error_dialog (buf);
|
||||
g_free (buf);
|
||||
uh_oh = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,9 +296,9 @@ gncPostFileOpen (const char * filename)
|
||||
|
||||
/* well, no matter what, I think its a good idea to have
|
||||
* a topgroup around. For example, early in the gnucash startup
|
||||
* sequence, the user opens a file ... if this open fails for any
|
||||
* sequence, the user opens a file; if this open fails for any
|
||||
* reason, we don't want to leave them high & dry without a topgroup,
|
||||
* because if user continues, then bad things will happen ...
|
||||
* because if the user continues, then bad things will happen.
|
||||
*/
|
||||
if (NULL == topgroup)
|
||||
{
|
||||
@ -343,7 +381,6 @@ gncFileSave (void)
|
||||
{
|
||||
AccountGroup *newgrp = NULL;
|
||||
char * newfile;
|
||||
char buf[BUFSIZE];
|
||||
int io_error, norr, uh_oh = 0;
|
||||
|
||||
/* hack alert -- Somehow make sure all in-progress edits get committed! */
|
||||
@ -392,7 +429,13 @@ gncFileSave (void)
|
||||
io_error = xaccGetFileIOError();
|
||||
newfile = xaccSessionGetFilePath(current_session);
|
||||
gnc_history_add_file(newfile);
|
||||
SHOW_IO_ERR_MSG(io_error);
|
||||
|
||||
uh_oh = show_file_error (io_error, newfile);
|
||||
if (uh_oh)
|
||||
{
|
||||
xaccFreeAccountGroup (newgrp);
|
||||
newgrp = NULL;
|
||||
}
|
||||
|
||||
/* going down -- abandon ship */
|
||||
if (uh_oh) return;
|
||||
@ -411,8 +454,8 @@ gncFileSaveAs (void)
|
||||
char *newfile;
|
||||
AccountGroup *newgrp;
|
||||
char * oldfile;
|
||||
char buf[BUFSIZE];
|
||||
int io_error, uh_oh = 0;
|
||||
int io_error;
|
||||
gboolean uh_oh = FALSE;
|
||||
|
||||
filename = fileBox(SAVE_STR, "*.gnc");
|
||||
if (!filename) return;
|
||||
@ -424,8 +467,9 @@ gncFileSaveAs (void)
|
||||
*/
|
||||
newfile = xaccResolveFilePath (filename);
|
||||
if (!newfile) {
|
||||
sprintf (buf, FILE_NOT_FOUND_MSG, filename);
|
||||
char *buf = g_strdup_printf (FILE_NOT_FOUND_MSG, filename);
|
||||
gnc_error_dialog (buf);
|
||||
g_free (buf);
|
||||
return;
|
||||
}
|
||||
oldfile = xaccSessionGetFilePath (current_session);
|
||||
@ -449,17 +493,22 @@ gncFileSaveAs (void)
|
||||
* edit; the mass deletetion of accounts and transactions during
|
||||
* switchover is not something we want to keep in a journal. */
|
||||
xaccLogDisable();
|
||||
newgrp = xaccSessionBeginFile (newsess, newfile);
|
||||
newgrp = xaccSessionBeginFile (newsess, newfile, gncLockFailHandler);
|
||||
xaccLogEnable();
|
||||
|
||||
/* check for session errors (e.g. file locked by another user) */
|
||||
SHOW_LOCK_ERR_MSG (newsess);
|
||||
uh_oh = show_session_error (newsess, newfile);
|
||||
|
||||
if (!uh_oh)
|
||||
{
|
||||
/* check for i/o error, put up appropriate error message */
|
||||
io_error = xaccGetFileIOError();
|
||||
SHOW_IO_ERR_MSG(io_error);
|
||||
uh_oh = show_file_error (io_error, newfile);
|
||||
if (uh_oh)
|
||||
{
|
||||
xaccFreeAccountGroup (newgrp);
|
||||
newgrp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* going down -- abandon ship */
|
||||
@ -496,10 +545,15 @@ gncFileSaveAs (void)
|
||||
if (newgrp)
|
||||
{
|
||||
char *tmpmsg;
|
||||
tmpmsg = alloca (strlen (FMB_EEXIST_MSG) + strlen (newfile));
|
||||
sprintf (tmpmsg, FMB_EEXIST_MSG, newfile);
|
||||
gboolean result;
|
||||
|
||||
tmpmsg = g_strdup_printf (FMB_EEXIST_MSG, newfile);
|
||||
result = gnc_verify_dialog (tmpmsg, FALSE);
|
||||
g_free (tmpmsg);
|
||||
|
||||
/* if user says cancel, we should break out */
|
||||
if (! gnc_verify_dialog (tmpmsg, FALSE)) return;
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
/* Whoa-ok. Blow away the previous file.
|
||||
* Do not disable logging ... we want to capture the
|
||||
@ -537,7 +591,6 @@ gncFileQuit (void)
|
||||
xaccSessionEnd (current_session);
|
||||
xaccSessionDestroy (current_session);
|
||||
current_session = NULL;
|
||||
// xaccGroupWindowDestroy (grp);
|
||||
xaccFreeAccountGroup (grp);
|
||||
topgroup = NULL;
|
||||
}
|
||||
|
@ -1,15 +1,3 @@
|
||||
/*
|
||||
* FILE:
|
||||
* Session.c
|
||||
*
|
||||
* FUNCTION:
|
||||
* Provide wrappers for initiating/concluding a file-editing session.
|
||||
*
|
||||
* HISTORY:
|
||||
* Created by Linas Vepstas December 1998
|
||||
* Copyright (c) 1998-2000 Linas Vepstas
|
||||
*/
|
||||
|
||||
/********************************************************************\
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
@ -29,6 +17,18 @@
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
\********************************************************************/
|
||||
|
||||
/*
|
||||
* FILE:
|
||||
* Session.c
|
||||
*
|
||||
* FUNCTION:
|
||||
* Provide wrappers for initiating/concluding a file-editing session.
|
||||
*
|
||||
* HISTORY:
|
||||
* Created by Linas Vepstas December 1998
|
||||
* Copyright (c) 1998-2000 Linas Vepstas
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
@ -81,7 +81,7 @@ Session *
|
||||
xaccMallocSession (void)
|
||||
{
|
||||
Session *sess;
|
||||
sess = (Session *) malloc (sizeof (Session));
|
||||
sess = g_new(Session, 1);
|
||||
|
||||
xaccInitSession (sess);
|
||||
return sess;
|
||||
@ -179,7 +179,7 @@ xaccSessionBegin (Session *sess, const char * sid)
|
||||
}
|
||||
|
||||
/* add 5 to space past 'file:' */
|
||||
retval = xaccSessionBeginFile (sess, sid+5);
|
||||
retval = xaccSessionBeginFile (sess, sid+5, NULL);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -217,12 +217,79 @@ extern Backend * pgendNew (void);
|
||||
|
||||
/* ============================================================== */
|
||||
|
||||
static gboolean
|
||||
xaccSessionGetFileLock (Session *sess)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char pathbuf[PATH_MAX];
|
||||
char *path = NULL;
|
||||
int rc;
|
||||
|
||||
rc = stat (sess->lockfile, &statbuf);
|
||||
if (!rc) {
|
||||
/* oops .. file is all locked up .. */
|
||||
sess->errtype = ETXTBSY;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sess->lockfd = open (sess->lockfile, O_RDWR | O_CREAT | O_EXCL , 0);
|
||||
if (0 > sess->lockfd) {
|
||||
/* oops .. file is all locked up .. */
|
||||
sess->errtype = ETXTBSY;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* OK, now work around some NFS atomic lock race condition
|
||||
* mumbo-jumbo. We do this by linking a unique file, and
|
||||
* then examing the link count. At least that's what the
|
||||
* NFS programmers guide suggests.
|
||||
* Note: the "unique filename" must be unique for the
|
||||
* triplet filename-host-process, otherwise accidental
|
||||
* aliases can occur.
|
||||
*/
|
||||
|
||||
/* apparently, even this code may not work for some NFS
|
||||
* implementations. In the long run, I am told that
|
||||
* ftp.debian.org
|
||||
* /pub/debian/dists/unstable/main/source/libs/liblockfile_0.1-6.tar.gz
|
||||
* provides a better long-term solution.
|
||||
*/
|
||||
|
||||
strcpy (pathbuf, sess->lockfile);
|
||||
path = strrchr (pathbuf, '.');
|
||||
sprintf (path, ".%lx.%d.LNK", gethostid(), getpid());
|
||||
link (sess->lockfile, pathbuf);
|
||||
rc = stat (sess->lockfile, &statbuf);
|
||||
if (rc) {
|
||||
/* oops .. stat failed! This can't happen! */
|
||||
sess->errtype = ETXTBSY;
|
||||
unlink (pathbuf);
|
||||
close (sess->lockfd);
|
||||
unlink (sess->lockfile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (2 != statbuf.st_nlink) {
|
||||
/* oops .. stat failed! This can't happen! */
|
||||
sess->errtype = ETXTBSY;
|
||||
unlink (pathbuf);
|
||||
close (sess->lockfd);
|
||||
unlink (sess->lockfile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sess->linkfile = g_strdup (pathbuf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ============================================================== */
|
||||
|
||||
AccountGroup *
|
||||
xaccSessionBeginFile (Session *sess, const char * filefrag)
|
||||
xaccSessionBeginFile (Session *sess, const char * filefrag,
|
||||
SessionLockFailHandler handler)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char pathbuf[PATH_MAX];
|
||||
char *path = NULL;
|
||||
int rc;
|
||||
|
||||
if (!sess) return NULL;
|
||||
@ -252,87 +319,27 @@ xaccSessionBeginFile (Session *sess, const char * filefrag)
|
||||
}
|
||||
|
||||
/* Store the sessionid URL also ... */
|
||||
strcpy (pathbuf, "file:");
|
||||
strcat (pathbuf, filefrag);
|
||||
sess->sessionid = strdup (pathbuf);
|
||||
sess->sessionid = g_strconcat ("file:", filefrag, NULL);
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
/* We should now have a fully resolved path name.
|
||||
* Lets see if we can get a lock on it.
|
||||
*/
|
||||
* Lets see if we can get a lock on it. */
|
||||
|
||||
sess->lockfile = malloc (strlen (sess->fullpath) + 5);
|
||||
strcpy (sess->lockfile, sess->fullpath);
|
||||
strcat (sess->lockfile, ".LCK");
|
||||
|
||||
rc = stat (sess->lockfile, &statbuf);
|
||||
if (!rc) {
|
||||
/* oops .. file is all locked up .. */
|
||||
sess->errtype = ETXTBSY;
|
||||
free (sess->sessionid); sess->sessionid = NULL;
|
||||
free (sess->fullpath); sess->fullpath = NULL;
|
||||
free (sess->lockfile); sess->lockfile = NULL;
|
||||
return NULL;
|
||||
}
|
||||
sess->lockfd = open (sess->lockfile, O_RDWR | O_CREAT | O_EXCL , 0);
|
||||
if (0 > sess->lockfd) {
|
||||
/* oops .. file is all locked up .. */
|
||||
sess->errtype = ETXTBSY;
|
||||
free (sess->sessionid); sess->sessionid = NULL;
|
||||
free (sess->fullpath); sess->fullpath = NULL;
|
||||
free (sess->lockfile); sess->lockfile = NULL;
|
||||
return NULL;
|
||||
}
|
||||
sess->lockfile = g_strconcat(sess->fullpath, ".LCK", NULL);
|
||||
|
||||
/* OK, now work around some NFS atomic lock race condition
|
||||
* mumbo-jumbo. We do this by linking a unique file, and
|
||||
* then examing the link count. At least that's what the
|
||||
* NFS programmers guide suggests.
|
||||
* Note: the "unique filename" must be unique for the
|
||||
* triplet filename-host-process, otherwise accidental
|
||||
* aliases can occur.
|
||||
*/
|
||||
/* appearently, even this code may not work for some NFS
|
||||
* implementations. In the long run, I am told that
|
||||
* ftp.debian.org
|
||||
* /pub/debian/dists/unstable/main/source/libs/liblockfile_0.1-6.tar.gz
|
||||
* provides a better long-term solution.
|
||||
*/
|
||||
strcpy (pathbuf, sess->lockfile);
|
||||
path = strrchr (pathbuf, '.');
|
||||
sprintf (path, ".%lx.%d.LNK", gethostid(), getpid());
|
||||
link (sess->lockfile, pathbuf);
|
||||
rc = stat (sess->lockfile, &statbuf);
|
||||
if (rc) {
|
||||
/* oops .. stat failed! This can't happen! */
|
||||
sess->errtype = ETXTBSY;
|
||||
unlink (pathbuf);
|
||||
close (sess->lockfd);
|
||||
unlink (sess->lockfile);
|
||||
free (sess->sessionid); sess->sessionid = NULL;
|
||||
free (sess->fullpath); sess->fullpath = NULL;
|
||||
free (sess->lockfile); sess->lockfile = NULL;
|
||||
return NULL;
|
||||
if (!xaccSessionGetFileLock (sess)) {
|
||||
if (!handler || !handler (sess->fullpath)) {
|
||||
g_free (sess->sessionid); sess->sessionid = NULL;
|
||||
g_free (sess->fullpath); sess->fullpath = NULL;
|
||||
g_free (sess->lockfile); sess->lockfile = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (2 != statbuf.st_nlink) {
|
||||
/* oops .. stat failed! This can't happen! */
|
||||
sess->errtype = ETXTBSY;
|
||||
unlink (pathbuf);
|
||||
close (sess->lockfd);
|
||||
unlink (sess->lockfile);
|
||||
free (sess->sessionid); sess->sessionid = NULL;
|
||||
free (sess->fullpath); sess->fullpath = NULL;
|
||||
free (sess->lockfile); sess->lockfile = NULL;
|
||||
return NULL;
|
||||
}
|
||||
sess->linkfile = strdup (pathbuf);
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
/* OK, if we've gotten this far, then we've succesfully obtained
|
||||
* an atomic lock on the file. Go read the file contents ...
|
||||
* well, read it only if it exists ...
|
||||
*/
|
||||
* an atomic lock on the file. Go read the file contents if it
|
||||
* exists. */
|
||||
|
||||
sess->errtype = 0;
|
||||
sess->topgroup = NULL;
|
||||
@ -387,13 +394,20 @@ xaccSessionEnd (Session *sess)
|
||||
if (sess->linkfile) unlink (sess->linkfile);
|
||||
if (0 < sess->lockfd) close (sess->lockfd);
|
||||
if (sess->lockfile) unlink (sess->lockfile);
|
||||
if (sess->sessionid) free (sess->sessionid); sess->sessionid = NULL;
|
||||
if (sess->fullpath) free (sess->fullpath); sess->fullpath = NULL;
|
||||
if (sess->lockfile) free (sess->lockfile); sess->lockfile = NULL;
|
||||
if (sess->linkfile) free (sess->linkfile); sess->linkfile = NULL;
|
||||
sess->topgroup = NULL;
|
||||
|
||||
return;
|
||||
g_free (sess->sessionid);
|
||||
sess->sessionid = NULL;
|
||||
|
||||
g_free (sess->fullpath);
|
||||
sess->fullpath = NULL;
|
||||
|
||||
g_free (sess->lockfile);
|
||||
sess->lockfile = NULL;
|
||||
|
||||
g_free (sess->linkfile);
|
||||
sess->linkfile = NULL;
|
||||
|
||||
sess->topgroup = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@ -401,7 +415,7 @@ xaccSessionDestroy (Session *sess)
|
||||
{
|
||||
if (!sess) return;
|
||||
xaccSessionEnd (sess);
|
||||
free (sess);
|
||||
g_free (sess);
|
||||
}
|
||||
|
||||
|
||||
@ -415,29 +429,32 @@ MakeHomeDir (void)
|
||||
{
|
||||
int rc;
|
||||
struct stat statbuf;
|
||||
char *home, *path;
|
||||
char *home;
|
||||
char *path;
|
||||
char *data;
|
||||
|
||||
/* Punt. Can't figure out where home is. */
|
||||
home = getenv ("HOME");
|
||||
if (!home) return;
|
||||
|
||||
path = alloca (strlen (home) +50);
|
||||
strcpy (path, home);
|
||||
strcat (path, "/.gnucash");
|
||||
path = g_strconcat(home, "/.gnucash", NULL);
|
||||
|
||||
rc = stat (path, &statbuf);
|
||||
if (rc) {
|
||||
/* assume that the stat failed only because the dir is absent,
|
||||
* and not because its read-protected or other error.
|
||||
* Go ahead and make it. Don't bother much with checking mkdir
|
||||
* for errors; seems pointless ... */
|
||||
* for errors; seems pointless. */
|
||||
mkdir (path, S_IRWXU); /* perms = S_IRWXU = 0700 */
|
||||
}
|
||||
|
||||
strcat (path, "/data");
|
||||
rc = stat (path, &statbuf);
|
||||
data = g_strconcat (path, "/data");
|
||||
rc = stat (data, &statbuf);
|
||||
if (rc)
|
||||
mkdir (path, S_IRWXU);
|
||||
mkdir (data, S_IRWXU);
|
||||
|
||||
g_free (path);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
/* ============================================================== */
|
||||
|
@ -88,7 +88,12 @@ void xaccSessionDestroy (Session *);
|
||||
*
|
||||
* The xaccSessionBeginFile() routine is identical to the xaccSessionBegin()
|
||||
* routine, except that the argument is a filename (i.e. the five
|
||||
* letters "file:" should not be prepended).
|
||||
* letters "file:" should not be prepended) and there is an additional
|
||||
* function argument. This function is called if xaccSessionBeginFile
|
||||
* fails to obtain a lock for the file. If it returns true, the file
|
||||
* is loaded anyway. If it returns false, or the handler is NULL, a
|
||||
* failed lock attempt will abort the load. The lock fail handler is
|
||||
* passed the filename of the data file being loaded.
|
||||
*
|
||||
* The xaccSessionGetFilePath() routine returns the fully-qualified file
|
||||
* path for the session. That is, if a relative or partial filename
|
||||
@ -168,8 +173,11 @@ void xaccSessionDestroy (Session *);
|
||||
* xaccSessionDestroy (sess);
|
||||
* */
|
||||
|
||||
typedef gboolean (*SessionLockFailHandler)(const char *file);
|
||||
|
||||
AccountGroup * xaccSessionBegin (Session *, const char * sessionid);
|
||||
AccountGroup * xaccSessionBeginFile (Session *, const char * filename);
|
||||
AccountGroup * xaccSessionBeginFile (Session *, const char * filename,
|
||||
SessionLockFailHandler handler);
|
||||
int xaccSessionGetError (Session *);
|
||||
AccountGroup * xaccSessionGetGroup (Session *);
|
||||
void xaccSessionSetGroup (Session *, AccountGroup *topgroup);
|
||||
|
Loading…
Reference in New Issue
Block a user