52
52
# define EX_OK EXIT_SUCCESS
53
53
#endif
54
54
55
+ #ifdef __APPLE__
56
+ /* Needed for the implementation of os.statvfs */
57
+ # include <sys/param.h>
58
+ # include <sys/mount.h>
59
+ #endif
60
+
55
61
/* On android API level 21, 'AT_EACCESS' is not declared although
56
62
* HAVE_FACCESSAT is defined. */
57
63
#ifdef __ANDROID__
@@ -12886,6 +12892,59 @@ os_WSTOPSIG_impl(PyObject *module, int status)
12886
12892
#endif
12887
12893
#include <sys/statvfs.h>
12888
12894
12895
+ #ifdef __APPLE__
12896
+ /* On macOS struct statvfs uses 32-bit integers for block counts,
12897
+ * resulting in overflow when filesystems are larger tan 4TB. Therefore
12898
+ * os.statvfs is implemented in terms of statfs(2).
12899
+ */
12900
+
12901
+ static PyObject *
12902
+ _pystatvfs_fromstructstatfs (PyObject * module , struct statfs st ) {
12903
+ PyObject * StatVFSResultType = get_posix_state (module )-> StatVFSResultType ;
12904
+ PyObject * v = PyStructSequence_New ((PyTypeObject * )StatVFSResultType );
12905
+ if (v == NULL )
12906
+ return NULL ;
12907
+
12908
+ long flags = 0 ;
12909
+ if (st .f_flags & MNT_RDONLY ) {
12910
+ flags |= ST_RDONLY ;
12911
+ }
12912
+ if (st .f_flags & MNT_NOSUID ) {
12913
+ flags |= ST_NOSUID ;
12914
+ }
12915
+
12916
+ _Static_assert (sizeof (st .f_blocks ) == sizeof (long long ), "assuming large file" );
12917
+
12918
+ PyStructSequence_SET_ITEM (v , 0 , PyLong_FromLong ((long ) st .f_iosize ));
12919
+ PyStructSequence_SET_ITEM (v , 1 , PyLong_FromLong ((long ) st .f_bsize ));
12920
+ PyStructSequence_SET_ITEM (v , 2 ,
12921
+ PyLong_FromLongLong ((long long ) st .f_blocks ));
12922
+ PyStructSequence_SET_ITEM (v , 3 ,
12923
+ PyLong_FromLongLong ((long long ) st .f_bfree ));
12924
+ PyStructSequence_SET_ITEM (v , 4 ,
12925
+ PyLong_FromLongLong ((long long ) st .f_bavail ));
12926
+ PyStructSequence_SET_ITEM (v , 5 ,
12927
+ PyLong_FromLongLong ((long long ) st .f_files ));
12928
+ PyStructSequence_SET_ITEM (v , 6 ,
12929
+ PyLong_FromLongLong ((long long ) st .f_ffree ));
12930
+ PyStructSequence_SET_ITEM (v , 7 ,
12931
+ PyLong_FromLongLong ((long long ) st .f_ffree ));
12932
+ PyStructSequence_SET_ITEM (v , 8 , PyLong_FromLong ((long ) flags ));
12933
+
12934
+ PyStructSequence_SET_ITEM (v , 9 , PyLong_FromLong ((long ) NAME_MAX ));
12935
+ PyStructSequence_SET_ITEM (v , 10 , PyLong_FromUnsignedLong (st .f_fsid .val [0 ]));
12936
+ if (PyErr_Occurred ()) {
12937
+ Py_DECREF (v );
12938
+ return NULL ;
12939
+ }
12940
+
12941
+ return v ;
12942
+ }
12943
+
12944
+ #else
12945
+
12946
+
12947
+
12889
12948
static PyObject *
12890
12949
_pystatvfs_fromstructstatvfs (PyObject * module , struct statvfs st ) {
12891
12950
PyObject * StatVFSResultType = get_posix_state (module )-> StatVFSResultType ;
@@ -12937,6 +12996,8 @@ _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
12937
12996
return v ;
12938
12997
}
12939
12998
12999
+ #endif
13000
+
12940
13001
12941
13002
/*[clinic input]
12942
13003
os.fstatvfs
@@ -12954,6 +13015,22 @@ os_fstatvfs_impl(PyObject *module, int fd)
12954
13015
{
12955
13016
int result ;
12956
13017
int async_err = 0 ;
13018
+ #ifdef __APPLE__
13019
+ struct statfs st ;
13020
+ /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13021
+ * the former uses 32-bit values for block counts.
13022
+ */
13023
+ do {
13024
+ Py_BEGIN_ALLOW_THREADS
13025
+ result = fstatfs (fd , & st );
13026
+ Py_END_ALLOW_THREADS
13027
+ } while (result != 0 && errno == EINTR &&
13028
+ !(async_err = PyErr_CheckSignals ()));
13029
+ if (result != 0 )
13030
+ return (!async_err ) ? posix_error () : NULL ;
13031
+
13032
+ return _pystatvfs_fromstructstatfs (module , st );
13033
+ #else
12957
13034
struct statvfs st ;
12958
13035
12959
13036
do {
@@ -12966,6 +13043,7 @@ os_fstatvfs_impl(PyObject *module, int fd)
12966
13043
return (!async_err ) ? posix_error () : NULL ;
12967
13044
12968
13045
return _pystatvfs_fromstructstatvfs (module , st );
13046
+ #endif
12969
13047
}
12970
13048
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
12971
13049
@@ -12989,6 +13067,28 @@ os_statvfs_impl(PyObject *module, path_t *path)
12989
13067
/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
12990
13068
{
12991
13069
int result ;
13070
+
13071
+ #ifdef __APPLE__
13072
+ /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
13073
+ * the former uses 32-bit values for block counts.
13074
+ */
13075
+ struct statfs st ;
13076
+
13077
+ Py_BEGIN_ALLOW_THREADS
13078
+ if (path -> fd != -1 ) {
13079
+ result = fstatfs (path -> fd , & st );
13080
+ }
13081
+ else
13082
+ result = statfs (path -> narrow , & st );
13083
+ Py_END_ALLOW_THREADS
13084
+
13085
+ if (result ) {
13086
+ return path_error (path );
13087
+ }
13088
+
13089
+ return _pystatvfs_fromstructstatfs (module , st );
13090
+
13091
+ #else
12992
13092
struct statvfs st ;
12993
13093
12994
13094
Py_BEGIN_ALLOW_THREADS
@@ -13006,6 +13106,7 @@ os_statvfs_impl(PyObject *module, path_t *path)
13006
13106
}
13007
13107
13008
13108
return _pystatvfs_fromstructstatvfs (module , st );
13109
+ #endif
13009
13110
}
13010
13111
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
13011
13112
0 commit comments