You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux磁盘剩余空间获取方法及long返回值类型的容量上限问题

问题解答

会,这是原代码非常典型的溢出漏洞,具体说明如下:

  • 首先纠正你对f_bavail类型的误解:根据POSIX标准,struct statvfs里的f_bavail类型不是unsigned long,是fsblkcnt_t类型,这是一个平台相关的无符号整数类型,32位系统下通常是32位无符号数,64位系统下通常是64位无符号数。
  • 32位系统环境下:long是32位有符号整数,最大值仅为2^31-1(约2GB)。常见的文件系统块大小为4KB,只要磁盘剩余空间超过2GB,f_bsize * f_bavail的结果就会超过32位long的承载上限,出现溢出截断,返回完全错误的负值或者小数值。
  • 64位系统环境下:主流Linux采用LP64模型,long是64位有符号整数,最大值为263-1(约9EB),目前民用级存储暂时不会触及这个上限,但如果是面向大规模分布式存储场景,依然存在溢出风险。另外还有一个隐性问题:两个无符号整数相乘的结果是无符号类型,如果乘积刚好超过263-1,强制转换为有符号long后会变成负数,逻辑完全错误。

修正方案

可以参考如下代码规避溢出问题:

#include <sys/statvfs.h>
#include <stdint.h>
#include <stdio.h>

uint64_t GetAvailableSpace(const char* path, int* err)
{
  struct statvfs stat;
  if (statvfs(path, &stat) != 0) {
    if (err) *err = -1;
    return 0;
  }
  uint64_t bsize = stat.f_bsize;
  uint64_t bavail = stat.f_bavail;
  // 溢出校验
  if (bavail > UINT64_MAX / bsize) {
    if (err) *err = -2;
    return UINT64_MAX;
  }
  if (err) *err = 0;
  return bsize * bavail;
}

int main(int argc, const char *argv[])
{
   if (argc < 2) {
       printf("Usage: %s <path>\n", argv[0]);
       return 1;
   }
   int err;
   uint64_t avail = GetAvailableSpace(argv[1], &err);
   if (err != 0) {
       printf("Get available space failed, err: %d\n", err);
       return 1;
   }
   printf("The remaining size is %lu \n", (unsigned long)avail);
   return 0;
}

内容的提问来源于stack exchange,提问作者user1538798

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 11:54:03