mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
common: Support a gpgconf.ctl file under Unix.
* common/homedir.c (unix_rootdir): New. (gnupg_bindir): Use it. (gnupg_libexecdir): Use it. (gnupg_libdir): Use it. (gnupg_datadir): Use it. (gnupg_localedir): Use it. -- This feature is useful for building and using an AppImage version of gnupg and probably also for some other use cases. GnuPG-bug-id: 5999 Here is a sample gpgconf.ctl file --8<---------------cut here---------------start------------->8--- # gpgconf.ctl # # This file is used to change the directories where the gpg components # are installed. It does not change the configuration directories. # The file is expected in the same directory as gpgconf. The physical # installation directories are evaluated and no symlinks. Blank lines # and lines starting with pound signed are ignored. No errors are # printed for unknown keywords or commands. The only defined key for # now is "rootdir" which must be followed by one optional space, an # equal sign, and the value for the root directory. Environment # variables are substituted in standard shell manner, the final value # must start with a slash, trailing slashed are stripped. rootdir = $APPDIR/gnupg --8<---------------cut here---------------end--------------->8---
This commit is contained in:
parent
9c272dc245
commit
d4768bb982
259
common/homedir.c
259
common/homedir.c
@ -388,8 +388,10 @@ check_portable_app (const char *dir)
|
|||||||
}
|
}
|
||||||
xfree (fname);
|
xfree (fname);
|
||||||
}
|
}
|
||||||
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
/* Determine the root directory of the gnupg installation on Windows. */
|
/* Determine the root directory of the gnupg installation on Windows. */
|
||||||
static const char *
|
static const char *
|
||||||
w32_rootdir (void)
|
w32_rootdir (void)
|
||||||
@ -441,7 +443,180 @@ w32_rootdir (void)
|
|||||||
/* Fallback to the hardwired value. */
|
/* Fallback to the hardwired value. */
|
||||||
return GNUPG_LIBEXECDIR;
|
return GNUPG_LIBEXECDIR;
|
||||||
}
|
}
|
||||||
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_W32_SYSTEM /* Unix */
|
||||||
|
/* Determine the root directory of the gnupg installation on Unix.
|
||||||
|
* The standard case is that this function returns NULL so that the
|
||||||
|
* root directory as configured at build time is used. However, it
|
||||||
|
* may return a static string with a different root directory, similar
|
||||||
|
* to what we do on Windows. That second mode is triggered by the
|
||||||
|
* existence of a file gpgconf.ctl installed side-by-side to gpgconf.
|
||||||
|
* This file is parsed for keywords describing the actually to be used
|
||||||
|
* root directory. There is no solid standard on Unix to locate the
|
||||||
|
* binary used to create the process, thus we support this currently
|
||||||
|
* only on Linux where we can look this info up using the proc file
|
||||||
|
* system. */
|
||||||
|
static const char *
|
||||||
|
unix_rootdir (void)
|
||||||
|
{
|
||||||
|
static int checked;
|
||||||
|
static char *dir;
|
||||||
|
|
||||||
|
if (!checked)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char *buffer;
|
||||||
|
size_t bufsize = 256-1;
|
||||||
|
int nread;
|
||||||
|
gpg_error_t err;
|
||||||
|
char *line;
|
||||||
|
size_t linelen;
|
||||||
|
ssize_t length;
|
||||||
|
estream_t fp;
|
||||||
|
char *rootdir;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
buffer = xmalloc (bufsize+1);
|
||||||
|
nread = readlink ("/proc/self/exe", buffer, bufsize);
|
||||||
|
if (nread < 0)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_info ("error reading symlink '/proc/self/exe': %s\n",
|
||||||
|
gpg_strerror (err));
|
||||||
|
buffer[0] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (nread < bufsize)
|
||||||
|
{
|
||||||
|
buffer[nread] = 0;
|
||||||
|
break; /* Got it. */
|
||||||
|
}
|
||||||
|
else if (bufsize >= 4095)
|
||||||
|
{
|
||||||
|
buffer[0] = 0;
|
||||||
|
log_info ("error reading symlink '/proc/self/exe': %s\n",
|
||||||
|
"value too large");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xfree (buffer);
|
||||||
|
bufsize += 256;
|
||||||
|
}
|
||||||
|
if (!*buffer)
|
||||||
|
{
|
||||||
|
xfree (buffer);
|
||||||
|
checked = 1;
|
||||||
|
return NULL; /* Error - assume no gpgconf.ctl. */
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strrchr (buffer, '/');
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
xfree (buffer);
|
||||||
|
checked = 1;
|
||||||
|
return NULL; /* Erroneous /proc - assume no gpgconf.ctl. */
|
||||||
|
}
|
||||||
|
*p = 0; /* BUFFER has the directory. */
|
||||||
|
if ((p = strrchr (buffer, '/')))
|
||||||
|
{
|
||||||
|
/* Strip one part and expect the file below a bin dir. */
|
||||||
|
*p = 0;
|
||||||
|
p = xstrconcat (buffer, "/bin/gpgconf.ctl", NULL);
|
||||||
|
xfree (buffer);
|
||||||
|
buffer = p;
|
||||||
|
}
|
||||||
|
else /* !p */
|
||||||
|
{
|
||||||
|
/* Installed in the root which is not a good idea. Assume
|
||||||
|
* no gpgconf.ctl. */
|
||||||
|
xfree (buffer);
|
||||||
|
checked = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gnupg_access (buffer, F_OK))
|
||||||
|
{
|
||||||
|
/* No gpgconf.ctl file. */
|
||||||
|
xfree (buffer);
|
||||||
|
checked = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* log_info ("detected '%s'\n", buffer); */
|
||||||
|
fp = es_fopen (buffer, "r");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_info ("error opening '%s': %s\n", buffer, gpg_strerror (err));
|
||||||
|
xfree (buffer);
|
||||||
|
checked = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = NULL;
|
||||||
|
linelen = 0;
|
||||||
|
rootdir = NULL;
|
||||||
|
while ((length = es_read_line (fp, &line, &linelen, NULL)) > 0)
|
||||||
|
{
|
||||||
|
/* Strip NL and CR, if present. */
|
||||||
|
while (length > 0
|
||||||
|
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
|
||||||
|
line[--length] = 0;
|
||||||
|
trim_spaces (line);
|
||||||
|
if (!strncmp (line, "rootdir=", 8))
|
||||||
|
p = line + 8;
|
||||||
|
else if (!strncmp (line, "rootdir =", 9)) /* (What a kludge) */
|
||||||
|
p = line + 9;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
trim_spaces (p);
|
||||||
|
rootdir = substitute_envvars (p);
|
||||||
|
if (!rootdir)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_info ("error getting rootdir from gpgconf.ctl: %s\n",
|
||||||
|
gpg_strerror (err));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (length < 0 || es_ferror (fp))
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_info ("error reading '%s': %s\n", buffer, gpg_strerror (err));
|
||||||
|
es_fclose (fp);
|
||||||
|
xfree (buffer);
|
||||||
|
xfree (line);
|
||||||
|
checked = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
es_fclose (fp);
|
||||||
|
xfree (buffer);
|
||||||
|
xfree (line);
|
||||||
|
|
||||||
|
if (!rootdir || !*rootdir || *rootdir != '/')
|
||||||
|
{
|
||||||
|
log_info ("invalid rootdir '%s' specified in gpgconf.ctl\n", rootdir);
|
||||||
|
xfree (rootdir);
|
||||||
|
dir = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (*rootdir && rootdir[strlen (rootdir)-1] == '/')
|
||||||
|
rootdir[strlen (rootdir)-1] = 0;
|
||||||
|
dir = rootdir;
|
||||||
|
gpgrt_annotate_leaked_object (dir);
|
||||||
|
/* log_info ("want rootdir '%s'\n", dir); */
|
||||||
|
}
|
||||||
|
checked = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
#endif /* Unix */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
static const char *
|
static const char *
|
||||||
w32_commondir (void)
|
w32_commondir (void)
|
||||||
{
|
{
|
||||||
@ -954,20 +1129,13 @@ gnupg_sysconfdir (void)
|
|||||||
const char *
|
const char *
|
||||||
gnupg_bindir (void)
|
gnupg_bindir (void)
|
||||||
{
|
{
|
||||||
#if defined (HAVE_W32CE_SYSTEM)
|
|
||||||
static char *name;
|
static char *name;
|
||||||
|
|
||||||
if (!name)
|
|
||||||
name = xstrconcat (w32_rootdir (), DIRSEP_S "bin", NULL);
|
|
||||||
return name;
|
|
||||||
#elif defined(HAVE_W32_SYSTEM)
|
|
||||||
const char *rdir;
|
const char *rdir;
|
||||||
|
|
||||||
|
#if defined(HAVE_W32_SYSTEM)
|
||||||
rdir = w32_rootdir ();
|
rdir = w32_rootdir ();
|
||||||
if (w32_bin_is_bin)
|
if (w32_bin_is_bin)
|
||||||
{
|
{
|
||||||
static char *name;
|
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
{
|
{
|
||||||
name = xstrconcat (rdir, DIRSEP_S "bin", NULL);
|
name = xstrconcat (rdir, DIRSEP_S "bin", NULL);
|
||||||
@ -978,6 +1146,17 @@ gnupg_bindir (void)
|
|||||||
else
|
else
|
||||||
return rdir;
|
return rdir;
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
#else /*!HAVE_W32_SYSTEM*/
|
||||||
|
rdir = unix_rootdir ();
|
||||||
|
if (rdir)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
name = xstrconcat (rdir, DIRSEP_S "bin", NULL);
|
||||||
|
gpgrt_annotate_leaked_object (name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
else
|
||||||
return GNUPG_BINDIR;
|
return GNUPG_BINDIR;
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
}
|
}
|
||||||
@ -991,6 +1170,20 @@ gnupg_libexecdir (void)
|
|||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
return gnupg_bindir ();
|
return gnupg_bindir ();
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
#else /*!HAVE_W32_SYSTEM*/
|
||||||
|
static char *name;
|
||||||
|
const char *rdir;
|
||||||
|
|
||||||
|
rdir = unix_rootdir ();
|
||||||
|
if (rdir)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
name = xstrconcat (rdir, DIRSEP_S "libexec", NULL);
|
||||||
|
gpgrt_annotate_leaked_object (name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
else
|
||||||
return GNUPG_LIBEXECDIR;
|
return GNUPG_LIBEXECDIR;
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
}
|
}
|
||||||
@ -998,9 +1191,9 @@ gnupg_libexecdir (void)
|
|||||||
const char *
|
const char *
|
||||||
gnupg_libdir (void)
|
gnupg_libdir (void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
static char *name;
|
static char *name;
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
if (!name)
|
if (!name)
|
||||||
{
|
{
|
||||||
name = xstrconcat (w32_rootdir (), DIRSEP_S "lib" DIRSEP_S "gnupg", NULL);
|
name = xstrconcat (w32_rootdir (), DIRSEP_S "lib" DIRSEP_S "gnupg", NULL);
|
||||||
@ -1008,6 +1201,19 @@ gnupg_libdir (void)
|
|||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
#else /*!HAVE_W32_SYSTEM*/
|
||||||
|
const char *rdir;
|
||||||
|
|
||||||
|
rdir = unix_rootdir ();
|
||||||
|
if (rdir)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
name = xstrconcat (rdir, DIRSEP_S "lib", DIRSEP_S, "gnupg", NULL);
|
||||||
|
gpgrt_annotate_leaked_object (name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
else
|
||||||
return GNUPG_LIBDIR;
|
return GNUPG_LIBDIR;
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
}
|
}
|
||||||
@ -1015,9 +1221,9 @@ gnupg_libdir (void)
|
|||||||
const char *
|
const char *
|
||||||
gnupg_datadir (void)
|
gnupg_datadir (void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
static char *name;
|
static char *name;
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
if (!name)
|
if (!name)
|
||||||
{
|
{
|
||||||
name = xstrconcat (w32_rootdir (), DIRSEP_S "share" DIRSEP_S "gnupg",
|
name = xstrconcat (w32_rootdir (), DIRSEP_S "share" DIRSEP_S "gnupg",
|
||||||
@ -1026,6 +1232,19 @@ gnupg_datadir (void)
|
|||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
#else /*!HAVE_W32_SYSTEM*/
|
||||||
|
const char *rdir;
|
||||||
|
|
||||||
|
rdir = unix_rootdir ();
|
||||||
|
if (rdir)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
name = xstrconcat (rdir, DIRSEP_S "share" DIRSEP_S "gnupg", NULL);
|
||||||
|
gpgrt_annotate_leaked_object (name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
else
|
||||||
return GNUPG_DATADIR;
|
return GNUPG_DATADIR;
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
}
|
}
|
||||||
@ -1034,9 +1253,9 @@ gnupg_datadir (void)
|
|||||||
const char *
|
const char *
|
||||||
gnupg_localedir (void)
|
gnupg_localedir (void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
static char *name;
|
static char *name;
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
if (!name)
|
if (!name)
|
||||||
{
|
{
|
||||||
name = xstrconcat (w32_rootdir (), DIRSEP_S "share" DIRSEP_S "locale",
|
name = xstrconcat (w32_rootdir (), DIRSEP_S "share" DIRSEP_S "locale",
|
||||||
@ -1045,6 +1264,19 @@ gnupg_localedir (void)
|
|||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
#else /*!HAVE_W32_SYSTEM*/
|
||||||
|
const char *rdir;
|
||||||
|
|
||||||
|
rdir = unix_rootdir ();
|
||||||
|
if (rdir)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
name = xstrconcat (rdir, DIRSEP_S "share" DIRSEP_S "locale", NULL);
|
||||||
|
gpgrt_annotate_leaked_object (name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
else
|
||||||
return LOCALEDIR;
|
return LOCALEDIR;
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
}
|
}
|
||||||
@ -1171,7 +1403,10 @@ static int gnupg_module_name_called;
|
|||||||
* be called before any invocation of 'gnupg_module_name', and must
|
* be called before any invocation of 'gnupg_module_name', and must
|
||||||
* not be called twice. It can be used by test suites to make sure
|
* not be called twice. It can be used by test suites to make sure
|
||||||
* the components from the build directory are used instead of
|
* the components from the build directory are used instead of
|
||||||
* potentially outdated installed ones. */
|
* potentially outdated installed ones.
|
||||||
|
* Fixme: It might be better to make use of the newer gpgconf.ctl feature
|
||||||
|
* for regression testing.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
gnupg_set_builddir (const char *newdir)
|
gnupg_set_builddir (const char *newdir)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user