else
xasprintf(&str, "---");
break;
+ case COL_XMODE: {
+ char r, w, x;
+ if (does_file_has_fdinfo_alike(file)) {
+ r = file->mode & S_IRUSR? 'r': '-';
+ w = file->mode & S_IWUSR? 'w': '-';
+ x = (is_mapped_file(file)
+ && file->mode & S_IXUSR)? 'x': '-';
+ } else
+ r = w = x = '-';
+ xasprintf(&str, "%c%c%c", r, w, x);
+ break;
+ }
case COL_POS:
xasprintf(&str, "%" PRIu64,
(does_file_has_fdinfo_alike(file))? file->pos: 0);
--- /dev/null
+#!/bin/bash
+#
+# Copyright (C) 2022 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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 General Public License for more details.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="MODE and XMODE columns"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_LSFD"
+ts_check_test_command "$TS_HELPER_MKFDS"
+
+ts_check_prog "stat"
+
+ts_cd "$TS_OUTDIR"
+
+INO=$(stat -c '%i' "$TS_HELPER_MKFDS")
+PID=
+FD=3
+
+
+EXPR="(FD == 3)"
+ts_init_subtest "MODE-r-bit"
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" ro-regular-file $FD; }
+ if read -r -u "${MKFDS[0]}" PID; then
+ "${TS_CMD_LSFD}" -n -o MODE -p "${PID}" -Q "${EXPR}"
+ echo "MODE(r-bit): " $?
+ kill -CONT "${PID}"
+ fi
+} > "$TS_OUTPUT" 2>&1
+wait "${MKFDS_PID}"
+ts_finalize_subtest
+
+ts_init_subtest "XMODE-r-bit"
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" ro-regular-file $FD; }
+ if read -r -u "${MKFDS[0]}" PID; then
+ "${TS_CMD_LSFD}" -n -o XMODE -p "${PID}" -Q "${EXPR}"
+ echo "XMODE(r-bit): " $?
+ kill -CONT "${PID}"
+ fi
+} > "$TS_OUTPUT" 2>&1
+wait "${MKFDS_PID}"
+ts_finalize_subtest
+
+EXPR="(FD == $((FD + 1)))"
+ts_init_subtest "MODE-w-bit"
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" pipe-no-fork $FD $((FD + 1)); }
+ if read -r -u "${MKFDS[0]}" PID; then
+ "${TS_CMD_LSFD}" -n -o MODE -p "${PID}" -Q "${EXPR}"
+ echo "MODE(w-bit): " $?
+ kill -CONT "${PID}"
+ fi
+} > "$TS_OUTPUT" 2>&1
+wait "${MKFDS_PID}"
+ts_finalize_subtest
+
+ts_init_subtest "XMODE-w-bit"
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" pipe-no-fork $FD $((FD + 1)); }
+ if read -r -u "${MKFDS[0]}" PID; then
+ "${TS_CMD_LSFD}" -n -o XMODE -p "${PID}" -Q "${EXPR}"
+ echo "XMODE(w-bit): " $?
+ kill -CONT "${PID}"
+ fi
+} > "$TS_OUTPUT" 2>&1
+wait "${MKFDS_PID}"
+ts_finalize_subtest
+
+EXPR='(ASSOC == "mem") and (INODE == '"$INO"') and (MODE != "r--") and (MODE != "rw-")'
+ts_init_subtest "MODE-x-bit"
+if [ "$QEMU_USER" == "1" ]; then
+ ts_skip_subtest "running under qemu-user emulation"
+else
+ {
+ coproc MKFDS { "$TS_HELPER_MKFDS" ro-regular-file $FD; }
+ if read -r -u "${MKFDS[0]}" PID; then
+ "${TS_CMD_LSFD}" -n -o MODE -p "${PID}" -Q "${EXPR}"
+ echo "MODE(x-bit): " $?
+ kill -CONT "${PID}"
+ fi
+ } > "$TS_OUTPUT" 2>&1
+ wait "${MKFDS_PID}"
+ ts_finalize_subtest
+fi
+
+ts_init_subtest "XMODE-x-bit"
+if [ "$QEMU_USER" == "1" ]; then
+ ts_skip_subtest "running under qemu-user emulation"
+else
+ {
+ coproc MKFDS { "$TS_HELPER_MKFDS" ro-regular-file $FD; }
+ if read -r -u "${MKFDS[0]}" PID; then
+ "${TS_CMD_LSFD}" -n -o XMODE -p "${PID}" -Q "${EXPR}"
+ echo "XMODE(x-bit): " $?
+ kill -CONT "${PID}"
+ fi
+ } > "$TS_OUTPUT" 2>&1
+ wait "${MKFDS_PID}"
+ ts_finalize_subtest
+fi
+
+ts_finalize