Viewing: du.c
📄 du.c (Read Only) ⬅ To go back
/* AdrOS du utility — estimate file space usage */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>

static int sflag = 0; /* -s: summary only */

static long du_path(const char* path, int print) {
    struct stat st;
    if (stat(path, &st) < 0) {
        fprintf(stderr, "du: cannot access '%s'\n", path);
        return 0;
    }

    if (!(st.st_mode & 0040000)) {
        long blocks = (st.st_size + 511) / 512;
        if (print && !sflag) printf("%ld\t%s\n", blocks, path);
        return blocks;
    }

    int fd = open(path, O_RDONLY);
    if (fd < 0) return 0;

    long total = 0;
    char buf[2048];
    int rc;
    while ((rc = getdents(fd, buf, sizeof(buf))) > 0) {
        int off = 0;
        while (off < rc) {
            struct dirent* d = (struct dirent*)(buf + off);
            if (d->d_reclen == 0) break;
            if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
                char child[512];
                if (path[strlen(path)-1] == '/')
                    snprintf(child, sizeof(child), "%s%s", path, d->d_name);
                else
                    snprintf(child, sizeof(child), "%s/%s", path, d->d_name);
                total += du_path(child, print);
            }
            off += d->d_reclen;
        }
    }
    close(fd);

    if (print && !sflag) printf("%ld\t%s\n", total, path);
    return total;
}

int main(int argc, char** argv) {
    int argi = 1;
    while (argi < argc && argv[argi][0] == '-') {
        const char* f = argv[argi] + 1;
        while (*f) {
            if (*f == 's') sflag = 1;
            f++;
        }
        argi++;
    }

    if (argi >= argc) {
        long total = du_path(".", 1);
        if (sflag) printf("%ld\t.\n", total);
    } else {
        for (int i = argi; i < argc; i++) {
            long total = du_path(argv[i], 1);
            if (sflag) printf("%ld\t%s\n", total, argv[i]);
        }
    }
    return 0;
}