1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <unistd.h>
30 
31 #include <errno.h>
32 #include <sys/limits.h>
33 #include <sys/vfs.h>
34 
__filesizebits(const struct statfs & s)35 static long __filesizebits(const struct statfs& s) {
36   switch (s.f_type) {
37     case JFFS2_SUPER_MAGIC:
38     case MSDOS_SUPER_MAGIC:
39     case NCP_SUPER_MAGIC:
40       return 32;
41   }
42   // There won't be any new 32-bit file systems.
43   return 64;
44 }
45 
__link_max(const struct statfs & s)46 static long __link_max(const struct statfs& s) {
47   // These constant values were taken from kernel headers.
48   // They're not available in uapi headers.
49   switch (s.f_type) {
50     case EXT2_SUPER_MAGIC:
51       return 32000;
52     case MINIX_SUPER_MAGIC:
53       return 250;
54     case MINIX2_SUPER_MAGIC:
55       return 65530;
56     case REISERFS_SUPER_MAGIC:
57       return 0xffff - 1000;
58     case UFS_MAGIC:
59       return 32000;
60   }
61   return LINK_MAX;
62 }
63 
__2_symlinks(const struct statfs & s)64 static long __2_symlinks(const struct statfs& s) {
65   switch (s.f_type) {
66     case ADFS_SUPER_MAGIC:
67     case BFS_MAGIC:
68     case CRAMFS_MAGIC:
69     case EFS_SUPER_MAGIC:
70     case MSDOS_SUPER_MAGIC:
71     case QNX4_SUPER_MAGIC:
72       return 0;
73   }
74   return 1;
75 }
76 
__pathconf(const struct statfs & s,int name)77 static long __pathconf(const struct statfs& s, int name) {
78   switch (name) {
79     case _PC_FILESIZEBITS:
80       return __filesizebits(s);
81 
82     case _PC_LINK_MAX:
83       return __link_max(s);
84 
85     case _PC_MAX_CANON:
86       return MAX_CANON;
87 
88     case _PC_MAX_INPUT:
89       return MAX_INPUT;
90 
91     case _PC_NAME_MAX:
92       return s.f_namelen;
93 
94     case _PC_PATH_MAX:
95       return PATH_MAX;
96 
97     case _PC_PIPE_BUF:
98       return PIPE_BUF;
99 
100     case _PC_2_SYMLINKS:
101       return __2_symlinks(s);
102 
103     case _PC_ALLOC_SIZE_MIN:  /* fall through */
104     case _PC_REC_XFER_ALIGN:
105       return s.f_frsize;
106 
107     case _PC_REC_MIN_XFER_SIZE:
108       return s.f_bsize;
109 
110 #if 0
111     case _PC_REC_INCR_XFER_SIZE:
112     case _PC_REC_MAX_XFER_SIZE:
113 #endif
114 
115     case _PC_SYMLINK_MAX:
116       return -1; /* no limit */
117 
118     case _PC_CHOWN_RESTRICTED:
119       return _POSIX_CHOWN_RESTRICTED;
120 
121     case _PC_NO_TRUNC:
122       return _POSIX_NO_TRUNC;
123 
124     case _PC_VDISABLE:
125       return _POSIX_VDISABLE;
126 
127     case _PC_ASYNC_IO:
128       return -1;
129 
130     case _PC_PRIO_IO:
131       return -1;
132 
133     case _PC_SYNC_IO:
134       return -1;
135 
136     default:
137       errno = EINVAL;
138       return -1;
139   }
140 }
141 
pathconf(const char * path,int name)142 long pathconf(const char* path, int name) {
143   struct statfs sb;
144   if (statfs(path, &sb) == -1) {
145     return -1;
146   }
147   return __pathconf(sb, name);
148 }
149 
fpathconf(int fd,int name)150 long fpathconf(int fd, int name) {
151   struct statfs sb;
152   if (fstatfs(fd, &sb) == -1) {
153     return -1;
154   }
155   return __pathconf(sb, name);
156 }
157