Filan prints symlink target

This commit is contained in:
Gerhard Rieger 2022-06-05 10:55:45 +02:00
parent c62f93a168
commit e0c669028d
4 changed files with 85 additions and 6 deletions

View file

@ -63,6 +63,10 @@ Porting:
Corrected message format when no strftime() is available; improved
handling of very long host or program names
Features:
Filan prints target of symlink when appropriate
Test: FILANSYMLINK
Testing:
Unset SOCAT_MAIN_WAIT on informational Socat calls

33
filan.c
View file

@ -79,17 +79,20 @@ int filan_file(const char *filename, FILE *outfile) {
default:
if ((fd =
Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK
#ifdef O_NOFOLLOW
|(filan_followsymlinks?0:O_NOFOLLOW)
#endif
#ifdef O_LARGEFILE
|O_LARGEFILE
#endif
, 0700))
< 0) {
Warn2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s",
Warn2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_LARGEFILE, 0700): %s",
filename, strerror(errno));
}
}
result = filan_stat(&buf, fd, -1, outfile);
result = filan_stat(&buf, fd, -1, outfile, filename);
fputc('\n', outfile);
return result;
}
@ -119,7 +122,7 @@ int filan_fd(int fd, FILE *outfile) {
}
Debug2("fd %d is a %s", fd, getfiletypestring(buf.st_mode));
result = filan_stat(&buf, fd, fd, outfile);
result = filan_stat(&buf, fd, fd, outfile, NULL);
if (result >= 0) {
/* even more dynamic info */
@ -212,7 +215,12 @@ int filan_stat(
#else
struct stat *buf
#endif /* !HAVE_STAT64 */
, int statfd, int dynfd, FILE *outfile) {
, int statfd, int dynfd, FILE *outfile,
const char *filename /* Linux does not (yet) provide an
freadlink system call, so we need
the original name for readlink in
case it is a symlink */
) {
char stdevstr[8];
/* print header */
@ -380,7 +388,11 @@ int filan_stat(
break;
case (S_IFREG): /* 8, regular file */
break;
#ifdef S_IFLNK
case (S_IFLNK): /* 10, symbolic link */
/* we wait for freadlink() sytem call */
break;
#endif /* S_IFLNK */
break;
#ifdef S_IFSOCK
case (S_IFSOCK): /* 12, socket */
@ -393,6 +405,19 @@ int filan_stat(
break;
#endif /* S_IFSOCK */
}
} else {
switch (buf->st_mode&S_IFMT) {
#ifdef S_IFLNK
case (S_IFLNK): /* 10, symbolic link */
{
char linktarget[PATH_MAX+1];
memset(linktarget, 0, PATH_MAX+1);
Readlink(filename, linktarget, PATH_MAX);
fprintf(outfile, "LINKTARGET=%s", linktarget);
}
break;
#endif /* S_IFLNK */
}
}
/* ioctl() */
return 0;

View file

@ -22,7 +22,8 @@ extern int filan_stat(
#else
struct stat *buf
#endif /* !HAVE_STAT64 */
, int statfd, int dynfd, FILE *outfile);
, int statfd, int dynfd, FILE *outfile,
const char *filename);
extern int cdevan(int fd, FILE *outfile);

51
test.sh
View file

@ -6502,10 +6502,13 @@ esac
N=$((N+1))
# Test if Filan can determine UNIX domain socket in file system
NAME=FILANSOCKET
case "$TESTS" in
*%$N%*|*%filan%*|*%$NAME%*)
TEST="$NAME: capability to analyze named unix socket"
# Run Filan on a listening UNIX domain socket.
# When its output gives "socket" as type (2nd column), the test succeeded
if ! eval $NUMCOND; then :; else
ts="$td/test$N.socket"
te1="$td/test$N.stderr1" # socat
@ -6517,10 +6520,16 @@ waitfile "$ts" 1
type=$($FILAN -f "$ts" 2>$te2 |tail -n 1 |awk '{print($2);}')
if [ "$type" = "socket" ]; then
$PRINTF "$OK\n"
numOK=$((numOK+1))
if [ "$VERBOSE" ]; then
echo "$SOCAT $opts UNIX-LISTEN:\"$ts\" /dev/null </dev/null 2>\"$te1\""
echo "$FILAN -f "$ts" 2>$te2 |tail -n 1 |awk '{print(\$2);}'"
fi
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "$SOCAT $opts UNIX-LISTEN:\"$ts\" /dev/null </dev/null 2>\"$te1\"" >&2
cat "$te1"
echo "$FILAN -f "$ts" 2>$te2 |tail -n 1 |awk '{print(\$2);}'" >&2
cat "$te2"
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
@ -15602,6 +15611,46 @@ esac
N=$((N+1))
# Test if Filan can print the target of symbolic links
NAME=FILANSYMLINK
case "$TESTS" in
*%$N%*|*%filan%*|*%$NAME%*)
TEST="$NAME: capability to display symlink target"
# Run Filan on a symbolic link
# When its output contains "LINKTARGET=<target>" the test succeeded
if ! eval $NUMCOND; then :; else
tf="$td/test$N.file"
tl="$td/test$N.symlink"
te1="$td/test$N.stderr1" # socat
te2="$td/test$N.stderr2" # filan
printf "test $F_n $TEST... " $N
touch "$tf"
ln -s "$tf" "$tl"
target=$($FILAN -f "$tl" 2>$te |tail -n 1 |sed 's/.*LINKTARGET=\([^ ]*\)/\1/')
if [ "$target" = "$tf" ]; then
$PRINTF "$OK\n"
if [ "$VERBOSE" ]; then
echo "touch \"$tf\""
echo "ln -s \"$tf\" \"$tl\""
echo "$FILAN -f "$tl" 2>$te |tail -n 1 |sed 's/.*LINKTARGET=\([^ ]*\)/\1/'"
fi
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "touch \"$tf\"" >&2
echo "ln -s \"$tf\" \"$tl\"" >&2
echo "$FILAN -f "$tl" 2>$te |tail -n 1 |sed 's/.*LINKTARGET=\([^ ]*\)/\1/'" >&2
cat "$te"
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
fi
kill $spid 2>/dev/null
wait
fi ;; # NUMCOND
esac
N=$((N+1))
# end of common tests
##################################################################################