summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2023-02-01 17:28:57 +0100
committerWerner Koch <wk@gnupg.org>2023-02-01 17:29:24 +0100
commit5ab9c234d6b507f568fe1d2a2cbc82250a7828ee (patch)
tree8df5d558776d4ab48b5b6ad706dcc8d60b6f235c
parent343fb33bf02bea74caf4e615483f1a00dc06f7b8 (diff)
downloadgpgme-5ab9c234d6b507f568fe1d2a2cbc82250a7828ee.tar.gz
core,w32: More robust detection of GnuPG Desktop dir layout
* src/w32-util.c (INST_TYPE_GPG4WIN, INST_TYPE_GPGDESK): New to replace the numeric constants. (find_version_file): New. (_gpgme_get_gpgconf_path): Guess a default for inst_type. -- GnuPG-bug-id: 6362
-rw-r--r--src/w32-util.c95
1 files changed, 75 insertions, 20 deletions
diff --git a/src/w32-util.c b/src/w32-util.c
index ffe19f6f..2e6428c0 100644
--- a/src/w32-util.c
+++ b/src/w32-util.c
@@ -83,11 +83,17 @@
# define GNUPG_REGKEY_3 "Software\\GnuPG"
#endif
+/* Installation type constants. */
+#define INST_TYPE_GPG4WIN 1
+#define INST_TYPE_GPGDESK 2
+
/* Relative name parts for different installation types. */
#define INST_TYPE_GPG4WIN_DIR "\\..\\..\\GnuPG\\bin"
#define INST_TYPE_GPGDESK_DIR "\\..\\GnuPG\\bin"
+
+
DEFINE_STATIC_LOCK (get_path_lock);
/* The module handle of this DLL. If we are linked statically,
@@ -544,8 +550,8 @@ _gpgme_set_override_inst_dir (const char *dir)
/* Used by gpgme_set_global_flag to set the installation type.
* VALUE is a string interpreted as integer with this meaning:
* 0 = standard
- * 1 = Gpg4win 4 style
- * 2 = GnuPG (VS-)Desktop style
+ * 1 = Gpg4win 4 style (INST_TYPE_GPG4WIN)
+ * 2 = GnuPG (VS-)Desktop style (INST_TYPE_GPGDESK)
* If VALUE is NULL, nothing is changed. The return value is the
* previous value.
*/
@@ -612,6 +618,33 @@ _gpgme_get_gpg_path (void)
}
+/* Helper for _gpgme_get_gpgconf_path. */
+static char *
+find_version_file (const char *inst_dir)
+{
+ char *fname;
+
+ fname = _gpgme_strconcat (inst_dir, "\\..\\", "VERSION.sig", NULL);
+ if (fname && !_gpgme_access (fname, F_OK))
+ {
+ fname[strlen(fname)-4] = 0;
+ if (!_gpgme_access (fname, F_OK))
+ return fname;
+ }
+ free (fname);
+ /* Check the case that a binary in gnupg/bin uses libgpgme. */
+ fname = _gpgme_strconcat (inst_dir, "\\..\\..\\", "VERSION.sig", NULL);
+ if (fname && !_gpgme_access (fname, F_OK))
+ {
+ fname[strlen(fname)-4] = 0;
+ if (!_gpgme_access (fname, F_OK))
+ return fname;
+ }
+ free (fname);
+ return NULL;
+}
+
+
/* This function is only called by get_gpgconf_item and may not be
called concurrently. */
char *
@@ -620,23 +653,48 @@ _gpgme_get_gpgconf_path (void)
char *gpgconf = NULL;
const char *inst_dir, *name;
int inst_type;
- char *dir;
+ char *dir = NULL;
name = default_gpgconf_name? get_basename(default_gpgconf_name):"gpgconf.exe";
- /* 0. If an installation type is requested try to find gpgconf.exe
- * depending on that installation type. */
inst_dir = _gpgme_get_inst_dir ();
+ inst_type = _gpgme_set_get_inst_type (NULL);
+
+ /* 0.0. If no installation type has been explicitly requested guess
+ * one by looking at files used by the installation type. */
+ if (inst_dir && !inst_type)
+ {
+ gpgrt_stream_t fp;
+ char buffer[128];
+ int n;
+
+ free (dir);
+ dir = find_version_file (inst_dir);
+ if (dir && (fp = gpgrt_fopen (dir, "r")))
+ {
+ n = gpgrt_fread (buffer, 1, 128, fp);
+ if (n > 10)
+ {
+ buffer[n-1] = 0;
+ if (strstr (buffer, "GnuPG") && strstr (buffer, "Desktop"))
+ inst_type = INST_TYPE_GPGDESK;
+ }
+ gpgrt_fclose (fp);
+ }
+ }
+
+ /* 0.1. If an installation type was requested or guessed try to find
+ * gpgconf.exe depending on that installation type. */
if (inst_dir
- && (inst_type = _gpgme_set_get_inst_type (NULL))
- && (inst_type == 1 || inst_type == 2))
+ && (inst_type == INST_TYPE_GPG4WIN || inst_type == INST_TYPE_GPGDESK))
{
- dir = _gpgme_strconcat (inst_dir,
- inst_type == 1? INST_TYPE_GPG4WIN_DIR
- /* */ : INST_TYPE_GPGDESK_DIR,
- NULL);
- gpgconf = find_program_in_dir (dir, name);
free (dir);
+ dir = _gpgme_strconcat
+ (inst_dir,
+ inst_type == INST_TYPE_GPG4WIN? INST_TYPE_GPG4WIN_DIR
+ /* */ : INST_TYPE_GPGDESK_DIR,
+ NULL);
+ gpgconf = find_program_in_dir (dir, name);
}
/* 1. Try to find gpgconf.exe in the installation directory of gpgme. */
@@ -656,8 +714,7 @@ _gpgme_get_gpgconf_path (void)
/* 3. Try to find gpgconf.exe using the Windows registry. */
if (!gpgconf)
{
- char *dir;
-
+ free (dir);
dir = read_w32_registry_string (NULL,
GNUPG_REGKEY_2,
"Install Directory");
@@ -675,10 +732,7 @@ _gpgme_get_gpgconf_path (void)
}
}
if (dir)
- {
- gpgconf = find_program_in_dir (dir, name);
- free (dir);
- }
+ gpgconf = find_program_in_dir (dir, name);
}
/* 4. Try to find gpgconf.exe from Gpg4win below CSIDL_PROGRAM_FILES. */
@@ -690,17 +744,17 @@ _gpgme_get_gpgconf_path (void)
/* 5. Try to find gpgconf.exe relative to us as Gpg4win installs it. */
if (!gpgconf && inst_dir)
{
+ free (dir);
dir = _gpgme_strconcat (inst_dir, INST_TYPE_GPG4WIN_DIR, NULL);
gpgconf = find_program_in_dir (dir, name);
- free (dir);
}
/* 6. Try to find gpgconf.exe relative to us as GnuPG VSD installs it. */
if (!gpgconf && inst_dir)
{
+ free (dir);
dir = _gpgme_strconcat (inst_dir, INST_TYPE_GPGDESK_DIR, NULL);
gpgconf = find_program_in_dir (dir, name);
- free (dir);
}
/* Print a debug message if not found. */
@@ -708,6 +762,7 @@ _gpgme_get_gpgconf_path (void)
_gpgme_debug (NULL, DEBUG_ENGINE, -1, NULL, NULL, NULL,
"_gpgme_get_gpgconf_path: '%s' not found",name);
+ free (dir);
return gpgconf;
}