]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/posix/fpathconf.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / posix / fpathconf.c
index 649a2a4c4970cdc99cd75c09a9df8692223cf1eb..8586428556048a2f90c3125b22129d94dd679e68 100644 (file)
@@ -1,50 +1,49 @@
-/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+/* Copyright (C) 1991-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 Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   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
-Library General Public License for more details.
+   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 Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
+   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 <ansidecl.h>
 #include <errno.h>
 #include <stddef.h>
 #include <unistd.h>
 #include <limits.h>
+#include <sys/stat.h>
 #include <sys/statfs.h>
+#include <sys/statvfs.h>
 
 
 /* Get file-specific information about descriptor FD.  */
 long int
-DEFUN(__fpathconf, (fd, name), int fd AND int name)
+__fpathconf (int fd, int name)
 {
   if (fd < 0)
     {
-      errno = EBADF;
+      __set_errno (EBADF);
       return -1;
     }
 
   switch (name)
     {
     default:
-      errno = EINVAL;
+      __set_errno (EINVAL);
       return -1;
 
     case _PC_LINK_MAX:
 #ifdef LINK_MAX
       return LINK_MAX;
 #else
-      errno = ENOSYS;
       return -1;
 #endif
 
@@ -52,7 +51,6 @@ DEFUN(__fpathconf, (fd, name), int fd AND int name)
 #ifdef MAX_CANON
       return MAX_CANON;
 #else
-      errno = ENOSYS;
       return -1;
 #endif
 
@@ -60,30 +58,40 @@ DEFUN(__fpathconf, (fd, name), int fd AND int name)
 #ifdef MAX_INPUT
       return MAX_INPUT;
 #else
-      errno = ENOSYS;
       return -1;
 #endif
 
     case _PC_NAME_MAX:
 #ifdef NAME_MAX
-      return NAME_MAX;
+      {
+       struct statvfs64 sv;
+       int save_errno = errno;
+
+       if (__fstatvfs64 (fd, &sv) < 0)
+         {
+           if (errno == ENOSYS)
+             {
+               __set_errno (save_errno);
+               return NAME_MAX;
+             }
+           else if (errno == ENODEV)
+             __set_errno (EINVAL);
+
+           return -1;
+         }
+       else
+         {
+           return sv.f_namemax;
+         }
+      }
 #else
-      errno = ENOSYS;
       return -1;
 #endif
 
     case _PC_PATH_MAX:
 #ifdef PATH_MAX
-      {
-       struct statfs buf;
-
-       if (__fstatfs (fd, &buf) < 0)
-         return errno == ENOSYS ? PATH_MAX : -1;
-       else
-         return buf.f_namelen;
-      }
+      return PATH_MAX;
 #else
-      errno = ENOSYS;
       return -1;
 #endif
 
@@ -91,30 +99,26 @@ DEFUN(__fpathconf, (fd, name), int fd AND int name)
 #ifdef PIPE_BUF
       return PIPE_BUF;
 #else
-      errno = ENOSYS;
       return -1;
 #endif
 
     case _PC_CHOWN_RESTRICTED:
-#ifdef _POSIX_CHOWN_RESTRICTED
-      return _POSIX_CHOWN_RESTRICTED;
-#else
-      return -1;
+#if _POSIX_CHOWN_RESTRICTED == -1
+# error "Invalid value for _POSIX_CHOWN_RESTRICTED"
 #endif
+      return _POSIX_CHOWN_RESTRICTED;
 
     case _PC_NO_TRUNC:
-#ifdef _POSIX_NO_TRUNC
-      return _POSIX_NO_TRUNC;
-#else
-      return -1;
+#if _POSIX_NO_TRUNC == -1
+# error "Invalid value for _POSIX_NO_TRUNC"
 #endif
+      return _POSIX_NO_TRUNC;
 
     case _PC_VDISABLE:
-#ifdef _POSIX_VDISABLE
-      return _POSIX_VDISABLE;
-#else
-      return -1;
+#if _POSIX_VDISABLE == -1
+# error "Invalid value for _POSIX_VDISABLE"
 #endif
+      return _POSIX_VDISABLE;
 
     case _PC_SYNC_IO:
 #ifdef _POSIX_SYNC_IO
@@ -125,7 +129,16 @@ DEFUN(__fpathconf, (fd, name), int fd AND int name)
 
     case _PC_ASYNC_IO:
 #ifdef _POSIX_ASYNC_IO
-      return _POSIX_ASYNC_IO;
+      {
+       /* AIO is only allowed on regular files and block devices.  */
+       struct stat64 st;
+
+       if (__fxstat64 (_STAT_VER, fd, &st) < 0
+           || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode)))
+         return -1;
+       else
+         return 1;
+      }
 #else
       return -1;
 #endif
@@ -136,10 +149,78 @@ DEFUN(__fpathconf, (fd, name), int fd AND int name)
 #else
       return -1;
 #endif
-    }
 
-  errno = ENOSYS;
-  return -1;
+    case _PC_SOCK_MAXBUF:
+#ifdef SOCK_MAXBUF
+      return SOCK_MAXBUF;
+#else
+      return -1;
+#endif
+
+    case _PC_FILESIZEBITS:
+#ifdef FILESIZEBITS
+      return FILESIZEBITS;
+#else
+      /* We let platforms with larger file sizes overwrite this value.  */
+      return 32;
+#endif
+
+    case _PC_REC_INCR_XFER_SIZE:
+      /* XXX It is not entirely clear what the limit is supposed to do.
+        What is incremented?  */
+      return -1;
+
+    case _PC_REC_MAX_XFER_SIZE:
+      /* XXX It is not entirely clear what the limit is supposed to do.
+        In general there is no top limit of the number of bytes which
+        case be transported at once.  */
+      return -1;
+
+    case _PC_REC_MIN_XFER_SIZE:
+      {
+       /* XXX It is not entirely clear what the limit is supposed to do.
+          I assume this is the block size of the filesystem.  */
+       struct statvfs64 sv;
+
+       if (__fstatvfs64 (fd, &sv) < 0)
+         return -1;
+       return sv.f_bsize;
+      }
+
+    case _PC_REC_XFER_ALIGN:
+      {
+       /* XXX It is not entirely clear what the limit is supposed to do.
+          I assume that the number should reflect the minimal block
+          alignment.  */
+       struct statvfs64 sv;
+
+       if (__fstatvfs64 (fd, &sv) < 0)
+         return -1;
+       return sv.f_frsize;
+      }
+
+    case _PC_ALLOC_SIZE_MIN:
+      {
+       /* XXX It is not entirely clear what the limit is supposed to do.
+          I assume that the number should reflect the minimal block
+          alignment.  */
+       struct statvfs64 sv;
+
+       if (__fstatvfs64 (fd, &sv) < 0)
+         return -1;
+       return sv.f_frsize;
+      }
+
+    case _PC_SYMLINK_MAX:
+      /* In general there are no limits.  If a system has one it should
+        overwrite this case.  */
+      return -1;
+
+    case _PC_2_SYMLINKS:
+      /* Unix systems generally have symlinks.  */
+      return 1;
+    }
 }
 
+#undef __fpathconf
 weak_alias (__fpathconf, fpathconf)