2015-08-21 2 views
0

Я пытаюсь получить информацию о файловой системе (с программой на C) внешней SD-карты, установленной на моей Linux-системе.Отрицательные значения, возвращаемые элементами stafs struct

Согласно определению statfs в бит/statfs.h

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 
~$ 

Хотя oputput из крепления и ДФ является:

~$ 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?

ответ

3

Проблема с кодом заключается в том, что вы пытаетесь напечатать long int вместо unsigned long int. Вам необходимо изменить свои операторы printf следующим образом:

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

OMG Обязательно! Спасибо, Пуджа! –

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, то total размера внешней SD-карты будет превышать 64-битный о годе 2075 YMMV

код может использовать uintmax_t вместо unsigned long long и обнаружить переполнение продукта , IMO uintmax_t, как правило, превысит 64-разрядную версию за 10 лет.

#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); 
Смежные вопросы