5252# define EX_OK EXIT_SUCCESS
5353#endif
5454
55+ #ifdef __APPLE__
56+ /* Needed for the implementation of os.statvfs */
57+ # include <sys/param.h>
58+ # include <sys/mount.h>
59+ #endif
60+
5561/* On android API level 21, 'AT_EACCESS' is not declared although
5662 * HAVE_FACCESSAT is defined. */
5763#ifdef __ANDROID__
@@ -12886,6 +12892,59 @@ os_WSTOPSIG_impl(PyObject *module, int status)
1288612892#endif
1288712893#include <sys/statvfs.h>
1288812894
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+
1288912948static PyObject *
1289012949_pystatvfs_fromstructstatvfs (PyObject * module , struct statvfs st ) {
1289112950 PyObject * StatVFSResultType = get_posix_state (module )-> StatVFSResultType ;
@@ -12937,6 +12996,8 @@ _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
1293712996 return v ;
1293812997}
1293912998
12999+ #endif
13000+
1294013001
1294113002/*[clinic input]
1294213003os.fstatvfs
@@ -12954,6 +13015,22 @@ os_fstatvfs_impl(PyObject *module, int fd)
1295413015{
1295513016 int result ;
1295613017 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
1295713034 struct statvfs st ;
1295813035
1295913036 do {
@@ -12966,6 +13043,7 @@ os_fstatvfs_impl(PyObject *module, int fd)
1296613043 return (!async_err ) ? posix_error () : NULL ;
1296713044
1296813045 return _pystatvfs_fromstructstatvfs (module , st );
13046+ #endif
1296913047}
1297013048#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
1297113049
@@ -12989,6 +13067,28 @@ os_statvfs_impl(PyObject *module, path_t *path)
1298913067/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
1299013068{
1299113069 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
1299213092 struct statvfs st ;
1299313093
1299413094 Py_BEGIN_ALLOW_THREADS
@@ -13006,6 +13106,7 @@ os_statvfs_impl(PyObject *module, path_t *path)
1300613106 }
1300713107
1300813108 return _pystatvfs_fromstructstatvfs (module , st );
13109+ #endif
1300913110}
1301013111#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
1301113112
0 commit comments