Mail Archives: djgpp-workers/2003/01/18/09:26:58
This is a multi-part message in MIME format.
--------------070504000101040808090705
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Richard Dawe wrote:
>>Well, maybe I'm on drugs,
>
>
> Maybe the problem is that I'm not on drugs (caffeine)! ;)
Nope, it's quite clear that the problems are on my side :)
> I reverted my changes and I'm now running fileutils, sh-utils and textutils
> built with DJGPP CVS HEAD. But the test program still fails for me:
[...]
> FAIL
>
> Do you expect this test to fail?
No I don't, but I didn't see any failures, probably because we're
running two different test programs - I've cleaned up the test program a
bit. I'm attaching it. Could you tell if it fails with your testcases?
> * symlinks between drives;
Will see, the problem is that not everybody has multiple drives...
> * paths using /dev/<drive> instead of <drive>:;
> * paths using environment variables in paths - e.g.: /dev/env/FOO.
OK. Will add those tests too.
> Basically tests that mix absolute and relative paths in every possible way.
> Most of the tests are too "normal" at the moment IMHO. Not that I am
> criticising.
See that part about drugs above :)
> It's just that you may not have thought of bizarre filenames as
> much as I have, while testing fileutils, etc. ;)
Right. I was trying to make up tests according to the problem
description, and probably failed.
>> /* FIXME below, but note that you're insane to run this test
>>really that deep :) */
>> test_success("c:../../../../../../../../../../../../../../../link",
>>"c:/autoexec.bat");
> Why is this marked as a FIXME?
>
> Why is it insane? Sure, having more than 8 levels of directories is
> unsupported on DOS, but the code should cope with excess ".."s.
No I mean, the test will not work as expected if there won't be enough
'../' to try to get above c:/ from the cwd on C:. I tried to make this
test to expose the bug you're talking about - isn't this the same
situation? (relative path with drive letter and trying to get above the
root).
--
Laurynas
--------------070504000101040808090705
Content-Type: text/plain;
name="test.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="test.c"
/* Testsuite for __solve_symlinks()
* There are following success tests:
* 1. Simple case with symlink in current directory
* 2. Recursive symlinks
* 3. Symlink in subdirectory
* 4. Real file in symlinked directory
* 5. Symlink in symlinked directory
* 6. Symlink in symlinked directory to UNIX-style absolute path
* 7. The same with DOS-style absolute path
* 8. Real file in a symlink subdir in a symlink subdir
* 9. Symlink in a subdir to file in an upper dir
* 10. 3 with a double-slash
* 11. 7 with a double-slash
* 12. 8 with a double-slash
* 13. Regular file
* Any unhandled cases are more than welcome.
*
* There are some tests based on the current-working directory:
* 14. An absolute path using '..' to navigate through the directories.
* 15. A relative path using a drive letter and '..'.
* 16. A relative path using a drive letter and one too many '..' over 2.
*
* And following are failure tests:
* 17. Simple symlink loop.
* 18. Symlink loop across directories
*
* These are absolute path tests:
* 19. /../symlink should be expanded correctly
*
* TODO: device a test, where symlink expands to absolute path, which,
* in turn, has symlinks somewhere inside. There was such a test once, but
* it was broken - it depended on testsuite location.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <libc/symlink.h>
#include <sys/stat.h>
/* Global test index */
static unsigned test_num = 0;
/* 1, if all testsuite passes */
static int full_pass = 1;
typedef struct {
const char *src; /* Source: includes symlink(s) */
const char *target; /* Target of the symlink */
} test_success_t;
static const test_success_t tests_success[] = {
{ "test1", "file1" },
{ "test4", "file2" },
{ "dir1/test1", "dir1/file1" },
{ "dirtest/file1", "dir1/file1" },
{ "dirtest/test1", "dir1/file1" },
{ "dirtest/test2", "/dev/env/DJDIR/bin/gcc.exe" },
{ "dirtest/test3", "c:\\autoexec.bat" },
{ "dirtest/test6/file", "dir1/dir2/file" },
{ "dir1/test7", "file" },
/* Check that __solve_symlinks copes with double-slashes. */
{ "dir1//test1", "dir1/file1" },
{ "dirtest//test3", "c:\\autoexec.bat" },
{ "dirtest//test6//file", "dir1/dir2/file" },
/* Non-symlinks */
{ "makefile", "makefile" }
};
static const int n_tests_success
= sizeof(tests_success) / sizeof(tests_success[0]);
static const char *tests_failure[] = {
"fail1",
"fail3"
};
static const int n_tests_failure
= sizeof(tests_failure) / sizeof(tests_failure[0]);
static void test_success(const char * slink,
const char * expect);
static void test_failure(const char * slink);
int main(void)
{
int i;
if (!__file_exists("test1") || !__file_exists("test4") ||
!__file_exists("test5") || !__file_exists("dirtest") ||
!__file_exists("fail1") || !__file_exists("fail2") ||
!__file_exists("fail3") || !__file_exists("dir1/fail1") ||
!__file_exists("dir1/test1") || !__file_exists("dir1/test2") ||
!__file_exists("dir1/test3") || !__file_exists("dir1/test4") ||
!__file_exists("dir1/test5") || !__file_exists("dir1/test6") ||
!__file_exists("dir1/test7") || access("dir1/dir2", D_OK))
{
fprintf(stderr, "Required data files not found");
exit(1);
}
puts("Running __solve_symlinks() and readlink() testsuite:");
puts("Tests that check __solve_symlinks() works:");
for (i = 0; i < n_tests_success; i++)
test_success(tests_success[i].src, tests_success[i].target);
/* Construct some tests with relative paths. */
puts("Tests that check __solve_symlinks() based on current directory:");
{
char cwd[PATH_MAX], path[PATH_MAX + 1];
test_success_t test;
int n_slashes = 0;
char *cwd_without_drive = cwd;
char *ptr = NULL;
if (getcwd(cwd, sizeof(cwd) - 1) == NULL)
{
fprintf(stderr, "Error: Unable to get current working directory\n");
return(EXIT_FAILURE);
}
if (cwd[0] && (cwd[1] == ':'))
cwd_without_drive = cwd + 2;
/* Count the number of slashes in the current directory => number
* of '..' we can use. */
for (ptr = strpbrk(cwd, "/\\"), n_slashes = 0;
ptr != NULL;
ptr = strpbrk(ptr + 1, "/\\"), n_slashes++) {;}
/* Try tests_success[0] with an absolute path with '..'. */
test_num++;
strcpy(path, cwd);
for (i = 0; i < n_slashes; i++)
{
strcat(path, "/..");
}
strcat(path, cwd_without_drive);
strcat(path, "/");
strcat(path, tests_success[0].src);
test.src = path;
test.target = tests_success[0].target;
printf("Test %d: Solving %s\n", test_num, test.src);
test_success(test.src, test.target);
/* Try tests_success[0] with a drive-letter and relative path
* with '..'. */
test_num++;
if (cwd[0] && (cwd[1] == ':'))
{
path[0] = cwd[0];
path[1] = cwd[1];
path[2] = '\0';
for (i = 0; i < n_slashes; i++)
{
if (i)
strcat(path, "/..");
else
strcat(path, "..");
}
strcat(path, cwd_without_drive);
strcat(path, "/");
strcat(path, tests_success[0].src);
test.src = path;
test.target = tests_success[0].target;
printf("Test %d: Solving %s\n", test_num, test.src);
test_success(test.src, test.target);
}
else
{
printf("Test %d: No drive letter - skipping\n", test_num);
}
/* Try tests_success[0] with a drive-letter and relative path
* with too many '..'. */
test_num++;
if (cwd[0] && (cwd[1] == ':'))
{
path[0] = cwd[0];
path[1] = cwd[1];
path[2] = '\0';
for (i = 0; i <= n_slashes; i++)
{
if (i)
strcat(path, "/..");
else
strcat(path, "..");
}
strcat(path, cwd_without_drive);
strcat(path, "/");
strcat(path, tests_success[0].src);
test.src = path;
test.target = tests_success[0].target;
printf("Test %d: Solving %s\n", test_num, test.src);
test_success(test.src, test.target);
}
else
{
printf("Test %d: No drive letter - skipping\n", test_num);
}
}
puts("Tests that check __solve_symlinks() failure cases:");
for (i = 0; i < n_tests_failure; i++)
test_failure(tests_failure[i]);
puts("2003 tests:");
symlink("c:/autoexec.bat", "/link");
test_success("c:/link", "c:/autoexec.bat");
test_success("/link", "c:/autoexec.bat");
test_success("c://link", "c:/autoexec.bat");
test_success("//link", "c:/autoexec.bat");
test_success("c:/./link", "c:/autoexec.bat");
test_success("/../link", "c:/autoexec.bat");
test_success("c:/../link", "c:/autoexec.bat");
test_success("/../../link", "c:/autoexec.bat");
test_success("c:/../../link", "c:/autoexec.bat");
/* FIXME below, but note that you're insane to run this test really that deep :) */
test_success("c:../../../../../../../../../../../../../../../link", "c:/autoexec.bat");
mkdir("c:/tdir", S_IWUSR);
symlink("c:/config.sys", "c:/tdir/link");
test_success("c:/tdir/link", "c:/config.sys");
test_success("/tdir/link", "c:/config.sys");
test_success("c:/tdir/../.././tdir/link", "c:/config.sys");
test_success("/tdir/..//../.././../../tdir/link", "c:/config.sys");
/* FIXME below, but note that you're insane to run this test really that deep :) */
test_success("c:../../../../../../../../../../../../../../../tdir/link", "c:/config.sys");
unlink("c:/tdir/link");
rmdir("c:/tdir");
unlink("/link");
symlink("/dev/env/DJDIR/djgpp.env", "/dev/env/DJDIR/link");
test_success("/dev/env/DJDIR/link", "/dev/env/DJDIR/djgpp.env");
test_success("/dev/env/DJDIR/../djgpp/link", "/dev/env/DJDIR/djgpp.env"); /* FIXME */
unlink("/dev/env/DJDIR/link");
if (full_pass) {
puts("PASS");
return(EXIT_SUCCESS);
} else {
puts("FAIL");
return(EXIT_FAILURE);
}
}
static void test_success(const char * slink,
const char * expect)
{
char real_name[FILENAME_MAX + 1];
char real_fixed[FILENAME_MAX + 1];
char expect_fixed[FILENAME_MAX + 1];
char err_buf[50];
++test_num;
if (!__solve_symlinks(slink, real_name))
{
sprintf(err_buf, "Test %d failed ", test_num);
perror(err_buf);
full_pass = 0;
}
_fixpath(expect, expect_fixed);
_fixpath(real_name, real_fixed);
if (strcmp(real_fixed, expect_fixed))
{
fprintf(stderr,
"Test %d failed - __solve_symlinks returns wrong resolved path\n",
test_num);
fprintf(stderr, "Returned path: %s\n", real_fixed);
fprintf(stderr, "Expected path: %s\n", expect_fixed);
full_pass = 0;
}
printf("Test %d passed\n", test_num);
}
static void test_failure(const char * slink)
{
char buf[FILENAME_MAX + 1];
char err_buf[50];
errno = 0;
test_num++;
if (__solve_symlinks(slink, buf))
{
fprintf(stderr,
"Test %d failed - __solve_symlinks suceeds when it should fail\n",
test_num);
}
if (errno != ELOOP)
{
sprintf(err_buf, "Test %d failed - wrong errno returned ", test_num);
perror(err_buf);
}
printf("Test %d passed\n", test_num);
}
--------------070504000101040808090705--
- Raw text -