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:
committed by
Sergei Golubchik
parent
895b28d672
commit
003c3b24f0
@@ -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
|
||||
{
|
||||
|
||||
@@ -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})
|
||||
|
||||
85
unittest/mysys/my_symlink-t.c
Normal file
85
unittest/mysys/my_symlink-t.c
Normal 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();
|
||||
}
|
||||
Reference in New Issue
Block a user