[pacman-dev] [RFC] [PATCH] Implement a du --apparent-size equivalent

Alastair Hughes hobbitalastair at gmail.com
Sat Jun 11 07:53:37 UTC 2016


From: Alastair Hughes <hobbitalastair at yandex.com>

Add a pkgsize binary which mimics the behaviour of GNU du --apparent-size -skl.
Fixes FS#47943.

Signed-off-by: Alastair Hughes <hobbitalastair at gmail.com>
---
I haven't done much C programming before - I'd appreciate any feedback you have.
At the moment, this patch creates a new pkgsize binary as an extra utility, and
installs with the other utilities.
I think that it would be better if it installed it to a libexec dir, but I'm
not entirely sure how to do that without making a mess.
---
 configure.ac          |  5 ---
 scripts/Makefile.am   |  2 --
 scripts/makepkg.sh.in |  2 +-
 src/util/.gitignore   |  2 ++
 src/util/Makefile.am  |  4 ++-
 src/util/pkgsize.c    | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 94 insertions(+), 9 deletions(-)
 create mode 100644 src/util/pkgsize.c

diff --git a/configure.ac b/configure.ac
index dd4ac04..ee5f7ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -332,7 +332,6 @@ OWNERCMD="stat -c '%u:%g'"
 MODECMD="stat -c '%a'"
 SIZECMD="stat -c %s"
 SEDINPLACE="sed --follow-symlinks -i"
-DUFLAGS="-sk --apparent-size"
 STRIP_BINARIES="--strip-all"
 STRIP_SHARED="--strip-unneeded"
 STRIP_STATIC="--strip-debug"
@@ -343,7 +342,6 @@ case "${host_os}" in
 		MODECMD="stat -f '%Lp'"
 		SIZECMD="stat -f %z"
 		SEDINPLACE="sed -i \"\""
-		DUFLAGS="-sk"
 		;;
 	darwin*)
 		host_os_darwin=yes
@@ -352,7 +350,6 @@ case "${host_os}" in
 		MODECMD="/usr/bin/stat -f '%Lp'"
 		SIZECMD="/usr/bin/stat -f %z"
 		SEDINPLACE="/usr/bin/sed -i ''"
-		DUFLAGS="-sk"
 		STRIP_BINARIES=""
 		STRIP_SHARED="-S"
 		STRIP_STATIC="-S"
@@ -360,13 +357,11 @@ case "${host_os}" in
 esac
 
 AM_CONDITIONAL([DARWIN], test "x$host_os_darwin" = "xyes")
-AC_PATH_PROGS([DUPATH], [du], [du], [/usr/bin$PATH_SEPARATOR/bin] )
 AC_SUBST(INODECMD)
 AC_SUBST(OWNERCMD)
 AC_SUBST(MODECMD)
 AC_SUBST(SIZECMD)
 AC_SUBST(SEDINPLACE)
-AC_SUBST(DUFLAGS)
 AC_SUBST(STRIP_BINARIES)
 AC_SUBST(STRIP_SHARED)
 AC_SUBST(STRIP_STATIC)
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index e4f9fb1..ea14e73 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -138,8 +138,6 @@ edit = sed \
 	-e "s|@MODECMD[@]|$(MODECMD)|g" \
 	-e 's|@SIZECMD[@]|$(SIZECMD)|g' \
 	-e 's|@SEDINPLACE[@]|$(SEDINPLACE)|g' \
-	-e 's|@DUFLAGS[@]|$(DUFLAGS)|g' \
-	-e 's|@DUPATH[@]|$(DUPATH)|g' \
 	-e 's|@SCRIPTNAME[@]|$@|g' \
 	-e 's|@configure_input[@]|Generated from $@.sh.in; do not edit by hand.|g'
 
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 7b2ce51..249c878 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -605,7 +605,7 @@ write_pkginfo() {
 		local packager="Unknown Packager"
 	fi
 
-	local size="$(@DUPATH@ @DUFLAGS@)"
+	local size="$(pkgsize .)"
 	size="$(( ${size%%[^0-9]*} * 1024 ))"
 
 	merge_arch_attrs
diff --git a/src/util/.gitignore b/src/util/.gitignore
index 202fb75..7dbefe8 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -6,6 +6,8 @@ pacsort
 pacsort.exe
 pactree
 pactree.exe
+pkgsize
+pkgsize.exe
 testpkg
 testpkg.exe
 vercmp
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 6a89ea6..84dfce9 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -4,7 +4,7 @@ dbpath    = ${localstatedir}/lib/pacman/
 gpgdir    = ${sysconfdir}/pacman.d/gnupg/
 cachedir  = ${localstatedir}/cache/pacman/pkg/
 
-bin_PROGRAMS = vercmp testpkg cleanupdelta pacsort pactree
+bin_PROGRAMS = vercmp testpkg cleanupdelta pacsort pactree pkgsize
 
 AM_CPPFLAGS = \
 	-imacros $(top_builddir)/config.h \
@@ -27,6 +27,8 @@ pacsort_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
 pactree_SOURCES = pactree.c util-common.c
 pactree_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
 
+pkgsize_SOURCES = pkgsize.c
+
 testpkg_SOURCES = testpkg.c
 testpkg_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
 
diff --git a/src/util/pkgsize.c b/src/util/pkgsize.c
new file mode 100644
index 0000000..5e1b3fc
--- /dev/null
+++ b/src/util/pkgsize.c
@@ -0,0 +1,88 @@
+/*
+ *  pkgsize.c - a du --apparent-size equivalent for systems without GNU du
+ *
+ *  Copyright (c) 2016 Pacman Development Team <pacman-dev at archlinux.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This is equivalent to "du -skl --apparent-size".
+ * Unforunately, there appears to be no easy way of ignoring hard links, hence
+ * the additional '-l' argument.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+
+static long size(char *path)
+{
+	long total_size, subsize;
+	DIR *dir;
+	struct dirent *entry;
+	struct stat buf;
+
+	if(lstat(path, &buf) != 0) { return -1; }
+
+	if(S_ISLNK(buf.st_mode) || S_ISREG(buf.st_mode)) {
+		return buf.st_size;
+	} else if(S_ISDIR(buf.st_mode)) {
+		total_size = buf.st_size;
+		dir = opendir(path);
+		if(dir == NULL || chdir(path) != 0) { return -1; }
+		while(entry = readdir(dir)) {
+			if(strcmp(entry->d_name, "..") == 0 || strcmp(entry->d_name, ".") == 0) {
+				continue;
+			}
+			subsize = size(entry->d_name);
+			if(subsize == -1) {
+				closedir(dir);
+				return -1;
+			}
+			total_size += subsize;
+		}
+
+		closedir(dir);
+		if(chdir("../") != 0) { return -1; }
+		return total_size;
+	}
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	long total_size;
+
+	if(argc != 2) {
+		printf("Invalid argument count %d!\n", argc - 1);
+		exit(EXIT_FAILURE);
+	}
+
+	total_size = size(argv[1]);
+	if(total_size == -1) {
+		perror("");
+		exit(EXIT_FAILURE);
+	}
+
+	/* Use KB, rounded up - should be equivalent to the du -k flag */
+	printf("%ld %s\n", (total_size / 1024) + (total_size % 1024 != 0), argv[1]);
+
+	exit(EXIT_SUCCESS);
+}
+
+/* vim: set noet: */
-- 
2.8.3


More information about the pacman-dev mailing list