2010-10-10 16 views
5

Escribo una aplicación multiplataforma y necesito el espacio total en disco disponible. Para los sistemas posix (Linux y Macos) estoy usando statvfs. Creé este método de C++:¿Cómo obtener espacio de disco total disponible en sistemas Posix?

long OSSpecificPosix::getFreeDiskSpace(const char* absoluteFilePath) { 
    struct statvfs buf; 

    if (!statvfs(absoluteFilePath, &buf)) { 
     unsigned long blksize, blocks, freeblks, disk_size, used, free; 
     blksize = buf.f_bsize; 
     blocks = buf.f_blocks; 
     freeblks = buf.f_bfree; 

     disk_size = blocks*blksize; 
     free = freeblks*blksize; 
     used = disk_size - free; 

     return free; 
    } 
    else { 
     return -1; 
    } 
} 

Desafortunadamente estoy obteniendo valores bastante extraños que no puedo entender. Por ejemplo: f_blocks = 73242188 f_bsize = 1048576 f_bfree = 50393643 ...

son aquellos valores en bits, bytes o cualquier otra cosa? Leí aquí en stackoverflow esos deben ser bytes, pero luego me gustaría tener el número total de bytes libres es: f_bsize * f_bfree = 1048576 * 50393643 pero esto significa 49212.542GB ... demasiado ...

Am Estoy haciendo algo mal con el código o cualquier otra cosa? Gracias!

+0

¿Qué sistema de archivos está usando que tiene un tamaño de bloque de 1048576? –

+0

Este es un sistema operativo Mac extendido (mayúsculas y minúsculas, registro). En este momento estoy trabajando en mac, pero, por lo que puedo entender, se supone que esto funciona. –

+0

Además de la rareza con su tamaño de bloque y su supuesta unidad de 70TB, tenga en cuenta que un 'largo' en OSX de 32 bits es de solo 32 bits. Incluso una vez que tenga los números correctos, es probable que sea lo suficientemente grande para su número de * bloques *, pero no lo suficientemente grande para su número de * bytes *. Pueden obtenerse unidades de hasta 4GB de proveedores especializados ;-) –

Respuesta

2

Supongo que las dos últimas respuestas son correctas y útiles. Sin embargo, lo resolví simplemente reemplazando la función statvfs con la función statfs. El tamaño del bloque es 4096 como se esperaba y todo parece ser correcto. Gracias!

+1

'statfs' está en desuso. –

+0

No puedo ver dónde 'statfs' está en desuso en OS X. También' statfs' produce los valores correctos. – codingFriend1

+0

Tampoco puedo ver eso: https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/statfs.2.html. –

8

No sé OSX lo suficientemente bien como para predecir esto es definitivamente la respuesta, pero f_blocks y f_bfree en realidad se refieren a "bloques fundamentales", o "fragmentos" (que son de tamaño buf.f_frsize bytes), no el "bloque de sistema de archivos tamaño"(que es buf.f_bsize bytes):

http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html

f_bsize es sólo una pista de lo que es el tamaño preferido para las operaciones de E/S, no es necesariamente algo que ver con la forma en el sistema de archivos se divide.

3

Las siguientes líneas:

disk_size = blocks*blksize; 
free = freeblks*blksize; 

causará desbordamiento al tener enorme HDS.

Estaba obteniendo resultados extraños también hasta que descubrí que mi HD es 455GiB, por favor considere lanzar bloques, blksize y freeblks vars a unsigned mucho antes de hacer la multiplicación.

Algo como esto:

unsigned long long disk_size = (unsigned long long) (blocks) * (unsigned long long) (blksize) 

que he visto un montón de preguntas de este tipo, pero nadie se dio cuenta esto en las respuestas.

+0

¡Buena captura! Yo también vi los números extraños (sin firmar por mucho tiempo) – lppier

1
uint64_t userAvailableFreeSpace() 
{ 
    struct statvfs stat; 
    struct passwd *pw = getpwuid(getuid()); 
    if (NULL != pw && 0 == statvfs(pw->pw_dir, &stat)) 
    { 
     uint64_t freeBytes = (uint64_t)stat.f_bavail * stat.f_frsize; 
     return freeBytes; 
    } 
    return 0ULL; 
} 
Cuestiones relacionadas