Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <sys/statvfs.h>
     18 
     19 #include <sys/statfs.h>
     20 
     21 // Paper over the fact that 32-bit kernels use fstatfs64/statfs64 with an extra argument,
     22 // but 64-bit kernels don't have the "64" bit suffix or the extra size_t argument.
     23 #if defined(__LP64__)
     24 extern "C" int __fstatfs(int, struct statfs*);
     25 extern "C" int __statfs(const char*, struct statfs*);
     26 #  define __fstatfs64(fd,size,buf) __fstatfs(fd,buf)
     27 #  define __statfs64(path,size,buf) __statfs(path,buf)
     28 #else
     29 extern "C" int __fstatfs64(int, size_t, struct statfs*);
     30 extern "C" int __statfs64(const char*, size_t, struct statfs*);
     31 #endif
     32 
     33 // The kernel sets a private ST_VALID flag to signal to the C library whether the
     34 // f_flags field is valid. This flag should not be exposed to users of the C library.
     35 #define ST_VALID 0x0020
     36 
     37 static void __statfs_to_statvfs(const struct statfs& in, struct statvfs* out) {
     38   out->f_bsize = in.f_bsize;
     39   out->f_frsize = in.f_frsize;
     40   out->f_blocks = in.f_blocks;
     41   out->f_bfree = in.f_bfree;
     42   out->f_bavail = in.f_bavail;
     43   out->f_files = in.f_files;
     44   out->f_ffree = in.f_ffree;
     45   out->f_favail = in.f_ffree;
     46   out->f_fsid = in.f_fsid.__val[0] | (static_cast<uint64_t>(in.f_fsid.__val[1]) << 32);
     47   out->f_flag = in.f_flags;
     48   out->f_namemax = in.f_namelen;
     49 }
     50 
     51 int fstatfs(int fd, struct statfs* result) {
     52   int rc = __fstatfs64(fd, sizeof(*result), result);
     53   if (rc != 0) {
     54     return rc;
     55   }
     56   result->f_flags &= ~ST_VALID;
     57   return 0;
     58 }
     59 __strong_alias(fstatfs64, fstatfs);
     60 
     61 int statfs(const char* path, struct statfs* result) {
     62   int rc = __statfs64(path, sizeof(*result), result);
     63   if (rc != 0) {
     64     return rc;
     65   }
     66   result->f_flags &= ~ST_VALID;
     67   return 0;
     68 }
     69 __strong_alias(statfs64, statfs);
     70 
     71 int statvfs(const char* path, struct statvfs* result) {
     72   struct statfs tmp;
     73   int rc = statfs(path, &tmp);
     74   if (rc != 0) {
     75     return rc;
     76   }
     77   __statfs_to_statvfs(tmp, result);
     78   return 0;
     79 }
     80 __strong_alias(statvfs64, statvfs);
     81 
     82 int fstatvfs(int fd, struct statvfs* result) {
     83   struct statfs tmp;
     84   int rc = fstatfs(fd, &tmp);
     85   if (rc != 0) {
     86     return rc;
     87   }
     88   __statfs_to_statvfs(tmp, result);
     89   return 0;
     90 }
     91 __strong_alias(fstatvfs64, fstatvfs);
     92