Hi all,

This is an initial bare bones df(1) implementation.
I'm looking for some feedback, I have not put too much thought
into the code yet (too busy atm).

No manpage yet.

Thanks,
sin
>From a82f46681f68edafec898cd82b2ca64941440c11 Mon Sep 17 00:00:00 2001
From: sin <s...@2f30.org>
Date: Mon, 22 Jul 2013 13:17:32 +0100
Subject: [PATCH] Add df(1)

---
 Makefile |   1 +
 df.c     | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+)
 create mode 100644 df.c

diff --git a/Makefile b/Makefile
index 2e31f33..bb981ce 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,7 @@ SRC = \
        comm.c     \
        cp.c       \
        date.c     \
+       df.c       \
        dirname.c  \
        echo.c     \
        env.c      \
diff --git a/df.c b/df.c
new file mode 100644
index 0000000..86c58f3
--- /dev/null
+++ b/df.c
@@ -0,0 +1,120 @@
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mntent.h>
+#include "util.h"
+
+struct mnt_entry {
+       char *fsname;
+       char *dir;
+       char *type;
+       struct stat stat;
+       struct statvfs statvfs;
+};
+
+struct mnt_tbl {
+       struct mnt_entry *entry;
+       size_t siz;
+};
+
+static void mnt_show(struct mnt_entry *entry);
+
+enum {
+       BLKSIZ = 1024
+};
+
+struct mnt_tbl *
+init_mnt_tbl(void)
+{
+       struct mnt_tbl *mnt_tbl;
+       struct mnt_entry *entry;
+       FILE *fp;
+       struct mntent *me;
+       size_t siz = 0;
+
+       fp = setmntent("/proc/mounts", "r");
+       if (!fp)
+               eprintf("fopen /proc/mounts:");
+
+       mnt_tbl = malloc(sizeof(*mnt_tbl));
+       if (!mnt_tbl)
+               eprintf("malloc:");
+       mnt_tbl->entry = NULL;
+       mnt_tbl->siz = 0;
+
+       while ((me = getmntent(fp))) {
+               mnt_tbl->entry = realloc(mnt_tbl->entry,
+                                        sizeof(*entry) * (siz + 1));
+               if (!mnt_tbl->entry)
+                       eprintf("realloc");
+               entry = &mnt_tbl->entry[siz];
+               entry->fsname = strdup(me->mnt_fsname);
+               entry->dir = strdup(me->mnt_dir);
+               entry->type = strdup(me->mnt_type);
+               stat(me->mnt_dir, &entry->stat);
+               statvfs(me->mnt_dir, &entry->statvfs);
+               siz++;
+       }
+       mnt_tbl->siz = siz;
+
+       endmntent(fp);
+       return mnt_tbl;
+}
+
+int
+main(void)
+{
+       struct mnt_entry *entry;
+       struct mnt_tbl *mnt_tbl;
+       size_t i;
+
+       mnt_tbl = init_mnt_tbl();
+       printf("%-20s %-14s %s %s %s %s\n", "Filesystem", "1K-blocks",
+              "Used", "Available", "Use%", "Mounted on");
+       for (i = 0; i < mnt_tbl->siz; i++) {
+               entry = &mnt_tbl->entry[i];
+               if (!entry->stat.st_dev)
+                       continue;
+               mnt_show(entry);
+       }
+       return 0;
+}
+
+static void
+mnt_show(struct mnt_entry *entry)
+{
+       long long size, used, avail;
+       long long percent = 0, fsbsize;
+
+       if (!entry->statvfs.f_blocks)
+               return;
+
+       if (entry->statvfs.f_bsize)
+               fsbsize = entry->statvfs.f_bsize;
+       else
+               fsbsize = 1;
+
+       size = (fsbsize * entry->statvfs.f_blocks) / BLKSIZ;
+       used = (fsbsize * (entry->statvfs.f_blocks - entry->statvfs.f_bfree));
+       used /= BLKSIZ;
+       avail = fsbsize;
+       if (getuid())
+               avail *= entry->statvfs.f_bavail;
+       else
+               avail *= entry->statvfs.f_bfree;
+       avail /= BLKSIZ;
+
+       if (used + avail) {
+               percent = (used * 100) / (used + avail);
+               if (used * 100 != percent * (used + avail))
+                       percent++;
+       }
+
+       printf("%-20s %9lld ", entry->fsname, size);
+       printf("%9lld ", used);
+       printf("%9lld %3lld%% %s\n",
+              avail, percent, entry->dir);
+}
-- 
1.8.3.3

Reply via email to