|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * file-utils.c -- simple file utilities * 00003 * Copyright (C) 1997 Robin D. Clark <rclark@cs.hmc.edu> * 00004 * Copyright (C) 1998 Rob Browning * 00005 * Copyright (C) 1998-2000 Linas Vepstas <linas@linas.org> * 00006 * * 00007 * This program is free software; you can redistribute it and/or * 00008 * modify it under the terms of the GNU General Public License as * 00009 * published by the Free Software Foundation; either version 2 of * 00010 * the License, or (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License* 00018 * along with this program; if not, write to the Free Software * 00019 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00020 \********************************************************************/ 00021 00022 #include "config.h" 00023 00024 #include <glib.h> 00025 #include <glib/gstdio.h> 00026 #include <libguile.h> 00027 #include <errno.h> 00028 #include <fcntl.h> 00029 #include <string.h> 00030 #include <sys/stat.h> 00031 #include <sys/types.h> 00032 #ifdef HAVE_UNISTD_H 00033 # include <unistd.h> 00034 #else 00035 # include <io.h> 00036 # define close _close 00037 # define lseek _lseek 00038 # define read _read 00039 #endif 00040 00041 #include "guile-mappings.h" 00042 #include "file-utils.h" 00043 #include "gnc-engine.h" 00044 #include "gnc-filepath-utils.h" 00045 #include "gnc-gkeyfile-utils.h" 00046 #include "gnc-uri-utils.h" 00047 00048 /* This static indicates the debugging module that this .o belongs to. */ 00049 static QofLogModule log_module = GNC_MOD_GUILE; 00050 00051 /********************************************************************\ 00052 \********************************************************************/ 00053 00054 char * 00055 gncFindFile (const char * filename) 00056 { 00057 char *full_filename = NULL; 00058 char * return_string = NULL; 00059 SCM find_doc_file; 00060 SCM scm_filename; 00061 SCM scm_result; 00062 00063 if (!filename || *filename == '\0') 00064 return NULL; 00065 00066 find_doc_file = scm_c_eval_string("gnc:find-doc-file"); 00067 scm_filename = scm_makfrom0str ((char *) filename); 00068 scm_result = scm_call_1(find_doc_file, scm_filename); 00069 00070 if (scm_is_string(scm_result)) 00071 { 00072 char * str; 00073 00074 scm_dynwind_begin (0); 00075 full_filename = scm_to_locale_string(scm_result); 00076 return_string = g_strdup (full_filename); 00077 scm_dynwind_free (full_filename); 00078 scm_dynwind_end (); 00079 } 00080 00081 return return_string; 00082 } 00083 00084 /********************************************************************\ 00085 * gncReadFile * 00086 * * 00087 * Args: filename - the name of the html file to read * 00088 * data - pointer to set to the buffer of data read in * 00089 * Return: size of data read * 00090 * Global: helpPath - the path to the help files * 00091 \********************************************************************/ 00092 int 00093 gncReadFile (const char * filename, char ** data) 00094 { 00095 char *buf = NULL; 00096 char *fullname; 00097 int size = 0; 00098 int fd; 00099 00100 /* construct absolute path -- twiddle the relative path we received */ 00101 if (!filename || filename[0] == '\0') return 0; 00102 00103 /* take absolute paths without searching */ 00104 if (!g_path_is_absolute (filename)) 00105 fullname = gncFindFile (filename); 00106 else 00107 fullname = g_strdup (filename); 00108 00109 if (!fullname) return 0; 00110 00111 /* Open file: */ 00112 fd = g_open( fullname, O_RDONLY, 0 ); 00113 00114 g_free(fullname); 00115 fullname = NULL; 00116 00117 if ( fd == -1 ) 00118 { 00119 int norr = errno; 00120 PERR ("file %s: (%d) %s \n", filename, norr, strerror(norr)); 00121 return 0; 00122 } 00123 00124 /* Find size: */ 00125 size = lseek( fd, 0, SEEK_END ); 00126 lseek( fd, 0, SEEK_SET ); 00127 00128 /* Allocate memory */ 00129 buf = g_new(char, size + 1); 00130 00131 /* read in file */ 00132 if ( read(fd, buf, size) == -1 ) 00133 { 00134 g_free(buf); 00135 buf = NULL; 00136 } 00137 else 00138 { 00139 buf[size] = '\0'; 00140 } 00141 00142 close(fd); 00143 *data = buf; 00144 00145 return size; 00146 } 00147 00148 /*********************************************************************** 00149 * gnc_getline -- read a line from the input file, up to and including 00150 * the newline. 00151 * 00152 * Args: line - pointer to hold the buffer for the whole line (allocated by 00153 * this function) 00154 * file - the file from which to read 00155 * Return: the number of bytes read 00156 * 00157 * The caller MUST g_free() the line returned from this call in all 00158 * cases where it is non-NULL! 00159 */ 00160 00161 gint64 00162 gnc_getline (gchar **line, FILE *file) 00163 { 00164 char str[BUFSIZ]; 00165 gint64 len; 00166 GString *gs; 00167 00168 g_return_val_if_fail(line, -1); 00169 *line = NULL; 00170 g_return_val_if_fail(file, -1); 00171 00172 gs = g_string_new(""); 00173 00174 while (fgets(str, sizeof(str), file) != NULL) 00175 { 00176 g_string_append(gs, str); 00177 00178 len = strlen(str); 00179 if (str[len-1] == '\n') 00180 break; 00181 } 00182 00183 len = gs->len; 00184 *line = gs->str; 00185 g_string_free(gs, FALSE); 00186 return len; 00187 } 00188 00189 /* Find the state file that corresponds to this URL and guid. 00190 * 00191 * The state files will be searched for in the books directory in GnuCash' 00192 * private configuration directory. This configuration directory is 00193 * platform dependent and can be overridden with environment variable 00194 * DOT_GNUCASH_DIR. On linux for example this is ~/.gnucash by default. 00195 * 00196 * The URL is used to compute the base name of the state file and the 00197 * guid is used to differentiate when the user has multiple data files 00198 * with the same name. 00199 * 00200 * As of GnuCash 2.4.1 state files will have their own extension to 00201 * differentiate them from data files saved by the user. New state 00202 * files will always be created with such an extension. But GnuCash 00203 * will continue to search for state files without an extension if 00204 * no proper state file with extension is found. */ 00205 GKeyFile * 00206 gnc_find_state_file (const gchar *url, 00207 const gchar *guid, 00208 gchar **filename_p) 00209 { 00210 gchar *basename, *original = NULL, *filename, *tmp, *file_guid; 00211 gchar *sf_extension = NULL, *newstyle_filename = NULL; 00212 GKeyFile *key_file = NULL; 00213 gint i; 00214 00215 ENTER("url %s, guid %s", url, guid); 00216 00217 if ( gnc_uri_is_file_uri ( url ) ) 00218 { 00219 /* The url is a true file, use its basename. */ 00220 gchar *path = gnc_uri_get_path ( url ); 00221 basename = g_path_get_basename ( path ); 00222 g_free ( path ); 00223 } 00224 else 00225 { 00226 /* The url is composed of database connection parameters. */ 00227 gchar* protocol = NULL; 00228 gchar* host = NULL; 00229 gchar* dbname = NULL; 00230 gchar* username = NULL; 00231 gchar* password = NULL; 00232 gint portnum = 0; 00233 gnc_uri_get_components ( url, &protocol, &host, &portnum, 00234 &username, &password, &dbname ); 00235 00236 basename = g_strjoin("_", protocol, host, username, dbname, NULL); 00237 g_free( protocol ); 00238 g_free( host ); 00239 g_free( username ); 00240 g_free( password ); 00241 g_free( dbname ); 00242 } 00243 00244 DEBUG("Basename %s", basename); 00245 original = gnc_build_book_path(basename); 00246 g_free(basename); 00247 DEBUG("Original %s", original); 00248 00249 sf_extension = g_strdup(STATE_FILE_EXT); 00250 i = 1; 00251 while (1) 00252 { 00253 if (i == 1) 00254 filename = g_strconcat(original, sf_extension, NULL); 00255 else 00256 filename = g_strdup_printf("%s_%d%s", original, i, sf_extension); 00257 DEBUG("Trying %s", filename); 00258 key_file = gnc_key_file_load_from_file(filename, FALSE, FALSE, NULL); 00259 DEBUG("Result %p", key_file); 00260 00261 if (!key_file) 00262 { 00263 DEBUG("No key file by that name"); 00264 if (g_strcmp0(sf_extension, STATE_FILE_EXT) == 0) 00265 { 00266 DEBUG("Trying old state file names for compatibility"); 00267 newstyle_filename = filename; 00268 i = 1; 00269 g_free( sf_extension); 00270 sf_extension = g_strdup(""); 00271 continue; 00272 } 00273 break; 00274 } 00275 00276 file_guid = g_key_file_get_string(key_file, 00277 STATE_FILE_TOP, STATE_FILE_BOOK_GUID, 00278 NULL); 00279 DEBUG("File GncGUID is %s", file_guid ? file_guid : "<not found>"); 00280 if (safe_strcmp(guid, file_guid) == 0) 00281 { 00282 DEBUG("Matched !!!"); 00283 g_free(file_guid); 00284 break; 00285 } 00286 DEBUG("Clean up this pass"); 00287 g_free(file_guid); 00288 g_key_file_free(key_file); 00289 g_free(filename); 00290 i++; 00291 } 00292 00293 DEBUG("Clean up"); 00294 g_free(original); 00295 /* Pre-2.4.1 compatibility block: make sure when the state file is 00296 * written again later, it will use the next available filename with 00297 * extension and optional counter. (This name was determined earlier 00298 * in the loop.) */ 00299 if (newstyle_filename) 00300 { 00301 g_free(filename); 00302 filename = newstyle_filename; 00303 } 00304 00305 if (filename_p) 00306 *filename_p = filename; 00307 else 00308 g_free(filename); 00309 LEAVE("key_file %p, filename %s", key_file, 00310 filename_p ? *filename_p : "(none)"); 00311 return key_file; 00312 } 00313 00314 /* ----------------------- END OF FILE --------------------- */
1.7.4