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
This commit is contained in:
Werner Koch 2023-02-01 17:28:57 +01:00
parent 343fb33bf0
commit 5ab9c234d6
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -83,11 +83,17 @@
# define GNUPG_REGKEY_3 "Software\\GnuPG" # define GNUPG_REGKEY_3 "Software\\GnuPG"
#endif #endif
/* Installation type constants. */
#define INST_TYPE_GPG4WIN 1
#define INST_TYPE_GPGDESK 2
/* Relative name parts for different installation types. */ /* Relative name parts for different installation types. */
#define INST_TYPE_GPG4WIN_DIR "\\..\\..\\GnuPG\\bin" #define INST_TYPE_GPG4WIN_DIR "\\..\\..\\GnuPG\\bin"
#define INST_TYPE_GPGDESK_DIR "\\..\\GnuPG\\bin" #define INST_TYPE_GPGDESK_DIR "\\..\\GnuPG\\bin"
DEFINE_STATIC_LOCK (get_path_lock); DEFINE_STATIC_LOCK (get_path_lock);
/* The module handle of this DLL. If we are linked statically, /* 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. /* Used by gpgme_set_global_flag to set the installation type.
* VALUE is a string interpreted as integer with this meaning: * VALUE is a string interpreted as integer with this meaning:
* 0 = standard * 0 = standard
* 1 = Gpg4win 4 style * 1 = Gpg4win 4 style (INST_TYPE_GPG4WIN)
* 2 = GnuPG (VS-)Desktop style * 2 = GnuPG (VS-)Desktop style (INST_TYPE_GPGDESK)
* If VALUE is NULL, nothing is changed. The return value is the * If VALUE is NULL, nothing is changed. The return value is the
* previous value. * 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 /* This function is only called by get_gpgconf_item and may not be
called concurrently. */ called concurrently. */
char * char *
@ -620,23 +653,48 @@ _gpgme_get_gpgconf_path (void)
char *gpgconf = NULL; char *gpgconf = NULL;
const char *inst_dir, *name; const char *inst_dir, *name;
int inst_type; int inst_type;
char *dir; char *dir = NULL;
name = default_gpgconf_name? get_basename(default_gpgconf_name):"gpgconf.exe"; 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_dir = _gpgme_get_inst_dir ();
if (inst_dir inst_type = _gpgme_set_get_inst_type (NULL);
&& (inst_type = _gpgme_set_get_inst_type (NULL))
&& (inst_type == 1 || inst_type == 2)) /* 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)
{ {
dir = _gpgme_strconcat (inst_dir, gpgrt_stream_t fp;
inst_type == 1? INST_TYPE_GPG4WIN_DIR char buffer[128];
/* */ : INST_TYPE_GPGDESK_DIR, int n;
NULL);
gpgconf = find_program_in_dir (dir, name);
free (dir); 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 == INST_TYPE_GPG4WIN || inst_type == INST_TYPE_GPGDESK))
{
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. */ /* 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. */ /* 3. Try to find gpgconf.exe using the Windows registry. */
if (!gpgconf) if (!gpgconf)
{ {
char *dir; free (dir);
dir = read_w32_registry_string (NULL, dir = read_w32_registry_string (NULL,
GNUPG_REGKEY_2, GNUPG_REGKEY_2,
"Install Directory"); "Install Directory");
@ -675,10 +732,7 @@ _gpgme_get_gpgconf_path (void)
} }
} }
if (dir) if (dir)
{ gpgconf = find_program_in_dir (dir, name);
gpgconf = find_program_in_dir (dir, name);
free (dir);
}
} }
/* 4. Try to find gpgconf.exe from Gpg4win below CSIDL_PROGRAM_FILES. */ /* 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. */ /* 5. Try to find gpgconf.exe relative to us as Gpg4win installs it. */
if (!gpgconf && inst_dir) if (!gpgconf && inst_dir)
{ {
free (dir);
dir = _gpgme_strconcat (inst_dir, INST_TYPE_GPG4WIN_DIR, NULL); dir = _gpgme_strconcat (inst_dir, INST_TYPE_GPG4WIN_DIR, NULL);
gpgconf = find_program_in_dir (dir, name); gpgconf = find_program_in_dir (dir, name);
free (dir);
} }
/* 6. Try to find gpgconf.exe relative to us as GnuPG VSD installs it. */ /* 6. Try to find gpgconf.exe relative to us as GnuPG VSD installs it. */
if (!gpgconf && inst_dir) if (!gpgconf && inst_dir)
{ {
free (dir);
dir = _gpgme_strconcat (inst_dir, INST_TYPE_GPGDESK_DIR, NULL); dir = _gpgme_strconcat (inst_dir, INST_TYPE_GPGDESK_DIR, NULL);
gpgconf = find_program_in_dir (dir, name); gpgconf = find_program_in_dir (dir, name);
free (dir);
} }
/* Print a debug message if not found. */ /* 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_debug (NULL, DEBUG_ENGINE, -1, NULL, NULL, NULL,
"_gpgme_get_gpgconf_path: '%s' not found",name); "_gpgme_get_gpgconf_path: '%s' not found",name);
free (dir);
return gpgconf; return gpgconf;
} }