1  /* Copyright (C) 1991-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <stddef.h>
      20  #include <unistd.h>
      21  #include <limits.h>
      22  #include <fcntl.h>
      23  #include <sys/stat.h>
      24  #include <sys/statfs.h>
      25  #include <sys/statvfs.h>
      26  
      27  
      28  /* Get file-specific information about PATH.  */
      29  long int
      30  __pathconf (const char *path, int name)
      31  {
      32    if (path[0] == '\0')
      33      {
      34        __set_errno (ENOENT);
      35        return -1;
      36      }
      37  
      38    switch (name)
      39      {
      40      default:
      41        __set_errno (EINVAL);
      42        return -1;
      43  
      44      case _PC_LINK_MAX:
      45  #ifdef	LINK_MAX
      46        return LINK_MAX;
      47  #else
      48        return -1;
      49  #endif
      50  
      51      case _PC_MAX_CANON:
      52  #ifdef	MAX_CANON
      53        return MAX_CANON;
      54  #else
      55        return -1;
      56  #endif
      57  
      58      case _PC_MAX_INPUT:
      59  #ifdef	MAX_INPUT
      60        return MAX_INPUT;
      61  #else
      62        return -1;
      63  #endif
      64  
      65      case _PC_NAME_MAX:
      66  #ifdef	NAME_MAX
      67        {
      68  	struct statvfs64 sv;
      69  	int save_errno = errno;
      70  
      71  	if (__statvfs64 (path, &sv) < 0)
      72  	  {
      73  	    if (errno == ENOSYS)
      74  	      {
      75  		errno = save_errno;
      76  		return NAME_MAX;
      77  	      }
      78  	    return -1;
      79  	  }
      80  	else
      81  	  {
      82  	    return sv.f_namemax;
      83  	  }
      84        }
      85  #else
      86        return -1;
      87  #endif
      88  
      89      case _PC_PATH_MAX:
      90  #ifdef	PATH_MAX
      91        return PATH_MAX;
      92  #else
      93        return -1;
      94  #endif
      95  
      96      case _PC_PIPE_BUF:
      97  #ifdef	PIPE_BUF
      98        return PIPE_BUF;
      99  #else
     100        return -1;
     101  #endif
     102  
     103      case _PC_CHOWN_RESTRICTED:
     104  #if _POSIX_CHOWN_RESTRICTED == -1
     105  # error "Invalid value for _POSIX_CHOWN_RESTRICTED"
     106  #endif
     107        return _POSIX_CHOWN_RESTRICTED;
     108  
     109      case _PC_NO_TRUNC:
     110  #if _POSIX_NO_TRUNC == -1
     111  # error "Invalid value for _POSIX_NO_TRUNC"
     112  #endif
     113        return _POSIX_NO_TRUNC;
     114  
     115      case _PC_VDISABLE:
     116  #if _POSIX_VDISABLE == -1
     117  # error "Invalid value for _POSIX_VDISABLE"
     118  #endif
     119        return _POSIX_VDISABLE;
     120  
     121      case _PC_SYNC_IO:
     122  #ifdef	_POSIX_SYNC_IO
     123        return _POSIX_SYNC_IO;
     124  #else
     125        return -1;
     126  #endif
     127  
     128      case _PC_ASYNC_IO:
     129  #ifdef	_POSIX_ASYNC_IO
     130        {
     131  	/* AIO is only allowed on regular files and block devices.  */
     132  	struct __stat64_t64 st;
     133  
     134  	if (__stat64_time64 (path, &st) < 0
     135  	    || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode)))
     136  	  return -1;
     137  	else
     138  	  return 1;
     139        }
     140  #else
     141        return -1;
     142  #endif
     143  
     144      case _PC_PRIO_IO:
     145  #ifdef	_POSIX_PRIO_IO
     146        return _POSIX_PRIO_IO;
     147  #else
     148        return -1;
     149  #endif
     150  
     151      case _PC_SOCK_MAXBUF:
     152  #ifdef	SOCK_MAXBUF
     153        return SOCK_MAXBUF;
     154  #else
     155        return -1;
     156  #endif
     157  
     158      case _PC_FILESIZEBITS:
     159  #ifdef FILESIZEBITS
     160        return FILESIZEBITS;
     161  #else
     162        /* We let platforms with larger file sizes overwrite this value.  */
     163        return 32;
     164  #endif
     165  
     166      case _PC_REC_INCR_XFER_SIZE:
     167        /* XXX It is not entirely clear what the limit is supposed to do.
     168  	 What is incremented?  */
     169        return -1;
     170  
     171      case _PC_REC_MAX_XFER_SIZE:
     172        /* XXX It is not entirely clear what the limit is supposed to do.
     173  	 In general there is no top limit of the number of bytes which
     174  	 case be transported at once.  */
     175        return -1;
     176  
     177      case _PC_REC_MIN_XFER_SIZE:
     178        {
     179  	/* XXX It is not entirely clear what the limit is supposed to do.
     180  	   I assume this is the block size of the filesystem.  */
     181  	struct statvfs64 sv;
     182  
     183  	if (__statvfs64 (path, &sv) < 0)
     184  	  return -1;
     185  	return sv.f_bsize;
     186        }
     187  
     188      case _PC_REC_XFER_ALIGN:
     189        {
     190  	/* XXX It is not entirely clear what the limit is supposed to do.
     191  	   I assume that the number should reflect the minimal block
     192  	   alignment.  */
     193  	struct statvfs64 sv;
     194  
     195  	if (__statvfs64 (path, &sv) < 0)
     196  	  return -1;
     197  	return sv.f_frsize;
     198        }
     199  
     200      case _PC_ALLOC_SIZE_MIN:
     201        {
     202  	/* XXX It is not entirely clear what the limit is supposed to do.
     203  	   I assume that the number should reflect the minimal block
     204  	   alignment.  */
     205  	struct statvfs64 sv;
     206  
     207  	if (__statvfs64 (path, &sv) < 0)
     208  	  return -1;
     209  	return sv.f_frsize;
     210        }
     211  
     212      case _PC_SYMLINK_MAX:
     213        /* In general there are no limits.  If a system has one it should
     214  	 overwrite this case.  */
     215        return -1;
     216  
     217      case _PC_2_SYMLINKS:
     218        /* Unix systems generally have symlinks.  */
     219        return 1;
     220      }
     221  }
     222  
     223  #undef __pathconf
     224  weak_alias (__pathconf, pathconf)