From 25e4f9e8cf6aa80de16ba5f25cfc9b3da7c2c368 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Thu, 18 Feb 2016 12:46:25 +0100 Subject: [PATCH] fix undocumented unexpected LokiInitPaths --- tools/quake3/q3map2/path_init.c | 36 +++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/tools/quake3/q3map2/path_init.c b/tools/quake3/q3map2/path_init.c index 16758c6d..be28c203 100644 --- a/tools/quake3/q3map2/path_init.c +++ b/tools/quake3/q3map2/path_init.c @@ -122,7 +122,6 @@ void LokiInitPaths( char *argv0 ){ strcpy( installPath, "../" ); #else char temp[ MAX_OS_PATH ]; - char last0[ 2 ]; char *path; char *last; qboolean found; @@ -136,6 +135,25 @@ void LokiInitPaths( char *argv0 ){ argv0 = strrchr( argv0, '/' ) + 1; } else if ( path ) { + + /* + This code has a special behavior when q3map2 is a symbolic link. + + For each dir in ${PATH} (example: "/usr/bin", "/usr/local/bin" if ${PATH} == "/usr/bin:/usr/local/bin"), + it looks for "${dir}/q3map2" (file exists and is executable), + then it uses "dirname(realpath("${dir}/q3map2"))/../" as installPath. + + So, if "/usr/bin/q3map2" is a symbolic link to "/opt/radiant/tools/q3map2", + it will find the installPath "/usr/share/radiant/", + so q3map2 will look for "/opt/radiant/baseq3" to find paks. + + More precisely, it looks for "${dir}/${argv[0]}", + so if "/usr/bin/q3map2" is a symbolic link to "/opt/radiant/tools/q3map2", + and if "/opt/radiant/tools/q3ma2" is a symbolic link to "/opt/radiant/tools/q3map2.x86_64", + it will use "dirname("/opt/radiant/tools/q3map2.x86_64")/../" as path, + so it will use "/opt/radiant/" as installPath, which will be expanded later to "/opt/radiant/baseq3" to find paks. + */ + found = qfalse; last = path; @@ -157,17 +175,20 @@ void LokiInitPaths( char *argv0 ){ path++; } + /* concatenate */ if ( last > ( path + 1 ) ) { - Q_strncat( temp, sizeof( temp ), path, ( last - path ) ); + // +1 hack: Q_strncat calls Q_strncpyz that expects a len including '\0' + // so that extraneous char will be rewritten by '\0', so it's ok. + // Also, in this case this extraneous char is always ':' or '\0', so it's ok. + Q_strncat( temp, sizeof( temp ), path, ( last - path + 1) ); Q_strcat( temp, sizeof( temp ), "/" ); } - Q_strcat( temp, sizeof( temp ), "./" ); Q_strcat( temp, sizeof( temp ), argv0 ); /* verify the path */ if ( access( temp, X_OK ) == 0 ) { - found++; + found = qtrue; } path = last + 1; } @@ -175,9 +196,12 @@ void LokiInitPaths( char *argv0 ){ /* flake */ if ( realpath( temp, installPath ) ) { - /* q3map is in "tools/" */ + /* + if "q3map2" is "/opt/radiant/tools/q3map2", + installPath is "/opt/radiant" + */ + *( strrchr( installPath, '/' ) ) = '\0'; *( strrchr( installPath, '/' ) ) = '\0'; - *( strrchr( installPath, '/' ) + 1 ) = '\0'; } #endif } -- 2.39.2