diff --git a/libc/Android.bp b/libc/Android.bp index 71d4d4a6a5..c64fcf0cef 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -1133,6 +1133,7 @@ cc_library_static { "bionic/sigprocmask.cpp", "bionic/spawn.cpp", "bionic/stat.cpp", + "bionic/statfs.cpp", "bionic/statvfs.cpp", "bionic/stdlib_l.cpp", "bionic/strchrnul.cpp", diff --git a/libc/bionic/statfs.cpp b/libc/bionic/statfs.cpp new file mode 100644 index 0000000000..d78de2ddcb --- /dev/null +++ b/libc/bionic/statfs.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +// Paper over the fact that 32-bit kernels use fstatfs64/statfs64 with +// an extra argument, but 64-bit kernels don't have the "64" bit suffix or +// the extra size_t argument. +#if defined(__LP64__) +extern "C" int __fstatfs(int, struct statfs*); +extern "C" int __statfs(const char*, struct statfs*); +# define __fstatfs64(fd,size,buf) __fstatfs(fd,buf) +# define __statfs64(path,size,buf) __statfs(path,buf) +#else +extern "C" int __fstatfs64(int, size_t, struct statfs*); +extern "C" int __statfs64(const char*, size_t, struct statfs*); +#endif + +// The kernel sets a private ST_VALID flag to signal to the C library +// whether the f_flags field is valid. This flag should not be exposed to +// users of the C library. +#define ST_VALID 0x0020 + +int fstatfs(int fd, struct statfs* result) { + int rc = __fstatfs64(fd, sizeof(*result), result); + if (rc != 0) { + return rc; + } + result->f_flags &= ~ST_VALID; + return 0; +} +__strong_alias(fstatfs64, fstatfs); + +int statfs(const char* path, struct statfs* result) { + int rc = __statfs64(path, sizeof(*result), result); + if (rc != 0) { + return rc; + } + result->f_flags &= ~ST_VALID; + return 0; +} +__strong_alias(statfs64, statfs); diff --git a/libc/bionic/statvfs.cpp b/libc/bionic/statvfs.cpp index cd825eb16c..bbb0026e06 100644 --- a/libc/bionic/statvfs.cpp +++ b/libc/bionic/statvfs.cpp @@ -16,76 +16,19 @@ #include -#include +// libc++ uses statvfs (for Darwin compatibility), but on Linux statvfs is +// just another name for statfs, so it didn't arrive until API level 19. We +// make the implementation available as inlines to support std::filesystem +// for NDK users (see https://github.com/android-ndk/ndk/issues/609). -// Paper over the fact that 32-bit kernels use fstatfs64/statfs64 with an extra argument, -// but 64-bit kernels don't have the "64" bit suffix or the extra size_t argument. -#if defined(__LP64__) -extern "C" int __fstatfs(int, struct statfs*); -extern "C" int __statfs(const char*, struct statfs*); -# define __fstatfs64(fd,size,buf) __fstatfs(fd,buf) -# define __statfs64(path,size,buf) __statfs(path,buf) -#else -extern "C" int __fstatfs64(int, size_t, struct statfs*); -extern "C" int __statfs64(const char*, size_t, struct statfs*); -#endif +#define __BIONIC_SYS_STATVFS_INLINE /* Out of line. */ +#include -// The kernel sets a private ST_VALID flag to signal to the C library whether the -// f_flags field is valid. This flag should not be exposed to users of the C library. -#define ST_VALID 0x0020 +// Historically we provided actual symbols for statvfs64 and fstatvfs64. +// They're not particularly useful, but we can't take them away. -static void __statfs_to_statvfs(const struct statfs& in, struct statvfs* out) { - out->f_bsize = in.f_bsize; - out->f_frsize = in.f_frsize; - out->f_blocks = in.f_blocks; - out->f_bfree = in.f_bfree; - out->f_bavail = in.f_bavail; - out->f_files = in.f_files; - out->f_ffree = in.f_ffree; - out->f_favail = in.f_ffree; - out->f_fsid = in.f_fsid.__val[0] | (static_cast(in.f_fsid.__val[1]) << 32); - out->f_flag = in.f_flags; - out->f_namemax = in.f_namelen; -} - -int fstatfs(int fd, struct statfs* result) { - int rc = __fstatfs64(fd, sizeof(*result), result); - if (rc != 0) { - return rc; - } - result->f_flags &= ~ST_VALID; - return 0; -} -__strong_alias(fstatfs64, fstatfs); - -int statfs(const char* path, struct statfs* result) { - int rc = __statfs64(path, sizeof(*result), result); - if (rc != 0) { - return rc; - } - result->f_flags &= ~ST_VALID; - return 0; -} -__strong_alias(statfs64, statfs); - -int statvfs(const char* path, struct statvfs* result) { - struct statfs tmp; - int rc = statfs(path, &tmp); - if (rc != 0) { - return rc; - } - __statfs_to_statvfs(tmp, result); - return 0; -} +#undef statvfs64 __strong_alias(statvfs64, statvfs); -int fstatvfs(int fd, struct statvfs* result) { - struct statfs tmp; - int rc = fstatfs(fd, &tmp); - if (rc != 0) { - return rc; - } - __statfs_to_statvfs(tmp, result); - return 0; -} +#undef fstatvfs64 __strong_alias(fstatvfs64, fstatvfs); diff --git a/libc/include/android/legacy_sys_statvfs_inlines.h b/libc/include/android/legacy_sys_statvfs_inlines.h new file mode 100644 index 0000000000..e42ff38c7a --- /dev/null +++ b/libc/include/android/legacy_sys_statvfs_inlines.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#pragma once + +/** + * @file legacy_sys_statvfs_inlines.h + * @brief Inline definitions of statvfs/fstatvfs for old API levels. + */ + +#include + +#if __ANDROID_API__ < 19 + +#define __BIONIC_SYS_STATVFS_INLINE static __inline +#include + +#endif diff --git a/libc/include/bits/sys_statvfs_inlines.h b/libc/include/bits/sys_statvfs_inlines.h new file mode 100644 index 0000000000..38ab6d1d85 --- /dev/null +++ b/libc/include/bits/sys_statvfs_inlines.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include + +#if defined(__BIONIC_SYS_STATVFS_INLINE) + +__BEGIN_DECLS + +static __inline void __bionic_statfs_to_statvfs(const struct statfs* __in, + struct statvfs* __out) { + __out->f_bsize = __in->f_bsize; + __out->f_frsize = __in->f_frsize; + __out->f_blocks = __in->f_blocks; + __out->f_bfree = __in->f_bfree; + __out->f_bavail = __in->f_bavail; + __out->f_files = __in->f_files; + __out->f_ffree = __in->f_ffree; + __out->f_favail = __in->f_ffree; + __out->f_fsid = __in->f_fsid.__val[0] | + __BIONIC_CAST(static_cast, uint64_t, __in->f_fsid.__val[1]) << 32; + __out->f_flag = __in->f_flags; + __out->f_namemax = __in->f_namelen; +} + +__BIONIC_SYS_STATVFS_INLINE int statvfs(const char* path, + struct statvfs* result) { + struct statfs __tmp; + int __rc = statfs(path, &__tmp); + if (__rc != 0) return __rc; + __bionic_statfs_to_statvfs(&__tmp, result); + return 0; +} + +__BIONIC_SYS_STATVFS_INLINE int fstatvfs(int fd, + struct statvfs* result) { + struct statfs __tmp; + int __rc = fstatfs(fd, &__tmp); + if (__rc != 0) return __rc; + __bionic_statfs_to_statvfs(&__tmp, result); + return 0; +} + +__END_DECLS + +#endif diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h index e60cadc751..30892eb8de 100644 --- a/libc/include/sys/statvfs.h +++ b/libc/include/sys/statvfs.h @@ -14,8 +14,12 @@ * limitations under the License. */ -#ifndef _SYS_STATVFS_H_ -#define _SYS_STATVFS_H_ +#pragma once + +/** + * @file sys/statvfs.h + * @brief Filesystem statistics. + */ #include #include @@ -23,47 +27,86 @@ __BEGIN_DECLS -#ifdef __LP64__ -#define __STATVFS64_RESERVED uint32_t __f_reserved[6]; -#else -#define __STATVFS64_RESERVED -#endif +struct statvfs { + /** Block size. */ + unsigned long f_bsize; + /** Fragment size. */ + unsigned long f_frsize; + /** Total size of filesystem in `f_frsize` blocks. */ + fsblkcnt_t f_blocks; + /** Number of free blocks. */ + fsblkcnt_t f_bfree; + /** Number of free blocks for non-root. */ + fsblkcnt_t f_bavail; + /** Number of inodes. */ + fsfilcnt_t f_files; + /** Number of free inodes. */ + fsfilcnt_t f_ffree; + /** Number of free inodes for non-root. */ + fsfilcnt_t f_favail; + /** Filesystem id. */ + unsigned long f_fsid; + /** Mount flags. (See `ST_` constants.) */ + unsigned long f_flag; + /** Maximum filename length. */ + unsigned long f_namemax; -#define __STATVFS64_BODY \ - unsigned long f_bsize; \ - unsigned long f_frsize; \ - fsblkcnt_t f_blocks; \ - fsblkcnt_t f_bfree; \ - fsblkcnt_t f_bavail; \ - fsfilcnt_t f_files; \ - fsfilcnt_t f_ffree; \ - fsfilcnt_t f_favail; \ - unsigned long f_fsid; \ - unsigned long f_flag; \ - unsigned long f_namemax; \ - __STATVFS64_RESERVED - -struct statvfs { __STATVFS64_BODY }; -struct statvfs64 { __STATVFS64_BODY }; - -#undef __STATVFS64_BODY -#undef __STATVFS64_RESERVED +#if defined(__LP64__) + uint32_t __f_reserved[6]; +#endif +}; +/** Flag for `f_flag` in `struct statvfs`: mounted read-only. */ #define ST_RDONLY 0x0001 + +/** Flag for `f_flag` in `struct statvfs`: setuid/setgid ignored. */ #define ST_NOSUID 0x0002 + +/** Flag for `f_flag` in `struct statvfs`: access to device files disallowed. */ #define ST_NODEV 0x0004 + +/** Flag for `f_flag` in `struct statvfs`: execution disallowed. */ #define ST_NOEXEC 0x0008 + +/** Flag for `f_flag` in `struct statvfs`: writes synced immediately. */ #define ST_SYNCHRONOUS 0x0010 + +/** Flag for `f_flag` in `struct statvfs`: mandatory locking permitted. */ #define ST_MANDLOCK 0x0040 + +/** Flag for `f_flag` in `struct statvfs`: access times not updated. */ #define ST_NOATIME 0x0400 + +/** Flag for `f_flag` in `struct statvfs`: directory access times not updated. */ #define ST_NODIRATIME 0x0800 + +/** Flag for `f_flag` in `struct statvfs`: see `MS_RELATIME`. */ #define ST_RELATIME 0x1000 +#if __ANDROID_API__ >= 19 +// This file is implemented as static inlines before API level 19. + +/** + * [statvfs(3)](http://man7.org/linux/man-pages/man3/statvfs.3.html) + * queries filesystem statistics for the given path. + * + * Returns 0 on success, and returns -1 and sets `errno` on failure. + */ int statvfs(const char* __path, struct statvfs* __buf) __INTRODUCED_IN(19); -int statvfs64(const char* __path, struct statvfs64* __buf) __INTRODUCED_IN(21); + +/** + * [fstatvfs(3)](http://man7.org/linux/man-pages/man3/fstatvfs.3.html) + * queries filesystem statistics for the given file descriptor. + * + * Returns 0 on success, and returns -1 and sets `errno` on failure. + */ int fstatvfs(int __fd, struct statvfs* __buf) __INTRODUCED_IN(19); -int fstatvfs64(int __fd, struct statvfs64* __buf) __INTRODUCED_IN(21); + +#endif + +#define statvfs64 statvfs +#define fstatvfs64 fstatvfs __END_DECLS -#endif +#include