1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-39122 Fix my_realpath to treat empty string as current directory

my_realpath() uses my_load_path() as a fallback. my_load_path()
replaces empty string with a current directory. But my_realpath()
didn't do it itself so the result was inconsistent: empty string was
replaced with a current directory, but if the current directory was
symlinked, symlinks were not resolved (as they were for any other,
non-empty, path, including ".").

Fix my_realpath() to treat empty string consisently with all
other paths - replace with a current dir and resolve symlinks too.
This commit is contained in:
Andrzej Jarzabek
2026-03-24 16:51:07 +00:00
committed by Sergei Golubchik
parent 895b28d672
commit 003c3b24f0
3 changed files with 100 additions and 7 deletions

View File

@@ -126,14 +126,19 @@ int my_is_symlink(const char *filename __attribute__((unused)))
}
/*
Resolve all symbolic links in path
'to' may be equal to 'filename'
Resolve all symbolic links in path.
to is guaranteed to never set to a string longer than FN_REFLEN
(including the end \0)
If path is relative, assume current directory and replace with absolute.
If filename is empty string, resolve path to current directory.
Resolved path is placed in the 'to' buffer, and is guaranteed to never
be longer than FN_REFLEN (including the end \0); 'to' may be equal to
'filename'.
On error returns -1, unless error is file not found, in which case it
is 1.
is 1; 'to' will then be populated with a fallback value as specified by
my_load_path() with null own_path_prefix; symlinks will not be
resolved.
Sets my_errno to specific error number.
*/
@@ -144,10 +149,12 @@ int my_realpath(char *to, const char *filename, myf MyFlags)
int result=0;
char buff[BUFF_LEN];
char *ptr;
static const char cur_dir[] = {FN_CURLIB, '\0'};
DBUG_ENTER("my_realpath");
DBUG_PRINT("info",("executing realpath"));
if ((ptr=realpath(filename,buff)))
/* realpath won't accept empty string - use "." instead */
if ((ptr=realpath(filename[0] ? filename : cur_dir, buff)))
strmake(to, ptr, FN_REFLEN-1);
else
{

View File

@@ -14,7 +14,8 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
MY_ADD_TESTS(base64 bitmap byte_order crc32 dynstring lf my_atomic my_getopt
my_malloc my_rdtsc queues stack_allocation stacktrace waiting_threads
my_malloc my_rdtsc my_symlink queues stack_allocation stacktrace
waiting_threads
LINK_LIBRARIES mysys)
MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys)
ADD_DEFINITIONS(${SSL_DEFINES})

View File

@@ -0,0 +1,85 @@
#include <my_global.h>
#include <my_sys.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "tap.h"
static void test_my_realpath()
{
#ifndef HAVE_REALPATH
skip(2, "realpath not supported");
return;
#else
char cwd[PATH_MAX];
char *resolved_cwd;
char result[FN_REFLEN];
char link_name[64] = {0};
int errcode;
if (getcwd(cwd, sizeof(cwd)) == NULL)
{
diag("getcwd() failed: %s", strerror(errno));
skip(2, "getcwd() failed");
return;
}
resolved_cwd= realpath(cwd, NULL);
if (!resolved_cwd)
{
diag("realpath() failed: %s", strerror(errno));
skip(2, "realpath() failed");
return;
}
/* Call my_realpath with empty string in current working directory,
expecting resolved abolute path to that directory */
errcode= my_realpath(result, "", MYF(0));
ok(errcode == 0, "my_realpath returned error code: %d", errcode);
ok(!strcmp(result, resolved_cwd),
"Output of my_realpath: %s, expected: %s",
result, resolved_cwd);
/* Creae a symlink, chdir to it and resolve empty string */
/* Generate a unique name for the symlink */
srand(time(NULL));
snprintf(link_name, sizeof(link_name), "my_link_%d.%06d", getpid(), rand() % 1000000);
if (symlink(cwd, link_name) != 0)
{
diag("symlink() failed: %s", strerror(errno));
skip(1, "symlink() failed");
goto cwd_cleanup;
}
if (chdir(link_name) != 0)
{
diag("chdir() failed: %s", strerror(errno));
skip(1, "chdir() failed");
goto link_cleanup;
}
errcode= my_realpath(result, "", MYF(0));
ok(errcode == 0, "my_realpath returned error code: %d", errcode);
ok(!strcmp(result, resolved_cwd),
"Output of my_realpath: %s, expected: %s",
result, resolved_cwd);
link_cleanup:
unlink(link_name);
cwd_cleanup:
free(resolved_cwd);
#endif
}
int main(int argc __attribute__((unused)),char *argv[])
{
MY_INIT(argv[0]);
plan(4);
test_my_realpath();
my_end(0);
return exit_status();
}