• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Jeronimus Linuxius

Travessia de directórios POSIX

1 mensagem neste tópico

Há dias, enquanto vasculhava o Minix, resolvi escrever um utilitário que medisse o tamanho (disk usage) de um directório em Unix. Só depois me lembrei que já existe o "du" para fazer a mesma coisa :-), mas entratanto já estava escrito...

Atenção: este programa não ignora hard links (i.e. o tamanho dos ficheiro é contado duas vezes). Honestamente, não sei se segue symbolic links (não prestei atenção a isso).

Deu-me resultado diferente do "du" em muitos sítios, mas na maior parte dos casos esteve relativamente perto. A diferença mas aberrante foi no /lib (linux): o "du" deu-me 64MB enquanto que o dirsize me deu 2.31GB. :-) No entanto, serve pelo valor educativo.

Considerem-no sob domínio público.

/* Usage: ./dirsize directory */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>

char *convert ( unsigned long long original );
unsigned long long int traverse_dir(char *);

int main(int argc, char *argv[])
{
    char *dirname;
    unsigned long long int tot_size;

    if ( argc != 2 )
        return -1;
    dirname = argv[1];

    tot_size = traverse_dir(dirname);

    printf( "Disk usage for %s is %s (%llu bytes).\n",
             dirname, convert(tot_size), tot_size );

    return 0;

}

char *convert ( unsigned long long original )
{
    long double amount = original;
    static char ret[32];
    char *unitsv[] = { "bytes", "Kbytes", "Mbytes", "Gbytes", "Tbytes" };
    char **unitp = unitsv;

    while ( amount >= 1024 && unitp < unitsv+4 ) {
        amount /= 1024;
        unitp++;
    }

    sprintf(ret, "%.2Lf %s", amount, *unitp );

    return ret;

}

unsigned long long traverse_dir(char *dirname)
{
    DIR *thisdir;
    struct dirent *this_dirent;
    struct stat tmp_stat_struc;
    unsigned long long int size_acc = 0;
    char *dirpath = NULL;

    if (!(thisdir = opendir(dirname))) {
        printf("Unable to open directory %s. Errno gives %d.\n",
                dirname, errno);
        exit(-1);
    }

    while (( this_dirent = readdir(thisdir) )) {
        if (this_dirent->d_name[0] == '.')
            continue;

        dirpath = realloc(dirpath, strlen(dirname)+1
                                  +strlen(this_dirent->d_name)+1);
        strcpy(dirpath, dirname);
        strcat(dirpath, "/");
        strcat(dirpath, this_dirent->d_name);

        if ( stat(dirpath, &tmp_stat_struc) != 0) {
            printf("ERROR: Unable to stat %s. Errno gives %d.\n",
                dirpath, errno);
            exit(-1);
        }
        if ( tmp_stat_struc.st_mode & S_IFDIR ) {
            /* Recurse over directory. */
            size_acc += traverse_dir(dirpath);
        } else {
            /* Sum file size. */
            size_acc += tmp_stat_struc.st_size;
        }
    }

    free(dirpath);
    if (closedir(thisdir) != 0) {
        printf("WARNING: Unable to close directory %s\n", dirname);
        exit(-1);
    }

    return size_acc;
}

--

João Jerónimo

"Computer are composed of software, hardware, and other stuff terminated

in "ware", like firmware, tupperware, (...)" - by JJ.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora