stafs结构元素

时间:2015-08-21 10:56:46

标签: c stat

我正在尝试检索安装在我的Linux系统上的外部SD卡的文件系统信息(带有C程序)。

根据 bits / statfs.h

statfs 的定义
struct statfs
{
  __SWORD_TYPE f_type;
  __SWORD_TYPE f_bsize;
#ifndef __USE_FILE_OFFSET64
  __fsblkcnt_t f_blocks;
  __fsblkcnt_t f_bfree;
  __fsblkcnt_t f_bavail;
  __fsfilcnt_t f_files;
  __fsfilcnt_t f_ffree;
#else
  __fsblkcnt64_t f_blocks;
  __fsblkcnt64_t f_bfree;
  __fsblkcnt64_t f_bavail;
  __fsfilcnt64_t f_files;
  __fsfilcnt64_t f_ffree;
#endif
  __fsid_t f_fsid;
  __SWORD_TYPE f_namelen;
  __SWORD_TYPE f_frsize;
  __SWORD_TYPE f_flags;
  __SWORD_TYPE f_spare[4];
};

我写了这个小例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/statfs.h>

int main(int argc, const char *argv[])
{
   struct statfs buffer;

   unsigned long int total = 0;
   unsigned long int available = 0;

   statfs(argv[1], &buffer);

   total = buffer.f_blocks * buffer.f_frsize;
   available = buffer.f_bavail * buffer.f_frsize;

   printf("Total size of %s: %ld\n", argv[1], total);
   printf("Total free space: %ld\n", available);

   return 0;
}

但是当代码执行时,我总是检索负值:

~$ ./fsStat /media/E4AD-87E9
Total size of /media/E4AD-87E9: -637362176
Total free space: -637366272
~$

mount df 的输出为:

~$ mount
/dev/mmcblk0p1 on /media/E4AD-87E9 type vfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0077,codepage=cp437,iocharset=utf8,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks)

~$ df
Filesystem                                             1K-blocks     Used Available Use% Mounted on
/dev/mmcblk0p1                                           7766184        4   7766180   1% /media/E4AD-87E9

我的C代码出了什么问题?

2 个答案:

答案 0 :(得分:3)

您的代码存在的问题是您尝试打印long int而不是unsigned long int。您需要更改printf语句,如下所示:

printf("Total size of %s: %lu\n", argv[1], total);
printf("Total free space: %lu\n", available);

答案 1 :(得分:0)

代码有另一个问题。

__fsblkcnt_t不是标准类型,没有printf()说明符。至少在一个place中,它是64位无符号。

OP的代码可以通过分配更窄的类型进行限制,因为unsigned long只能确定至少有32位。

unsigned long int total = 0;
...
// Multiplication could overflow
// Assigment could narrow the product
total = buffer.f_blocks * buffer.f_frsize;

在代码不确定类型范围__fsblkcnt_t的地方,考虑更宽的类型并确保乘法也很宽。这将减少溢出/缩小的可能性。

unsigned long long total = 0;
...
total = 1ULL * buffer.f_blocks * buffer.f_frsize;
// use u for unsigned types, not d
printf("Total size of %s: %llu\n", argv[1], total);

为了好玩,考虑到Moore's law,外部SD卡的total大小将在2075年左右超过64位.YMMV

代码可以使用uintmax_t代替unsigned long long并检测产品溢出。 IMO uintmax_t通常会在十年左右超过64位。

#include <inttypes.h>
uintmax_t total;
...
if (UINTMAX_MAX/buffer.f_blocks >= buffer.f_frsize) 
  total = UINTMAX_MAX;
else 
  total = UINTMAX_C(1) * buffer.f_blocks * buffer.f_frsize;
// use j with intmax_t/uintmax_t
printf("Total size of %s: %ju\n", argv[1], total);