Add portable path tokens

Add USERCONFIG, COMMONCONFIG, LIBDIR, BINDIR, LIBEXEC, SBINDIR tokens.
This commit is contained in:
Asanka Herath
2009-09-14 15:02:40 -04:00
committed by Love Hornquist Astrand
parent 93445a8133
commit 6073ca9a28

View File

@@ -33,7 +33,7 @@
#include <shlobj.h> #include <shlobj.h>
#include <sddl.h> #include <sddl.h>
#define PTYPE int typedef int PTYPE;
/** /**
* Expand a %{TEMP} token * Expand a %{TEMP} token
@@ -47,7 +47,7 @@
* the returned path may or may not exist. * the returned path may or may not exist.
*/ */
static int static int
_expand_temp_folder(krb5_context context, PTYPE param, char ** ret) _expand_temp_folder(krb5_context context, PTYPE param, const char * postfix, char ** ret)
{ {
TCHAR tpath[MAX_PATH]; TCHAR tpath[MAX_PATH];
size_t len; size_t len;
@@ -56,7 +56,7 @@ _expand_temp_folder(krb5_context context, PTYPE param, char ** ret)
if (context) if (context)
krb5_set_error_string(context, "Failed to get temporary path (GLE=%d)", krb5_set_error_string(context, "Failed to get temporary path (GLE=%d)",
GetLastError()); GetLastError());
return 1; return EINVAL;
} }
len = strlen(tpath); len = strlen(tpath);
@@ -69,12 +69,57 @@ _expand_temp_folder(krb5_context context, PTYPE param, char ** ret)
if (*ret == NULL) { if (*ret == NULL) {
if (context) if (context)
krb5_set_error_string(context, "strdup - Out of memory"); krb5_set_error_string(context, "strdup - Out of memory");
return 1; return ENOMEM;
} }
return 0; return 0;
} }
extern HINSTANCE _krb5_hInstance;
/**
* Expand a %{BINDIR} token
*
* This is also used to expand a few other tokens on Windows, since
* most of the executable binaries end up in the same directory. The
* "bin" directory is considered to be the directory in which the
* krb5.dll is located.
*/
static int
_expand_bin_dir(krb5_context context, PTYPE param, const char * postfix, char ** ret)
{
TCHAR path[MAX_PATH];
TCHAR *lastSlash;
DWORD nc;
nc = GetModuleFileName(_krb5_hInstance, path, sizeof(path)/sizeof(path[0]));
if (nc == 0 ||
nc == sizeof(path)/sizeof(path[0])) {
return EINVAL;
}
lastSlash = strrchr(path, '\\');
if (lastSlash != NULL) {
TCHAR *fslash = strrchr(lastSlash, '/');
if (fslash != NULL)
lastSlash = fslash;
*lastSlash = '\0';
}
if (postfix) {
if (strlcat(path, postfix, sizeof(path)/sizeof(path[0])) >= sizeof(path)/sizeof(path[0]))
return EINVAL;
}
*ret = strdup(path);
if (*ret == NULL)
return ENOMEM;
return 0;
}
/** /**
* Expand a %{USERID} token * Expand a %{USERID} token
* *
@@ -91,9 +136,9 @@ _expand_temp_folder(krb5_context context, PTYPE param, char ** ret)
* *
*/ */
static int static int
_expand_userid(krb5_context context, PTYPE param, char ** ret) _expand_userid(krb5_context context, PTYPE param, const char * postfix, char ** ret)
{ {
int rv = 1; int rv = EINVAL;
HANDLE hThread = NULL; HANDLE hThread = NULL;
HANDLE hToken = NULL; HANDLE hToken = NULL;
PTOKEN_OWNER pOwner = NULL; PTOKEN_OWNER pOwner = NULL;
@@ -181,21 +226,34 @@ _expand_userid(krb5_context context, PTYPE param, char ** ret)
return rv; return rv;
} }
/**
* Expand a %{null} token
*
* The expansion of a %{null} token is always the empty string.
*/
static int static int
_expand_null(krb5_context context, PTYPE param, char ** ret) _expand_null(krb5_context context, PTYPE param, const char * postfix, char ** ret)
{ {
*ret = strdup(""); *ret = strdup("");
if (*ret == NULL) { if (*ret == NULL) {
if (context) if (context)
krb5_set_error_string(context, "Out of memory"); krb5_set_error_string(context, "Out of memory");
return 1; return ENOMEM;
} }
return 0; return 0;
} }
/**
* Expand a folder identified by a CSIDL
*
* Parameters:
*
* @param[in] folder A CSIDL value identifying the folder to be
* returned.
*/
static int static int
_expand_csidl(krb5_context context, PTYPE folder, char ** ret) _expand_csidl(krb5_context context, PTYPE folder, const char * postfix, char ** ret)
{ {
TCHAR path[MAX_PATH]; TCHAR path[MAX_PATH];
size_t len; size_t len;
@@ -211,11 +269,16 @@ _expand_csidl(krb5_context context, PTYPE folder, char ** ret)
if (len > 0 && path[len - 1] == '\\') if (len > 0 && path[len - 1] == '\\')
path[len - 1] = '\0'; path[len - 1] = '\0';
if (postfix &&
strlcat(path, postfix, sizeof(path)/sizeof(path[0])) >= sizeof(path)/sizeof(path[0])) {
return ENOMEM;
}
*ret = strdup(path); *ret = strdup(path);
if (*ret == NULL) { if (*ret == NULL) {
if (context) if (context)
krb5_set_error_string(context, "Out of memory"); krb5_set_error_string(context, "Out of memory");
return 1; return ENOMEM;
} }
return 0; return 0;
} }
@@ -227,14 +290,18 @@ static const struct token {
#define FTYPE_SPECIAL 1 #define FTYPE_SPECIAL 1
PTYPE param; PTYPE param;
const char * postfix;
int (*exp_func)(krb5_context, PTYPE, char **); int (*exp_func)(krb5_context, PTYPE, const char *, char **);
#define CSIDL(C) FTYPE_CSIDL, C, _expand_csidl #define CSIDLP(C,P) FTYPE_CSIDL, C, P, _expand_csidl
#define CSIDL(C) CSIDLP(C, NULL)
#define SPECIAL(f) FTYPE_SPECIAL, 0, f #define SPECIALP(f, P) FTYPE_SPECIAL, 0, P, f
#define SPECIAL(f) SPECIALP(f, NULL)
} tokens[] = { } tokens[] = {
/* Windows only -- */
{"APPDATA", CSIDL(CSIDL_APPDATA)}, {"APPDATA", CSIDL(CSIDL_APPDATA)},
/* Roaming application data (for current user) */ /* Roaming application data (for current user) */
@@ -249,6 +316,34 @@ static const struct token {
{"WINDOWS", CSIDL(CSIDL_WINDOWS)}, {"WINDOWS", CSIDL(CSIDL_WINDOWS)},
/* Windows folder */ /* Windows folder */
/* -- end Windows only */
{"USERCONFIG", CSIDLP(CSIDL_APPDATA, "\\" PACKAGE)},
/* Per user Heimdal configuration file path */
{"COMMONCONFIG", CSIDLP(CSIDL_COMMON_APPDATA, "\\" PACKAGE)},
/* Common Heimdal configuration file path */
{"LIBDIR", SPECIAL(_expand_bin_dir)},
/* Expands to the "lib" directory. On
Windows this is treated the same as
the "bin" directory. */
{"BINDIR", SPECIAL(_expand_bin_dir)},
/* Expands to the "bin" directory. On
Windows this is treated the same as
the "bin" directory. */
{"LIBEXEC", SPECIAL(_expand_bin_dir)},
/* Expands to the "libexec"
directory. On Windows, this is
treated the same as the "bin"
directory. */
{"SBINDIR", SPECIAL(_expand_bin_dir)},
/* Expands to the "sbin" directory.
On Windows, this is treated the
same as the "bin" directory. */
{"TEMP", SPECIAL(_expand_temp_folder)}, {"TEMP", SPECIAL(_expand_temp_folder)},
/* Temporary files folder */ /* Temporary files folder */
@@ -273,20 +368,32 @@ _expand_token(krb5_context context, const char * token, const char * token_end,
*ret = NULL; *ret = NULL;
if (token[0] != '%' || token[1] != '{' || token_end[0] != '}') { if (token[0] != '%' || token[1] != '{' || token_end[0] != '}' ||
token_end - token <= 2) {
if (context) if (context)
krb5_set_error_string(context, "Invalid token."); krb5_set_error_string(context, "Invalid token.");
return 1; return EINVAL;
} }
for (i=0; i < sizeof(tokens)/sizeof(tokens[0]); i++) { for (i=0; i < sizeof(tokens)/sizeof(tokens[0]); i++) {
if (!strncmp(token+2, tokens[i].tok, (token_end - token) - 2)) if (!strncmp(token+2, tokens[i].tok, (token_end - token) - 2))
return tokens[i].exp_func(context, tokens[i].param, ret); return tokens[i].exp_func(context, tokens[i].param, tokens[i].postfix, ret);
} }
if (context) if (context)
krb5_set_error_string(context, "Invalid token."); krb5_set_error_string(context, "Invalid token.");
return 1; return EINVAL;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_free_path(krb5_context context,
char * path)
{
if (path == NULL)
return EINVAL;
free(path);
return 0;
} }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
@@ -322,14 +429,14 @@ _krb5_expand_path_tokens(krb5_context context,
*ppath_out = NULL; *ppath_out = NULL;
if (context) if (context)
krb5_set_error_string(context, "variable missing }"); krb5_set_error_string(context, "variable missing }");
return KRB5_CONFIG_BADFORMAT; return EINVAL;
} }
if (_expand_token(context, tok_begin, tok_end, &append)) { if (_expand_token(context, tok_begin, tok_end, &append)) {
if (*ppath_out) if (*ppath_out)
free(*ppath_out); free(*ppath_out);
*ppath_out = NULL; *ppath_out = NULL;
return KRB5_CONFIG_BADFORMAT; return EINVAL;
} }
path_left = tok_end + 1; path_left = tok_end + 1;