Questa funzione, formatta o ritorna la grandezza visualizzata di un file o di una directory. Prende come parametri la grandezza in bytes e il tipo da visualizzare, se non viene specificato nessun tipo, formatta la grandezza automaticamente.
I tipi supportati sono ‘b’ per bytes, ‘k’ per kilobytes, ‘m’ per megabytes, ‘g’ per gigabites oppure 0 per la formattazione automatica. Alloca memoria dinamica quindi bisogna liberarla quando si è finito di usarla.
Notare come questa funzione si prende cura di formattare graziosamente l’output e approssimarlo proporzionalmente alla grandezza evitando di ritornare risultati del tipo 1000 bytes (restituirà infatti 0,98kb), che non corrispondono ancora 1 kilobyte, ma sono brutti da vedere.
char *format_size(unsigned long bytes, char type) {
unsigned long divfactor;
char *retfmt = NULL;
#define RETSIZE 128
switch (type) {
case 'b':
divfactor = 1;
break;
case 'k':
divfactor = 1024;
break;
case 'm':
divfactor = 1024 * 1024;
break;
case 'g':
divfactor = 1024 * 1024 * 1024;
break;
default:
divfactor = 0;
}
retfmt = (char *)malloc(RETSIZE+1);
if (!retfmt) return NULL;
if (divfactor) {
snprintf(retfmt, RETSIZE, "%lu", (bytes / divfactor));
} else {
float kb = bytes / 1024.00;
if (bytes < 1000) {
snprintf(retfmt, RETSIZE, " %d", (int)bytes);
} else if (bytes < 1024) {
snprintf(retfmt, RETSIZE, "%0.2fk", kb);
} else if (kb < 10) {
snprintf(retfmt, RETSIZE, "%1.1fk", kb);
} else {
float mb = kb / 1024.00;
if (kb < 1000) {
snprintf(retfmt, RETSIZE, "%3.0fk", kb);
} else if (kb < 1024) {
snprintf(retfmt, RETSIZE, "%0.2fM", mb);
} else if (mb < 10) {
snprintf(retfmt, RETSIZE, "%1.1fM", mb);
} else {
float gb = mb / 1024.00;
if (mb < 1000) {
snprintf(retfmt, RETSIZE, "%3.0fM", mb);
} else if (mb < 1024) {
snprintf(retfmt, RETSIZE, "%0.2fG", gb);
} else if (gb < 10) {
snprintf(retfmt, RETSIZE, "%1.1fG", gb);
} else {
snprintf(retfmt, RETSIZE, "%3.0fG", gb);
}
}
}
}
return retfmt;
}