00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __BINRELOC_C__
00014 #define __BINRELOC_C__
00015 #include "config.h"
00016
00017 #ifdef ENABLE_BINRELOC
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <unistd.h>
00021 #ifdef MAC_INTEGRATION
00022 #include <igemacintegration/gtkosxapplication.h>
00023 #endif
00024 #endif
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <limits.h>
00028 #include <string.h>
00029 #include "binreloc.h"
00030 #include <glib.h>
00031
00032 G_BEGIN_DECLS
00033
00039 static char *
00040 _br_find_exe (Gnc_GbrInitError *error)
00041 {
00042 #ifndef ENABLE_BINRELOC
00043 if (error)
00044 *error = GNC_GBR_INIT_ERROR_DISABLED;
00045 return NULL;
00046 #else
00047 #ifdef G_OS_WIN32
00048
00049
00050
00051
00052
00053 gchar *prefix;
00054 gchar *result;
00055
00056
00057
00058
00059 prefix = g_win32_get_package_installation_directory_of_module (NULL);
00060 result = g_build_filename (prefix,
00061 "bin", "gnucash.exe",
00062 (char*)NULL);
00063 g_free (prefix);
00064 return result;
00065 #elif defined MAC_INTEGRATION
00066 GtkOSXApplication *theApp;
00067 g_type_init();
00068 theApp = g_object_new (GTK_TYPE_OSX_APPLICATION, NULL);
00069 return gtk_osxapplication_get_executable_path(theApp);
00070 #else
00071 char *path, *path2, *line, *result;
00072 size_t buf_size;
00073 ssize_t size;
00074 struct stat stat_buf;
00075 FILE *f;
00076
00077
00078 if (sizeof (path) > SSIZE_MAX)
00079 buf_size = SSIZE_MAX - 1;
00080 else
00081 buf_size = PATH_MAX - 1;
00082 path = (char *) g_try_malloc (buf_size);
00083 if (path == NULL)
00084 {
00085
00086 if (error)
00087 *error = GNC_GBR_INIT_ERROR_NOMEM;
00088 return NULL;
00089 }
00090 path2 = (char *) g_try_malloc (buf_size);
00091 if (path2 == NULL)
00092 {
00093
00094 if (error)
00095 *error = GNC_GBR_INIT_ERROR_NOMEM;
00096 g_free (path);
00097 return NULL;
00098 }
00099
00100 strncpy (path2, "/proc/self/exe", buf_size - 1);
00101
00102 while (1)
00103 {
00104 int i;
00105
00106 size = readlink (path2, path, buf_size - 1);
00107 if (size == -1)
00108 {
00109
00110 g_free (path2);
00111 break;
00112 }
00113
00114
00115 path[size] = '\0';
00116
00117
00118
00119 i = stat (path, &stat_buf);
00120 if (i == -1)
00121 {
00122
00123 g_free (path2);
00124 break;
00125 }
00126
00127
00128 if (!S_ISLNK (stat_buf.st_mode))
00129 {
00130
00131 g_free (path2);
00132 return path;
00133 }
00134
00135
00136 strncpy (path, path2, buf_size - 1);
00137 }
00138
00139
00140
00141
00142
00143 buf_size = PATH_MAX + 128;
00144 line = (char *) g_try_realloc (path, buf_size);
00145 if (line == NULL)
00146 {
00147
00148 g_free (path);
00149 if (error)
00150 *error = GNC_GBR_INIT_ERROR_NOMEM;
00151 return NULL;
00152 }
00153
00154 f = fopen ("/proc/self/maps", "r");
00155 if (f == NULL)
00156 {
00157 g_free (line);
00158 if (error)
00159 *error = GNC_GBR_INIT_ERROR_OPEN_MAPS;
00160 return NULL;
00161 }
00162
00163
00164 result = fgets (line, (int) buf_size, f);
00165 if (result == NULL)
00166 {
00167 fclose (f);
00168 g_free (line);
00169 if (error)
00170 *error = GNC_GBR_INIT_ERROR_READ_MAPS;
00171 return NULL;
00172 }
00173
00174
00175 buf_size = strlen (line);
00176 if (buf_size <= 0)
00177 {
00178
00179 fclose (f);
00180 g_free (line);
00181 if (error)
00182 *error = GNC_GBR_INIT_ERROR_INVALID_MAPS;
00183 return NULL;
00184 }
00185 if (line[buf_size - 1] == 10)
00186 line[buf_size - 1] = 0;
00187
00188
00189 path = strchr (line, '/');
00190
00191
00192 if (strstr (line, " r-xp ") == NULL || path == NULL)
00193 {
00194 fclose (f);
00195 g_free (line);
00196 if (error)
00197 *error = GNC_GBR_INIT_ERROR_INVALID_MAPS;
00198 return NULL;
00199 }
00200
00201 path = g_strdup (path);
00202 g_free (line);
00203 fclose (f);
00204 return path;
00205 #endif
00206 #endif
00207 }
00208
00209
00210
00211 static gchar *exe = NULL;
00212
00213 static void set_gerror (GError **error, Gnc_GbrInitError errcode);
00214
00215
00216 void gnc_gbr_set_exe (const gchar* default_exe)
00217 {
00218 if (exe != NULL)
00219 g_free(exe);
00220 exe = NULL;
00221
00222 if (default_exe != NULL)
00223 exe = g_strdup(default_exe);
00224 }
00225
00226
00242 gboolean
00243 gnc_gbr_init (GError **error)
00244 {
00245 Gnc_GbrInitError errcode = 0;
00246
00247
00248 exe = _br_find_exe (&errcode);
00249 if (exe != NULL)
00250
00251 return TRUE;
00252 else
00253 {
00254
00255 set_gerror (error, errcode);
00256 return FALSE;
00257 }
00258 }
00259
00260
00261 static void
00262 set_gerror (GError **error, Gnc_GbrInitError errcode)
00263 {
00264 gchar *error_message;
00265
00266 if (error == NULL)
00267 return;
00268
00269 switch (errcode)
00270 {
00271 case GNC_GBR_INIT_ERROR_NOMEM:
00272 error_message = "Cannot allocate memory.";
00273 break;
00274 case GNC_GBR_INIT_ERROR_OPEN_MAPS:
00275 error_message = "Unable to open /proc/self/maps for reading.";
00276 break;
00277 case GNC_GBR_INIT_ERROR_READ_MAPS:
00278 error_message = "Unable to read from /proc/self/maps.";
00279 break;
00280 case GNC_GBR_INIT_ERROR_INVALID_MAPS:
00281 error_message = "The file format of /proc/self/maps is invalid.";
00282 break;
00283 case GNC_GBR_INIT_ERROR_DISABLED:
00284 error_message = "Binary relocation support is disabled.";
00285 break;
00286 default:
00287 error_message = "Unknown error.";
00288 break;
00289 };
00290 g_set_error (error, g_quark_from_static_string ("GBinReloc"),
00291 errcode, "%s", error_message);
00292 }
00293
00294
00304 gchar *
00305 gnc_gbr_find_exe (const gchar *default_exe)
00306 {
00307 if (exe == NULL)
00308 {
00309
00310 if (default_exe != NULL)
00311 return g_strdup (default_exe);
00312 else
00313 return NULL;
00314 }
00315 return g_strdup (exe);
00316 }
00317
00318
00333 gchar *
00334 gnc_gbr_find_exe_dir (const gchar *default_dir)
00335 {
00336 if (exe == NULL)
00337 {
00338
00339 if (default_dir != NULL)
00340 return g_strdup (default_dir);
00341 else
00342 return NULL;
00343 }
00344
00345 return g_path_get_dirname (exe);
00346 }
00347
00348
00363 gchar *
00364 gnc_gbr_find_prefix (const gchar *default_prefix)
00365 {
00366 #if defined ENABLE_BINRELOC && defined MAC_INTEGRATION
00367 gchar *id = quartz_application_get_bundle_id ();
00368 gchar *path = quartz_application_get_resource_path ();
00369 if (id == NULL)
00370 {
00371 gchar *dirname = g_path_get_dirname (path);
00372 g_free (path);
00373 g_free (id);
00374 return dirname;
00375 }
00376 g_free (id);
00377 return path;
00378 #else
00379 gchar *dir1, *dir2;
00380
00381 if (exe == NULL)
00382 {
00383
00384 if (default_prefix != NULL)
00385 return g_strdup (default_prefix);
00386 else
00387 return NULL;
00388 }
00389 dir1 = g_path_get_dirname (exe);
00390 dir2 = g_path_get_dirname (dir1);
00391 g_free (dir1);
00392 return dir2;
00393 #endif //ENABLE_BINRELOC && defined MAC_INTEGRATION
00394 }
00395
00396
00410 gchar *
00411 gnc_gbr_find_bin_dir (const gchar *default_bin_dir)
00412 {
00413 gchar *prefix, *dir;
00414 prefix = gnc_gbr_find_prefix (NULL);
00415 if (prefix == NULL)
00416 {
00417
00418 if (default_bin_dir != NULL)
00419 return g_strdup (default_bin_dir);
00420 else
00421 return NULL;
00422 }
00423
00424 dir = g_build_filename (prefix, "bin", NULL);
00425 g_free (prefix);
00426 return dir;
00427 }
00428
00429
00443 gchar *
00444 gnc_gbr_find_sbin_dir (const gchar *default_sbin_dir)
00445 {
00446 gchar *prefix, *dir;
00447
00448 prefix = gnc_gbr_find_prefix (NULL);
00449 if (prefix == NULL)
00450 {
00451
00452 if (default_sbin_dir != NULL)
00453 return g_strdup (default_sbin_dir);
00454 else
00455 return NULL;
00456 }
00457
00458 dir = g_build_filename (prefix, "sbin", NULL);
00459 g_free (prefix);
00460 return dir;
00461 }
00462
00463
00478 gchar *
00479 gnc_gbr_find_data_dir (const gchar *default_data_dir)
00480 {
00481 gchar *prefix, *dir;
00482
00483 prefix = gnc_gbr_find_prefix (NULL);
00484 if (prefix == NULL)
00485 {
00486
00487 if (default_data_dir != NULL)
00488 return g_strdup (default_data_dir);
00489 else
00490 return NULL;
00491 }
00492
00493 dir = g_build_filename (prefix, "share", NULL);
00494 g_free (prefix);
00495 return dir;
00496 }
00497
00498
00512 gchar *
00513 gnc_gbr_find_lib_dir (const gchar *default_lib_dir)
00514 {
00515 gchar *prefix, *dir;
00516
00517 prefix = gnc_gbr_find_prefix (NULL);
00518 if (prefix == NULL)
00519 {
00520
00521 if (default_lib_dir != NULL)
00522 return g_strdup (default_lib_dir);
00523 else
00524 return NULL;
00525 }
00526
00527 dir = g_build_filename (prefix, "lib", NULL);
00528 g_free (prefix);
00529 return dir;
00530 }
00531
00532
00546 gchar *
00547 gnc_gbr_find_libexec_dir (const gchar *default_libexec_dir)
00548 {
00549 gchar *prefix, *dir;
00550
00551 prefix = gnc_gbr_find_prefix (NULL);
00552 if (prefix == NULL)
00553 {
00554
00555 if (default_libexec_dir != NULL)
00556 return g_strdup (default_libexec_dir);
00557 else
00558 return NULL;
00559 }
00560
00561 dir = g_build_filename (prefix, "libexec", NULL);
00562 g_free (prefix);
00563 return dir;
00564 }
00565
00566
00580 gchar *
00581 gnc_gbr_find_etc_dir (const gchar *default_etc_dir)
00582 {
00583 gchar *prefix, *dir;
00584
00585 prefix = gnc_gbr_find_prefix (NULL);
00586 if (prefix == NULL)
00587 {
00588
00589 if (default_etc_dir != NULL)
00590 return g_strdup (default_etc_dir);
00591 else
00592 return NULL;
00593 }
00594
00595 dir = g_build_filename (prefix, "etc", NULL);
00596 g_free (prefix);
00597 return dir;
00598 }
00599
00600
00601 G_END_DECLS
00602
00603 #endif