mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-15 04:20:28 +08:00
5a82c74822
Also, change sources.redhat.com to sourceware.org. This patch was automatically generated by running the following shell script, which uses GNU sed, and which avoids modifying files imported from upstream: sed -ri ' s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g ' \ $(find $(git ls-files) -prune -type f \ ! -name '*.po' \ ! -name 'ChangeLog*' \ ! -path COPYING ! -path COPYING.LIB \ ! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \ ! -path manual/texinfo.tex ! -path scripts/config.guess \ ! -path scripts/config.sub ! -path scripts/install-sh \ ! -path scripts/mkinstalldirs ! -path scripts/move-if-change \ ! -path INSTALL ! -path locale/programs/charmap-kw.h \ ! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \ ! '(' -name configure \ -execdir test -f configure.ac -o -f configure.in ';' ')' \ ! '(' -name preconfigure \ -execdir test -f preconfigure.ac ';' ')' \ -print) and then by running 'make dist-prepare' to regenerate files built from the altered files, and then executing the following to cleanup: chmod a+x sysdeps/unix/sysv/linux/riscv/configure # Omit irrelevant whitespace and comment-only changes, # perhaps from a slightly-different Autoconf version. git checkout -f \ sysdeps/csky/configure \ sysdeps/hppa/configure \ sysdeps/riscv/configure \ sysdeps/unix/sysv/linux/csky/configure # Omit changes that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines git checkout -f \ sysdeps/powerpc/powerpc64/ppc-mcount.S \ sysdeps/unix/sysv/linux/s390/s390-64/syscall.S # Omit change that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
240 lines
6.5 KiB
C
240 lines
6.5 KiB
C
/* Test for ftw function related to symbolic links for BZ #23501
|
|
Copyright (C) 2019 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#include <ftw.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#include <support/support.h>
|
|
#include <support/check.h>
|
|
|
|
#define TSTDIR "tst-ftw-lnk.d"
|
|
|
|
static void
|
|
un (const char *file)
|
|
{
|
|
struct stat st;
|
|
/* Does the file exist? */
|
|
if (lstat (file, &st) < 0
|
|
&& errno == ENOENT)
|
|
return;
|
|
|
|
/* If so, try to remove it. */
|
|
if (unlink (file) < 0)
|
|
FAIL_EXIT1 ("Unable to unlink %s", file);
|
|
}
|
|
|
|
static void
|
|
debug_cb (const char *which, const char *fpath,
|
|
const struct stat *sb, int typeflags)
|
|
{
|
|
const char *sb_type = "???";
|
|
const char *ftw_type = "???";
|
|
|
|
/* Coding style here is intentionally "wrong" to increase readability. */
|
|
if (S_ISREG (sb->st_mode)) sb_type = "REG";
|
|
if (S_ISDIR (sb->st_mode)) sb_type = "DIR";
|
|
if (S_ISLNK (sb->st_mode)) sb_type = "LNK";
|
|
|
|
if (typeflags == FTW_F) ftw_type = "F";
|
|
if (typeflags == FTW_D) ftw_type = "D";
|
|
if (typeflags == FTW_DNR) ftw_type = "DNR";
|
|
if (typeflags == FTW_DP) ftw_type = "DP";
|
|
if (typeflags == FTW_NS) ftw_type = "NS";
|
|
if (typeflags == FTW_SL) ftw_type = "SL";
|
|
if (typeflags == FTW_SLN) ftw_type = "SLN";
|
|
|
|
printf ("%s %5d %-3s %-3s %s\n", which, (int)(sb->st_ino % 100000), sb_type, ftw_type, fpath);
|
|
}
|
|
|
|
int good_cb = 0;
|
|
#define EXPECTED_GOOD 12
|
|
|
|
/* See if the stat buffer SB refers to the file AS_FNAME. */
|
|
static void
|
|
check_same_stats (const struct stat *sb, const char *as_fname)
|
|
{
|
|
struct stat as;
|
|
if (lstat (as_fname, &as) < 0)
|
|
FAIL_EXIT1 ("unable to stat %s for comparison", as_fname);
|
|
|
|
if (as.st_mode == sb->st_mode
|
|
&& as.st_ino == sb->st_ino
|
|
&& as.st_size == sb->st_size)
|
|
good_cb ++;
|
|
else
|
|
printf ("statbuf data doesn't match %s\n", as_fname);
|
|
}
|
|
|
|
static int
|
|
callback_phys (const char *fpath, const struct stat *sb, int typeflags, struct FTW *ftwbuf)
|
|
{
|
|
debug_cb ("P", fpath, sb, typeflags);
|
|
|
|
/* This callback is for when the FTW_PHYS flag is set. The results
|
|
should reflect the physical filesystem entry, not what it might
|
|
point to. */
|
|
|
|
/* link1-bad is a dangling symlink, but we're reporting on the link
|
|
anyway (ala lstat ()). */
|
|
if (strcmp (fpath, "./link1-bad") == 0)
|
|
{
|
|
if (S_ISLNK (sb->st_mode) && typeflags == FTW_SL)
|
|
good_cb ++;
|
|
else
|
|
printf ("link1-bad had wrong phys stats\n");
|
|
|
|
check_same_stats (sb, "link1-bad");
|
|
}
|
|
|
|
/* link2-ok is a regular non-dangling symlink. */
|
|
if (strcmp (fpath, "./link2-ok") == 0)
|
|
{
|
|
if (S_ISLNK (sb->st_mode) && typeflags == FTW_SL)
|
|
good_cb ++;
|
|
else
|
|
printf ("link2-ok had wrong phys stats\n");
|
|
|
|
check_same_stats (sb, "link2-ok");
|
|
}
|
|
|
|
/* This is the file link2-ok points to. */
|
|
if (strcmp (fpath, "./link2-tgt") == 0)
|
|
{
|
|
if (S_ISREG (sb->st_mode) && typeflags == FTW_F)
|
|
good_cb ++;
|
|
else
|
|
printf ("link2-tgt had wrong phys stats\n");
|
|
|
|
check_same_stats (sb, "link2-tgt");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
callback_log (const char *fpath, const struct stat *sb, int typeflags, struct FTW *ftwbuf)
|
|
{
|
|
debug_cb ("L", fpath, sb, typeflags);
|
|
|
|
/* This callback is for when the FTW_PHYS flags is NOT set. The
|
|
results should reflect the logical file, i.e. symlinks should be
|
|
followed. */
|
|
|
|
/* We would normally report what link1-bad links to, but link1-bad
|
|
is a dangling symlink. This is an exception to FTW_PHYS in that
|
|
we report FTW_SLN (dangling symlink) but the stat data is
|
|
correctly set to the link itself (ala lstat ()). */
|
|
if (strcmp (fpath, "./link1-bad") == 0)
|
|
{
|
|
if (S_ISLNK (sb->st_mode) && typeflags == FTW_SLN)
|
|
good_cb ++;
|
|
else
|
|
printf ("link1-bad had wrong logical stats\n");
|
|
|
|
check_same_stats (sb, "link1-bad");
|
|
}
|
|
|
|
/* link2-ok points to link2-tgt, so we expect data reflecting
|
|
link2-tgt (ala stat ()). */
|
|
if (strcmp (fpath, "./link2-ok") == 0)
|
|
{
|
|
if (S_ISREG (sb->st_mode) && typeflags == FTW_F)
|
|
good_cb ++;
|
|
else
|
|
printf ("link2-ok had wrong logical stats\n");
|
|
|
|
check_same_stats (sb, "link2-tgt");
|
|
}
|
|
|
|
/* This is the file link2-ok points to. */
|
|
if (strcmp (fpath, "./link2-tgt") == 0)
|
|
{
|
|
if (S_ISREG (sb->st_mode) && typeflags == FTW_F)
|
|
good_cb ++;
|
|
else
|
|
printf ("link2-tgt had wrong logical stats\n");
|
|
|
|
check_same_stats (sb, "link2-tgt");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
do_test (void)
|
|
{
|
|
struct stat st;
|
|
|
|
if (chdir (support_objdir_root) < 0)
|
|
FAIL_EXIT1 ("cannot chdir to objdir root");
|
|
|
|
if (chdir ("io") < 0)
|
|
FAIL_EXIT1 ("cannot chdir to objdir/io subdir");
|
|
|
|
if (stat (TSTDIR, &st) >= 0)
|
|
{
|
|
/* Directory does exist, delete any potential conflicts. */
|
|
if (chdir (TSTDIR) < 0)
|
|
FAIL_EXIT1 ("cannot chdir to %s\n", TSTDIR);
|
|
un ("link1-bad");
|
|
un ("link1-tgt");
|
|
un ("link2-ok");
|
|
un ("link2-tgt");
|
|
}
|
|
else
|
|
{
|
|
/* Directory does not exist, create it. */
|
|
mkdir (TSTDIR, 0777);
|
|
if (chdir (TSTDIR) < 0)
|
|
FAIL_EXIT1 ("cannot chdir to %s\n", TSTDIR);
|
|
}
|
|
|
|
/* At this point, we're inside our test directory, and need to
|
|
prepare it. */
|
|
|
|
if (symlink ("link1-tgt", "link1-bad") < 0)
|
|
FAIL_EXIT1 ("symlink link1-bad failed");
|
|
if (symlink ("link2-tgt", "link2-ok") < 0)
|
|
FAIL_EXIT1 ("symlink link2-ok failed");
|
|
if (open ("link2-tgt", O_RDWR|O_CREAT, 0777) < 0)
|
|
FAIL_EXIT1 ("create of link2-tgt failed");
|
|
|
|
/* Now we run the tests. */
|
|
|
|
nftw (".", callback_phys, 10, FTW_PHYS);
|
|
nftw (".", callback_log, 10, 0);
|
|
|
|
/* Did we see the expected number of correct callbacks? */
|
|
|
|
if (good_cb != EXPECTED_GOOD)
|
|
{
|
|
FAIL_EXIT1 ("Saw %d good callbacks, expected %d\n",
|
|
good_cb, EXPECTED_GOOD);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#include <support/test-driver.c>
|