Nosuid checking for statfs() people: from Spider Boardman.
Jarkko Hietaniemi [Wed, 27 Oct 1999 13:06:27 +0000 (13:06 +0000)]
p4raw-id: //depot/cfgperl@4465

Configure
Porting/Glossary
Porting/config.sh
Porting/config_H
config_h.SH
perl.c
perl.h
pod/perldiag.pod

index 659daef..5aa9068 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -20,7 +20,7 @@
 
 # $Id: Head.U,v 3.0.1.9 1997/02/28 15:02:09 ram Exp $
 #
-# Generated on Tue Oct 26 16:44:39 EET DST 1999 [metaconfig 3.0 PL70]
+# Generated on Wed Oct 27 14:42:21 EET DST 1999 [metaconfig 3.0 PL70]
 # (with additional metaconfig patches by perlbug@perl.com)
 
 cat >/tmp/c1$$ <<EOF
@@ -355,6 +355,7 @@ d_flock=''
 d_fork=''
 d_fseeko=''
 d_fsetpos=''
+d_fstatfs=''
 d_ftello=''
 d_ftime=''
 d_gettimeod=''
@@ -512,9 +513,10 @@ sockethdr=''
 socketlib=''
 d_sqrtl=''
 d_statblks=''
-d_fstatfs=''
+d_fs_data_s=''
 d_statfs=''
-d_statfsflags=''
+d_statfs_f_flags=''
+d_statfs_s=''
 d_fstatvfs=''
 d_statvfs=''
 d_stdio_cnt_lval=''
@@ -555,6 +557,7 @@ d_umask=''
 d_semctl_semid_ds=''
 d_semctl_semun=''
 d_union_semun=''
+d_ustat=''
 d_vfork=''
 usevfork=''
 d_voidsig=''
@@ -648,12 +651,14 @@ i_sysresrc=''
 i_syssecrt=''
 i_sysselct=''
 i_sysstat=''
+i_sysstatfs=''
 i_sysstatvfs=''
 i_systimes=''
 i_systypes=''
 d_iovec_s=''
 i_sysuio=''
 i_sysun=''
+i_sysvfs=''
 i_syswait=''
 i_sgtty=''
 i_termio=''
@@ -663,6 +668,7 @@ i_systimek=''
 i_time=''
 timeincl=''
 i_unistd=''
+i_ustat=''
 i_utime=''
 i_values=''
 i_stdarg=''
@@ -7713,8 +7719,9 @@ while $test $# -ge 2; do
        esac ;
     shift 2;
 done > try.c;
-echo "int main () { struct $struct foo; foo.$field = 0; }" >> try.c;
-if $cc $optimize $ccflags -c try.c >/dev/null 2>&1; then
+echo "int main () { struct $struct foo; char* bar; bar = (char*)foo.$field; }" >> try.c;
+set try;
+if eval $compile; then
        val="$define";
 else
        val="$undef";
@@ -8664,13 +8671,23 @@ $rm -f try.*
 set d_fpos64_t
 eval $setvar
 
-: see if fseeko exists
-set fseeko d_fseeko
-eval $inlibc
-
-: see if fsetpos exists
-set fsetpos d_fsetpos
-eval $inlibc
+hasstruct='varname=$1; struct=$2; shift; shift;
+while $test $# -ge 2; do
+       case "$1" in
+       $define) echo "#include <$2>";;
+       esac ;
+    shift 2;
+done > try.c;
+echo "int main () { struct $struct foo; }" >> try.c;
+set try;
+if eval $compile; then
+       val="$define";
+else
+       val="$undef";
+fi;
+set $varname;
+eval $setvar;
+$rm -f try.c try.o'
 
 : see if this is a sys/param system
 set sys/param.h i_sysparam
@@ -8680,25 +8697,68 @@ eval $inhdr
 set sys/mount.h i_sysmount
 eval $inhdr
 
+: see if sys/types.h has to be included
+set sys/types.h i_systypes
+eval $inhdr
+
+: see if this is a sys/vfs.h system
+set sys/vfs.h i_sysvfs
+eval $inhdr
+
+: see if this is a sys/statfs.h system
+set sys/statfs.h i_sysstatfs
+eval $inhdr
+
 
 : see if statfs exists
 set statfs d_statfs
 eval $inlibc
 
-: see if fstatfs exists
-set fstatfs d_fstatfs
-eval $inlibc
+echo "Checking to see if your system supports struct statfs..." >&4
+set d_statfs_s statfs $i_systypes sys/types.h $i_sysparam sys/param.h $i_sysmount sys/mount.h $i_sysvfs sys/vfs.h $i_sysstatfs sys/statfs.h
+eval $hasstruct
+case "$d_statfs_s" in
+"$define")      echo "Yup, it does."     >&4 ;;
+*)              echo "Nope, it doesn't." >&4 ;;
+esac
 
-: see if statfs knows about mount flags
-case "$d_statfs" in
-define)        set d_statfsflags statfs f_flags $i_sysparam sys/param.h $i_sysmount sys/mount.h
+: see if struct statfs knows about f_flags
+case "$d_statfs_s" in
+define)        
+       echo "Checking to see if your struct statfs has f_flags field..." >&4
+       set d_statfs_f_flags statfs f_flags $i_systypes sys/types.h $i_sysparam sys/param.h $i_sysmount sys/mount.h $i_sysvfs sys/vfs.h $i_sysstatfs sys/statfs.h
        eval $hasfield
        ;;
 *)     val="$undef"
-       set d_statfsflags
+       set d_statfs_f_flags
        eval $setvar
        ;;
 esac
+case "$d_statfs_f_flags" in
+"$define")      echo "Yup, it does."     >&4 ;;
+*)              echo "Nope, it doesn't." >&4 ;;
+esac
+
+echo "Checking to see if your system supports struct fs_data..." >&4
+set d_fs_data_s fs_data $i_systypes sys/types.h $i_sysparam sys/param.h $i_sysmount sys/mount.h
+eval $hasstruct
+case "$d_fs_data_s" in
+"$define")      echo "Yup, it does."     >&4 ;;
+*)              echo "Nope, it doesn't." >&4 ;;
+esac
+
+: see if fseeko exists
+set fseeko d_fseeko
+eval $inlibc
+
+: see if fsetpos exists
+set fsetpos d_fsetpos
+eval $inlibc
+
+
+: see if fstatfs exists
+set fstatfs d_fstatfs
+eval $inlibc
 
 
 : see if statvfs exists
@@ -10621,10 +10681,6 @@ eval $inlibc
 set tcsetpgrp d_tcsetpgrp
 eval $inlibc
 
-: see if sys/types.h has to be included
-set sys/types.h i_systypes
-eval $inhdr
-
 : see if prototype for telldir is available
 echo " "
 set d_telldirproto telldir $i_systypes sys/types.h $i_dirent dirent.h
@@ -10728,6 +10784,10 @@ eval $setvar
 set umask d_umask
 eval $inlibc
 
+: see if ustat exists
+set ustat d_ustat
+eval $inlibc
+
 : backward compatibility for d_hvfork
 if test X$d_hvfork != X; then
        d_vfork="$d_hvfork"
@@ -13113,6 +13173,10 @@ eval $inhdr
 set sys/wait.h i_syswait
 eval $inhdr
 
+: see if this is a ustat.h system
+set ustat.h i_ustat
+eval $inhdr
+
 : see if this is an utime system
 set utime.h i_utime
 eval $inhdr
@@ -13587,6 +13651,7 @@ d_flock='$d_flock'
 d_fork='$d_fork'
 d_fpathconf='$d_fpathconf'
 d_fpos64_t='$d_fpos64_t'
+d_fs_data_s='$d_fs_data_s'
 d_fseeko='$d_fseeko'
 d_fsetpos='$d_fsetpos'
 d_fstatfs='$d_fstatfs'
@@ -13750,7 +13815,8 @@ d_sockpair='$d_sockpair'
 d_sqrtl='$d_sqrtl'
 d_statblks='$d_statblks'
 d_statfs='$d_statfs'
-d_statfsflags='$d_statfsflags'
+d_statfs_f_flags='$d_statfs_f_flags'
+d_statfs_s='$d_statfs_s'
 d_statvfs='$d_statvfs'
 d_stdio_cnt_lval='$d_stdio_cnt_lval'
 d_stdio_ptr_lval='$d_stdio_ptr_lval'
@@ -13785,6 +13851,7 @@ d_tzname='$d_tzname'
 d_umask='$d_umask'
 d_uname='$d_uname'
 d_union_semun='$d_union_semun'
+d_ustat='$d_ustat'
 d_vendorbin='$d_vendorbin'
 d_vendorlib='$d_vendorlib'
 d_vfork='$d_vfork'
@@ -13891,6 +13958,7 @@ i_syssecrt='$i_syssecrt'
 i_sysselct='$i_sysselct'
 i_syssockio='$i_syssockio'
 i_sysstat='$i_sysstat'
+i_sysstatfs='$i_sysstatfs'
 i_sysstatvfs='$i_sysstatvfs'
 i_systime='$i_systime'
 i_systimek='$i_systimek'
@@ -13898,11 +13966,13 @@ i_systimes='$i_systimes'
 i_systypes='$i_systypes'
 i_sysuio='$i_sysuio'
 i_sysun='$i_sysun'
+i_sysvfs='$i_sysvfs'
 i_syswait='$i_syswait'
 i_termio='$i_termio'
 i_termios='$i_termios'
 i_time='$i_time'
 i_unistd='$i_unistd'
+i_ustat='$i_ustat'
 i_utime='$i_utime'
 i_values='$i_values'
 i_varargs='$i_varargs'
index 876bfe9..b0fb54d 100644 (file)
@@ -534,6 +534,10 @@ d_fpathconf (d_pathconf.U):
 d_fpos64_t (io64.U):
        This symbol will be defined if the C compiler supports fpos64_t.
 
+d_fs_data_s (d_statfs.U):
+       This variable conditionally defines the HAS_STRUCT_FS_DATA symbol,
+       which indicates that the struct fs_data is supported.
+
 d_fseeko (d_fseeko.U):
        This variable conditionally defines the HAS_FSEEKO symbol, which
        indicates to the C program that the fseeko() routine is available.
@@ -542,7 +546,7 @@ d_fsetpos (d_fsetpos.U):
        This variable conditionally defines HAS_FSETPOS if fsetpos() is
        available to set the file position indicator.
 
-d_fstatfs (d_statfs.U):
+d_fstatfs (d_fstatfs.U):
        This variable conditionally defines the HAS_FSTATFS symbol, which
        indicates to the C program that the fstatfs() routine is available.
 
@@ -1327,12 +1331,16 @@ d_statfs (d_statfs.U):
        This variable conditionally defines the HAS_STATFS symbol, which
        indicates to the C program that the statfs() routine is available.
 
-d_statfsflags (d_statfs.U):
-       This variable conditionally defines the HAS_STRUCT_STATFS_FLAGS
+d_statfs_f_flags (d_statfs.U):
+       This variable conditionally defines the HAS_STRUCT_STATFS_F_FLAGS
        symbol, which indicates to struct statfs from has f_flags member.
        This kind of struct statfs is coming from sys/mount.h (BSD),
        not from sys/statfs.h (SYSV).
 
+d_statfs_s (d_statfs.U):
+       This variable conditionally defines the HAS_STRUCT_STATFS symbol,
+       which indicates that the struct statfs is supported.
+
 d_statvfs (d_statvfs.U):
        This variable conditionally defines the HAS_STATVFS symbol, which
        indicates to the C program that the statvfs() routine is available.
@@ -1487,6 +1495,10 @@ d_union_semun (d_union_semun.U):
        This variable conditionally defines HAS_UNION_SEMUN if the
        union semun is defined by including <sys/sem.h>.
 
+d_ustat (d_ustat.U):
+       This variable conditionally defines HAS_USTAT if ustat() is
+       available to query file system statistics by dev_t.
+
 d_vendorbin (vendorbin.U):
        This variable conditionally defines PERL_VENDORBIN.
 
@@ -1973,6 +1985,10 @@ i_sysstat (i_sysstat.U):
        This variable conditionally defines the I_SYS_STAT symbol,
        and indicates whether a C program should include <sys/stat.h>.
 
+i_sysstatfs (i_sysstatfs.U):
+       This variable conditionally defines the I_SYSSTATFS symbol,
+       and indicates whether a C program should include <sys/statfs.h>.
+
 i_sysstatvfs (i_sysstatvfs.U):
        This variable conditionally defines the I_SYSSTATVFS symbol,
        and indicates whether a C program should include <sys/statvfs.h>.
@@ -2003,6 +2019,10 @@ i_sysun (i_sysun.U):
        to the C program that it should include <sys/un.h> to get UNIX
        domain socket definitions.
 
+i_sysvfs (i_sysvfs.U):
+       This variable conditionally defines the I_SYSVFS symbol,
+       and indicates whether a C program should include <sys/vfs.h>.
+
 i_syswait (i_syswait.U):
        This variable conditionally defines I_SYS_WAIT, which indicates
        to the C program that it should include <sys/wait.h>.
@@ -2025,6 +2045,10 @@ i_unistd (i_unistd.U):
        This variable conditionally defines the I_UNISTD symbol, and indicates
        whether a C program should include <unistd.h>.
 
+i_ustat (i_ustat.U):
+       This variable conditionally defines the I_USTAT symbol, and indicates
+       whether a C program should include <ustat.h>.
+
 i_utime (i_utime.U):
        This variable conditionally defines the I_UTIME symbol, and indicates
        whether a C program should include <utime.h>.
index f3c46a2..dce5791 100644 (file)
@@ -8,7 +8,7 @@
 
 # Package name      : perl5
 # Source directory  : .
-# Configuration time: Tue Oct 26 16:45:55 EET DST 1999
+# Configuration time: Wed Oct 27 15:23:59 EET DST 1999
 # Configured by     : jhi
 # Target system     : osf1 alpha.hut.fi v4.0 878 alpha 
 
@@ -56,7 +56,7 @@ ccflags='-pthread -std -DLANGUAGE_C'
 ccsymbols='__LANGUAGE_C__=1 _LONGLONG=1 LANGUAGE_C=1 SYSTYPE_BSD=1'
 cf_by='jhi'
 cf_email='yourname@yourhost.yourplace.com'
-cf_time='Tue Oct 26 16:45:55 EET DST 1999'
+cf_time='Wed Oct 27 15:23:59 EET DST 1999'
 chgrp=''
 chmod=''
 chown=''
@@ -148,6 +148,7 @@ d_flock='define'
 d_fork='define'
 d_fpathconf='define'
 d_fpos64_t='undef'
+d_fs_data_s='undef'
 d_fseeko='undef'
 d_fsetpos='define'
 d_fstatfs='define'
@@ -311,7 +312,8 @@ d_sockpair='define'
 d_sqrtl='define'
 d_statblks='define'
 d_statfs='define'
-d_statfsflags='define'
+d_statfs_f_flags='define'
+d_statfs_s='define'
 d_statvfs='define'
 d_stdio_cnt_lval='define'
 d_stdio_ptr_lval='define'
@@ -346,6 +348,7 @@ d_tzname='define'
 d_umask='define'
 d_uname='define'
 d_union_semun='undef'
+d_ustat='define'
 d_vendorbin='undef'
 d_vendorlib='undef'
 d_vfork='undef'
@@ -452,6 +455,7 @@ i_syssecrt='define'
 i_sysselct='define'
 i_syssockio=''
 i_sysstat='define'
+i_sysstatfs='undef'
 i_sysstatvfs='define'
 i_systime='define'
 i_systimek='undef'
@@ -459,11 +463,13 @@ i_systimes='define'
 i_systypes='define'
 i_sysuio='define'
 i_sysun='define'
+i_sysvfs='undef'
 i_syswait='define'
 i_termio='undef'
 i_termios='define'
 i_time='undef'
 i_unistd='define'
+i_ustat='define'
 i_utime='define'
 i_values='define'
 i_varargs='undef'
index 345ec01..1b96031 100644 (file)
@@ -17,7 +17,7 @@
 /*
  * Package name      : perl5
  * Source directory  : .
- * Configuration time: Tue Oct 26 16:45:55 EET DST 1999
+ * Configuration time: Wed Oct 27 15:23:59 EET DST 1999
  * Configured by     : jhi
  * Target system     : osf1 alpha.hut.fi v4.0 878 alpha 
  */
  */
 /*#define HAS_FSEEKO           / **/
 
+/* HAS_FSTATFS:
+ *     This symbol, if defined, indicates that the fstatfs routine is
+ *     available to stat filesystems by file descriptors.
+ */
+#define HAS_FSTATFS            /**/
 /* HAS_FTELLO:
  *     This symbol, if defined, indicates that the ftello routine is
  *     available to ftell beyond 32 bits (useful for ILP32 hosts).
  */
 #define HAS_SQRTL              /**/
 
-/* HAS_FSTATFS:
- *     This symbol, if defined, indicates that the fstatfs routine is
- *     available to stat filesystems by file descriptors.
+/* HAS_STATFS:
+ *     This symbol, if defined, indicates that the statfs routine is
+ *     available to stat filesystems by filenames.
+ */
+/* HAS_STRUCT_STATFS:
+ *     This symbol, if defined, indicates that the struct statfs
+ *     to do statfs() is supported.
+ */
+/* HAS_STRUCT_FS_DATA:
+ *     This symbol, if defined, indicates that the struct fs_data
+ *     to do statfs() is supported.
  */
-/* HAS_STRUCT_STATFS_FLAGS:
+/* HAS_STRUCT_STATFS_F_FLAGS:
  *     This symbol, if defined, indicates that the struct statfs
  *     does have the f_flags member containing the mount flags of
- *     the filesystem holding the file.
+ *     the filesystem containing the file.
  *     This kind of struct statfs is coming from <sys/mount.h> (BSD 4.3),
  *     not from <sys/statfs.h> (SYSV).  Older BSDs (like Ultrix) do not
- *     have statfs() and struct statfs, they have getmnt().
+ *     have statfs() and struct statfs, they have ustat() and statfs()
+ *     with struct fs_data.
  */
-#define HAS_FSTATFS            /**/
-#define HAS_STRUCT_STATFS_FLAGS                /**/
+#define HAS_STATFS             /**/
+#define HAS_STRUCT_STATFS      /**/
+/*#define HAS_STRUCT_FS_DATA   / **/
+#define HAS_STRUCT_STATFS_F_FLAGS              /**/
 
 /* HAS_FSTATVFS:
  *     This symbol, if defined, indicates that the fstatvfs routine is
  */
 #define        HAS_TELLDIR_PROTO       /**/
 
+/* HAS_USTAT:
+ *     This symbol, if defined, indicates that the ustat system call is
+ *     available to query file system statistics by dev_t.
+ */
+#define HAS_USTAT              /**/
+
 /* HAS_WRITEV:
  *     This symbol, if defined, indicates that the writev routine is
  *     available to do scatter writes.
  */
 #define        I_SYS_MOUNT             /**/
 
+/* I_SYS_STATFS:
+ *     This symbol, if defined, indicates that <sys/statfs.h> exists.
+ */
+/*#define      I_SYS_STATFS            / **/
+
 /* I_SYS_STATVFS:
  *     This symbol, if defined, indicates that <sys/statvfs.h> exists and
  *     should be included.
  */
 #define        I_SYS_STATVFS           /**/
 
+/* I_SYS_VFS:
+ *     This symbol, if defined, indicates that <sys/vfs.h> exists and
+ *     should be included.
+ */
+/*#define      I_SYS_VFS               / **/
+
+/* I_USTAT:
+ *     This symbol, if defined, indicates that <ustat.h> exists and
+ *     should be included.
+ */
+#define        I_USTAT         /**/
+
 /* HAS_OFF64_T:
  *     This symbol will be defined if the C compiler supports off64_t.
  */
index a0be5e3..a12916e 100644 (file)
@@ -2198,6 +2198,11 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un-
  */
 #$d_fseeko HAS_FSEEKO          /**/
 
+/* HAS_FSTATFS:
+ *     This symbol, if defined, indicates that the fstatfs routine is
+ *     available to stat filesystems by file descriptors.
+ */
+#$d_fstatfs HAS_FSTATFS                /**/
 /* HAS_FTELLO:
  *     This symbol, if defined, indicates that the ftello routine is
  *     available to ftell beyond 32 bits (useful for ILP32 hosts).
@@ -2273,20 +2278,31 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un-
  */
 #$d_sqrtl HAS_SQRTL            /**/
 
-/* HAS_FSTATFS:
- *     This symbol, if defined, indicates that the fstatfs routine is
- *     available to stat filesystems by file descriptors.
+/* HAS_STATFS:
+ *     This symbol, if defined, indicates that the statfs routine is
+ *     available to stat filesystems by filenames.
+ */
+/* HAS_STRUCT_STATFS:
+ *     This symbol, if defined, indicates that the struct statfs
+ *     to do statfs() is supported.
+ */
+/* HAS_STRUCT_FS_DATA:
+ *     This symbol, if defined, indicates that the struct fs_data
+ *     to do statfs() is supported.
  */
-/* HAS_STRUCT_STATFS_FLAGS:
+/* HAS_STRUCT_STATFS_F_FLAGS:
  *     This symbol, if defined, indicates that the struct statfs
  *     does have the f_flags member containing the mount flags of
- *     the filesystem holding the file.
+ *     the filesystem containing the file.
  *     This kind of struct statfs is coming from <sys/mount.h> (BSD 4.3),
  *     not from <sys/statfs.h> (SYSV).  Older BSDs (like Ultrix) do not
- *     have statfs() and struct statfs, they have getmnt().
+ *     have statfs() and struct statfs, they have ustat() and statfs()
+ *     with struct fs_data.
  */
-#$d_fstatfs HAS_FSTATFS                /**/
-#$d_statfsflags HAS_STRUCT_STATFS_FLAGS                /**/
+#$d_statfs HAS_STATFS          /**/
+#$d_statfs_s HAS_STRUCT_STATFS /**/
+#$d_fs_data_s HAS_STRUCT_FS_DATA       /**/
+#$d_statfs_f_flags HAS_STRUCT_STATFS_F_FLAGS           /**/
 
 /* HAS_FSTATVFS:
  *     This symbol, if defined, indicates that the fstatvfs routine is
@@ -2302,6 +2318,12 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un-
  */
 #$d_telldirproto       HAS_TELLDIR_PROTO       /**/
 
+/* HAS_USTAT:
+ *     This symbol, if defined, indicates that the ustat system call is
+ *     available to query file system statistics by dev_t.
+ */
+#$d_ustat HAS_USTAT            /**/
+
 /* HAS_WRITEV:
  *     This symbol, if defined, indicates that the writev routine is
  *     available to do scatter writes.
@@ -2395,12 +2417,29 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un-
  */
 #$i_sysmount   I_SYS_MOUNT             /**/
 
+/* I_SYS_STATFS:
+ *     This symbol, if defined, indicates that <sys/statfs.h> exists.
+ */
+#$i_sysstatfs  I_SYS_STATFS            /**/
+
 /* I_SYS_STATVFS:
  *     This symbol, if defined, indicates that <sys/statvfs.h> exists and
  *     should be included.
  */
 #$i_sysstatvfs I_SYS_STATVFS           /**/
 
+/* I_SYS_VFS:
+ *     This symbol, if defined, indicates that <sys/vfs.h> exists and
+ *     should be included.
+ */
+#$i_sysvfs     I_SYS_VFS               /**/
+
+/* I_USTAT:
+ *     This symbol, if defined, indicates that <ustat.h> exists and
+ *     should be included.
+ */
+#$i_ustat      I_USTAT         /**/
+
 /* HAS_OFF64_T:
  *     This symbol will be defined if the C compiler supports off64_t.
  */
diff --git a/perl.c b/perl.c
index 4fb1771..ce151ab 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -2180,13 +2180,15 @@ sed %s -e \"/^[^#]/b\" \
 STATIC int
 S_fd_on_nosuid_fs(pTHX_ int fd)
 {
-    int on_nosuid  = 0;
-    int check_okay = 0;
+    int check_okay = 0; /* able to do all the required sys/libcalls */
+    int on_nosuid  = 0; /* the fd is on a nosuid fs */
 /*
- * Preferred order: fstatvfs(), fstatfs(), getmntent().
+ * Preferred order: fstatvfs(), fstatfs(), ustat()+statfs(), getmntent().
  * fstatvfs() is UNIX98.
- * fstatfs() is BSD.
- * getmntent() is O(number-of-mounted-filesystems) and can hang.
+ * fstatfs() is 4.3 BSD.
+ * ustat()+statfs() is pre-4.3 BSD.
+ * getmntent() is O(number-of-mounted-filesystems) and can hang on
+ * an irrelevant filesystem while trying to reach the right one.
  */
 
 #   ifdef HAS_FSTATVFS
@@ -2194,24 +2196,40 @@ S_fd_on_nosuid_fs(pTHX_ int fd)
     check_okay = fstatvfs(fd, &stfs) == 0;
     on_nosuid  = check_okay && (stfs.f_flag  & ST_NOSUID);
 #   else
-#       if defined(HAS_FSTATFS) && defined(HAS_STRUCT_STATFS_FLAGS)
+#       ifdef PERL_MOUNT_NOSUID
+#           if defined(HAS_FSTATFS) && defined(HAS_STRUCT_STATFS_F_FLAGS)
     struct statfs  stfs;
     check_okay = fstatfs(fd, &stfs)  == 0;
-#           undef PERL_MOUNT_NOSUID
-#           if !defined(PERL_MOUNT_NOSUID) && defined(MNT_NOSUID)
-#              define PERL_MOUNT_NOSUID MNT_NOSUID
-#           endif
-#           if !defined(PERL_MOUNT_NOSUID) && defined(MS_NOSUID)
-#              define PERL_MOUNT_NOSUID MS_NOSUID
-#           endif
-#           if !defined(PERL_MOUNT_NOSUID) && defined(M_NOSUID)
-#              define PERL_MOUNT_NOSUID M_NOSUID
-#           endif
-#           ifdef PERL_MOUNT_NOSUID
     on_nosuid  = check_okay && (stfs.f_flags & PERL_MOUNT_NOSUID);
-#           endif
+#           else
+#               if defined(HAS_FSTAT) && \
+                  defined(HAS_USTAT) && \
+                  defined(HAS_STATFS) && \
+                  defined(HAS_STRUCT_FS_DATA) /* no struct statfs */
+    struct stat fdst;
+    if (fstat(fd, &fdst) == 0) {
+       struct ustat us;
+       if (ustat(fdst.st_dev, &us) == 0) {
+           struct fs_data fsd;
+           if (statfs(PL_origfilename, &fsd) == 0) {
+               size_t cmplen = sizeof(us.f_fname);
+               if (sizeof(fsd.fd_req.path) < cmplen)
+                   cmplen = sizeof(fsd.fd_req.path);
+               if (strnEQ(fsd.fd_req.path, us.f_fname, cmplen) &&
+                   fdst.st_dev == fsd.fd_req.dev) {
+                       check_okay = 1;
+                       on_nosuid = fsd.fd_req.flags & PERL_MOUNT_NOSUID;
+                   }
+               }
+           }
+       }
+    }
+#               endif /* fstat+ustat+statfs */
+#           endif /* statfs */
 #       else
-#           if defined(HAS_GETMNTENT) && defined(HAS_HASMNTOPT) && defined(MNTOPT_NOSUID)
+#           if defined(HAS_GETMNTENT) && \
+              defined(HAS_HASMNTOPT) && \
+              defined(MNTOPT_NOSUID)
     FILE               *mtab = fopen("/etc/mtab", "r");
     struct mntent      *entry;
     struct stat                stb, fsb;
@@ -2231,11 +2249,12 @@ S_fd_on_nosuid_fs(pTHX_ int fd)
     }
     if (mtab)
        fclose(mtab);
-#           endif /* mntent */
-#       endif /* statfs */
+#           endif /* getmntent */
+#       endif /* PERL_MOUNT_NOSUID: fstatfs or fstat+ustat+statfs */
 #   endif /* statvfs */
+
     if (!check_okay) 
-       Perl_croak(aTHX_ "Can't check filesystem of script \"%s\"", PL_origfilename);
+       Perl_croak(aTHX_ "Can't check filesystem of script \"%s\" for nosuid", PL_origfilename);
     return on_nosuid;
 }
 #endif /* IAMSUID */
diff --git a/perl.h b/perl.h
index 501c635..ddad5ce 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -3207,6 +3207,40 @@ typedef struct am_table_short AMTS;
 #ifdef I_MNTENT
 #   include <mntent.h>          /* for getmntent() */
 #endif
+#ifdef I_SYS_STATFS
+#   include <sys/statfs.h>      /* for some statfs() */
+#endif
+#ifdef I_SYS_VFS
+#   include <sys/vfs.h>         /* for some statfs() */
+#endif
+#ifdef I_USTAT
+#   include <ustat.h>           /* for ustat() */
+#endif
+
+#if !defined(PERL_MOUNT_NOSUID) && defined(MOUNT_NOSUID)
+#    define PERL_MOUNT_NOSUID MOUNT_NOSUID
+#endif
+#if !defined(PERL_MOUNT_NOSUID) && defined(MNT_NOSUID)
+#    define PERL_MOUNT_NOSUID MNT_NOSUID
+#endif
+#if !defined(PERL_MOUNT_NOSUID) && defined(MS_NOSUID)
+#   define PERL_MOUNT_NOSUID MS_NOSUID
+#endif
+#if !defined(PERL_MOUNT_NOSUID) && defined(M_NOSUID)
+#   define PERL_MOUNT_NOSUID M_NOSUID
+#endif
+
+#ifdef HAS_STRUCT_STATFS
+#   define PERL_STRUCT_STATFS statfs
+#   ifdef HAS_STRUCT_STATFS_F_FLAGS
+#       define PERL_STRUCT_STATFS_FLAGS(s) s.f_flags
+#   endif
+#else
+#   ifdef HAS_STRUCT_FS_DATA
+#       define PERL_STRUCT_STATFS statfs
+#       define PERL_STRUCT_STATFS_FLAGS(s) s.fd_req.flags
+#   endif
+#endif
 
 #endif /* IAMSUID */
 
index 5b1c324..006c2d9 100644 (file)
@@ -636,7 +636,7 @@ Something like this will reproduce the error:
 (F) You called C<perl -x/foo/bar>, but C</foo/bar> is not a directory
 that you can chdir to, possibly because it doesn't exist.
 
-=item Can't check filesystem of script "%s"
+=item Can't check filesystem of script "%s" for nosuid
 
 (P) For some reason you can't check the filesystem of the script for nosuid.