public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/elfix:master commit in: misc/mangle-paxflags/, misc/install.wrapper.c/, misc/change-interp/, ...
@ 2014-01-18 13:18 Anthony G. Basile
  0 siblings, 0 replies; only message in thread
From: Anthony G. Basile @ 2014-01-18 13:18 UTC (permalink / raw
  To: gentoo-commits

commit:     84846a047baade3488d1538f16d54e4b8a80682b
Author:     Anthony G. Basile <blueness <AT> gentoo <DOT> org>
AuthorDate: Sat Jan 11 15:01:40 2014 +0000
Commit:     Anthony G. Basile <blueness <AT> gentoo <DOT> org>
CommitDate: Sat Jan 11 15:03:13 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/elfix.git;a=commit;h=84846a04

misc/install.wrapper.c: address comments #47 and #48, Bug #465000

---
 misc/change-interp/.gitignore            |   1 +
 misc/elf-manipulate/.gitignore           |   1 +
 misc/install.wrapper.c/Makefile.am       |  16 +++
 misc/install.wrapper.c/autogen.sh        |   6 +
 misc/install.wrapper.c/checkcopyattrs.sh |  32 +++++
 misc/install.wrapper.c/configure.ac      |  30 +++++
 misc/install.wrapper.c/getfatter.sh      |   5 -
 misc/install.wrapper.c/install.wrapper.c | 196 ++++++++++++++++++++-----------
 misc/install.wrapper.c/setfatter.sh      |   6 -
 misc/mangle-paxflags/.gitignore          |   1 +
 10 files changed, 214 insertions(+), 80 deletions(-)

diff --git a/misc/change-interp/.gitignore b/misc/change-interp/.gitignore
new file mode 100644
index 0000000..2460008
--- /dev/null
+++ b/misc/change-interp/.gitignore
@@ -0,0 +1 @@
+!Makefile

diff --git a/misc/elf-manipulate/.gitignore b/misc/elf-manipulate/.gitignore
new file mode 100644
index 0000000..2460008
--- /dev/null
+++ b/misc/elf-manipulate/.gitignore
@@ -0,0 +1 @@
+!Makefile

diff --git a/misc/install.wrapper.c/Makefile.am b/misc/install.wrapper.c/Makefile.am
new file mode 100644
index 0000000..b047805
--- /dev/null
+++ b/misc/install.wrapper.c/Makefile.am
@@ -0,0 +1,16 @@
+CFLAGS=
+noinst_PROGRAMS = install-xattr
+install_xattr_SOURCES = install.wrapper.c
+install_xattr_CFLAGS = -ggdb -Wall -O3
+
+check_SCRIPTS = checkcopyattrs
+TEST = $(check_SCRIPTS)
+
+checkcopyattrs:
+	$(srcdir)/checkcopyattrs.sh
+
+EXTRA_DIST = checkcopyattrs.sh
+CLEANFILES = a b c x y z d/* e/*
+
+clean-local:
+	-rm -rf d e

diff --git a/misc/install.wrapper.c/autogen.sh b/misc/install.wrapper.c/autogen.sh
new file mode 100755
index 0000000..3888ff3
--- /dev/null
+++ b/misc/install.wrapper.c/autogen.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+aclocal && \
+autoheader && \
+autoconf && \
+automake --add-missing --copy

diff --git a/misc/install.wrapper.c/checkcopyattrs.sh b/misc/install.wrapper.c/checkcopyattrs.sh
new file mode 100755
index 0000000..4b3e7f3
--- /dev/null
+++ b/misc/install.wrapper.c/checkcopyattrs.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+set -e
+
+touch a b c
+mkdir -p d e
+setfattr -n user.foo -v "bar" a
+setfattr -n user.pax.flags -v "mr" a
+setfattr -n user.pax.flags -v "p" b
+setfattr -n user.pax.flags -v "r" c
+
+./install-xattr a x
+./install-xattr b y
+./install-xattr c z
+
+[ "$(getfattr --only-values -n user.foo x)" == "bar" ]
+[ "$(getfattr --only-values -n user.pax.flags x)" == "mr" ]
+[ "$(getfattr --only-values -n user.pax.flags y)" == "p" ]
+[ "$(getfattr --only-values -n user.pax.flags z)" == "r" ]
+
+./install-xattr a b c d
+
+[ "$(getfattr --only-values -n user.foo d/a)" == "bar" ]
+[ "$(getfattr --only-values -n user.pax.flags d/a)" == "mr" ]
+[ "$(getfattr --only-values -n user.pax.flags d/b)" == "p" ]
+[ "$(getfattr --only-values -n user.pax.flags d/c)" == "r" ]
+
+./install-xattr -t e a b c
+
+[ "$(getfattr --only-values -n user.foo e/a)" == "bar" ]
+[ "$(getfattr --only-values -n user.pax.flags e/a)" == "mr" ]
+[ "$(getfattr --only-values -n user.pax.flags e/b)" == "p" ]
+[ "$(getfattr --only-values -n user.pax.flags e/c)" == "r" ]

diff --git a/misc/install.wrapper.c/configure.ac b/misc/install.wrapper.c/configure.ac
new file mode 100644
index 0000000..08cc0ca
--- /dev/null
+++ b/misc/install.wrapper.c/configure.ac
@@ -0,0 +1,30 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.69])
+AC_INIT([install-wrapper],[1])
+AC_CONFIG_SRCDIR([install.wrapper.c])
+AC_CONFIG_HEADERS([config.h])
+
+AM_INIT_AUTOMAKE([1.13 foreign])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_CHECK_HEADERS([stdlib.h string.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+AC_CHECK_FUNCS([memset realpath strdup])
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT

diff --git a/misc/install.wrapper.c/getfatter.sh b/misc/install.wrapper.c/getfatter.sh
deleted file mode 100755
index c0eda95..0000000
--- a/misc/install.wrapper.c/getfatter.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-getfattr -d a b c 2>/dev/null
-getfattr -d d/*   2>/dev/null
-getfattr -d x y z 2>/dev/null

diff --git a/misc/install.wrapper.c/install.wrapper.c b/misc/install.wrapper.c/install.wrapper.c
index 2728381..441b7b8 100644
--- a/misc/install.wrapper.c/install.wrapper.c
+++ b/misc/install.wrapper.c/install.wrapper.c
@@ -7,33 +7,83 @@
  * Wrapper for coreutil's install to preserve extended attributes.
  */
 
-#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <err.h>
 #include <fnmatch.h>
 #include <ctype.h>
-#include <libgen.h>
 #include <getopt.h>
-
+#include <libgen.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/xattr.h>
 
+static void *
+xmalloc(size_t size)
+{
+	char *ret = malloc(size);
+	if (ret < 0)
+		err(1, "malloc() failed");
+	return ret;
+}
+
+static char *
+path_join(const char *path, const char *file)
+{
+	size_t len_path = strlen(path);
+	size_t len_file = strlen(file);
+	char *ret = xmalloc(len_path + len_file + 2);
+
+	memcpy(ret, path, len_path);
+	ret[len_path] = '/';
+	memcpy(ret + len_path + 1, file, len_file);
+	ret[len_path + len_file + 1] = '\0';
+
+	return ret;
+}
+
+static ssize_t
+xlistxattr(const char *path, char *list, size_t size)
+{
+	ssize_t ret = listxattr(path, list, size);
+	if (ret < 0)
+		err(1, "listxattr() failed");
+	return ret;
+}
+
+static ssize_t
+xgetxattr(const char *path, char *list, char *value, size_t size)
+{
+	ssize_t ret = getxattr(path, list, value, size);
+	if (ret < 0)
+		err(1, "getxattr() failed");
+	return ret;
+}
+
+static ssize_t
+xsetxattr(const char *path, char *list, char *value , size_t size)
+{
+	ssize_t ret = setxattr(path, list, value, size, 0);
+	if (ret < 0)
+		err(1, "setxattr() failed");
+	return ret;
+}
+
 static void
 copyxattr(const char *source, const char *target)
 {
-	int i, j;
 	char *exclude, *portage_xattr_exclude;  /* strings of excluded xattr names              */
-	int len;                                /* length of the string of excluded xattr names */
+	size_t i, j;                            /* counters to walk through strings             */
+	size_t len;                             /* length of the string of excluded xattr names */
 	ssize_t lsize, xsize;   /* size in bytes of the list of xattrs and the values           */
 	char *lxattr, *value;   /* string of xattr names and the values                         */
 
-	lsize = listxattr(source, 0, 0);
-	lxattr = (char *)malloc(lsize);
-	listxattr(source, lxattr, lsize);
+	lsize = xlistxattr(source, 0, 0);
+	lxattr = xmalloc(lsize);
+	xlistxattr(source, lxattr, lsize);
 
 	portage_xattr_exclude = getenv("PORTAGE_XATTR_EXCLUDE");
 	if (portage_xattr_exclude == NULL)
@@ -43,40 +93,44 @@ copyxattr(const char *source, const char *target)
 
 	len = strlen(exclude);
 
-	/* We convert exclude[] to an array of concatenated null   */
-	/* terminated strings.  lxattr[] is already such an array. */
+	/* We convert exclude[] to an array of concatenated null
+	 * terminated strings.  lxattr[] is already such an array.
+         */
 	for (i = 0; i < len; i++)
 		if (isspace(exclude[i]))
 			exclude[i] = 0;
 
-	i = 0 ;
-	while(1) {
-		while (lxattr[i++] == 0);
+	i = 0;
+	while (1) {
+		while (lxattr[i++] == 0)
+			continue;
 		if (i >= lsize)
 			break;
 
-		j = 0 ;
-		while(1) {
-			while (exclude[j++] == 0);
+		j = 0;
+		while (1) {
+			while (exclude[j++] == 0)
+				continue;
 			if (j >= len)
 				break;
 			if (!fnmatch(&exclude[j-1], &lxattr[i-1], 0))
 				goto skip;
-			while (exclude[j++] != 0);
+			while (exclude[j++] != 0)
+				continue;
 			if (j >= len)
 				break;
 		}
 
-		xsize = getxattr(source, &lxattr[i-1], 0, 0);
-		if (xsize != -1) {
-			value = (char *)malloc(xsize);
+		xsize = xgetxattr(source, &lxattr[i-1], 0, 0);
+		if (xsize > 0) {
+			value = xmalloc(xsize);
 			memset(value, 0, xsize);
-			getxattr(source, &lxattr[i-1], value, xsize);
-			setxattr(target, &lxattr[i-1], value, xsize, 0);
+			xgetxattr(source, &lxattr[i-1], value, xsize);
+			xsetxattr(target, &lxattr[i-1], value, xsize);
 			free(value);
 		}
 
-	skip:
+ skip:
 		while (lxattr[i++] != 0);
 		if (i >= lsize)
 			break;
@@ -84,25 +138,26 @@ copyxattr(const char *source, const char *target)
 
 	free(lxattr);
 	free(exclude);
-
-	return;
 }
 
 
 static char *
-which(char *mydir)
+which(const char *mydir)
 {
 	char *mycandir = realpath(mydir, NULL);  /* canonical value of argv[0]'s dirname */
 	char *path, *env_path = getenv("PATH");  /* full $PATH string                    */
 
 	/* If we don't have $PATH in our environment, then pick a sane path. */
-	if (env_path == NULL)
-		path = strdup("/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin");
+	if (env_path == NULL) {
+		size_t len = confstr(_CS_PATH, 0, 0);
+		path = xmalloc(len);
+		confstr(_CS_PATH, path, len);
+	}
 	else
 		path = strdup(env_path);
 
 	char *dir;       /* one directory in the $PATH string */
-	char *candir ;   /* canonical value of that directory */
+	char *candir;    /* canonical value of that directory */
 	char *file;      /* file name = path + "/install"     */
 	char *savedptr;  /* reentrant context for strtok_r()  */
 
@@ -113,20 +168,21 @@ which(char *mydir)
 	while (dir) {
 		candir = realpath(dir, NULL);
 
-		/* You don't get a canonical path for ~/bin etc., so skip. */
+		/* ignore invalid paths that cannot be cannoicalized */
 		if (!candir)
 			goto skip;
 
-		/* If argv[0]'s canonical dirname == the path's canonical dirname, then we  */
-		/* skip this path otheriwise we get into an infinite self-invocation.       */
-		if ( !fnmatch(mycandir, candir, 0) )
+		/* If argv[0]'s canonical dirname == the path's canonical dirname, then we
+		 * skip this path otheriwise we get into an infinite self-invocation.
+                 */
+		if (!fnmatch(mycandir, candir, 0))
 			goto skip;
 
-		if (asprintf(&file,"%s/%s", candir, "install") == -1)
-			abort();
+		file = path_join(candir, "install");
 
-		/* If the file exists and is either a regular file or sym link, */
-		/* assume we found the system's install. */
+		/* If the file exists and is either a regular file or sym link,
+		 * assume we found the system's install.
+                 */
 		if (stat(file, &s) == 0)
 			if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) {
 				free(candir);
@@ -137,13 +193,12 @@ which(char *mydir)
 
 		free(file);
 
-	skip:
+ skip:
 		free(candir);
 		dir = strtok_r(NULL, ":", &savedptr);
 	}
 
-	/* If we got here, then we didn't find install in the path */
-	abort();
+	err(1, "failed to find system 'install'");
 }
 
 
@@ -151,8 +206,8 @@ which(char *mydir)
 int
 main(int argc, char* argv[], char* envp[])
 {
-	int i ;
-	int status ;                   /* exit status of child "install" process                       */
+	int i;
+	int status;                    /* exit status of child "install" process                       */
 
 	int opts_directory = 0;        /* if -d was given, then all arguments are directories          */
 	int opts_target_directory = 0; /* if -t was given, then we're installing to a target directory */
@@ -166,7 +221,7 @@ main(int argc, char* argv[], char* envp[])
 	struct stat s;                 /* test if a file is a regular file or a directory              */
 
 
-	opterr = 0; /* we skip many legitimate arguments, so silence any warning */
+	opterr = 0; /* we skip many legitimate flags, so silence any warning */
 
 	while (1) {
 		static struct option long_options[] = {
@@ -175,88 +230,91 @@ main(int argc, char* argv[], char* envp[])
 			{                     0,                 0, 0,  0 }
 		};
 
-		int option_index = 0;
-
+		int option_index;
 		int c = getopt_long(argc, argv, "dt:", long_options, &option_index);
  
 		if (c == -1)
 			break;
 
 		switch (c) {
-			case  0 :
+			case 0:
 			case '?':
+				/* We skip the flags we don't care about */
 				break;
 
 			case 'd':
-				opts_directory = 1 ;
+				opts_directory = 1;
 				break;
 
 			case 't':
-				opts_target_directory = 1 ;
-				if (asprintf(&target, "%s", optarg) == -1)
-					abort();
+				opts_target_directory = 1;
+				target = optarg;
 				break;
 
 			default:
-				abort();
+				err(1, "getopt_long() failed");
 		}
 	}
 
 	first = optind;
-	last = argc-1;
+	last = argc - 1;
 
 	switch (fork()) {
 		case -1:
-			abort();
+			err(1, "fork() failed");
 
 		case 0:
 			install = which(dirname(argv[0]));
 			execve(install, argv, envp);
-			free(install);
-			break;
+			/* When the child exists, the kernel will free(install) for us.
+			 * Also, no break since we never return from execve.
+			 */
 
 		default:
 			wait(&status);
 
 			/* If all the targets are directories, do nothing. */
 			if (opts_directory)
-				return EXIT_SUCCESS;
+				return status;
 
 			if (!opts_target_directory) {
-				target = strdup(argv[last]);
+				target = argv[last];
 				if (stat(target, &s) != 0)
 					return EXIT_FAILURE;
-				target_is_directory = s.st_mode & S_IFDIR;
+				target_is_directory = S_ISDIR(s.st_mode);
 			} else {
 				/* target was set above with the -t option */
 				target_is_directory = 1;
 			}
 
 			if (target_is_directory) {
-				/* If -t was passed, then the last argv *is* */
-				/* a file, so we include it for copyxattr(). */
+				/* If -t was passed, then the last argv *is*
+				 * a file, so we include it for copyxattr().
+                                 */
 				if (opts_target_directory)
 					last++;
 
 				for (i = first; i < last; i++) {
-					/* We reproduce install's behavior and skip  */
-					/* all extra directories on the command line */
-					/* that are not the final target directory.  */
-					stat(argv[i], &s);
+					if (stat(argv[i], &s) != 0)
+						return EXIT_FAILURE;
+					/* We reproduce install's behavior and skip
+					 * all extra directories on the command line
+					 * that are not the final target directory.
+                                         */
 					if (S_ISDIR(s.st_mode))
 						continue;
-					if (asprintf(&path, "%s/%s", target, argv[i]) == -1)
-						abort();
 
+					path = path_join(target, argv[i]);
 					copyxattr(argv[i], path);
-
 					free(path);
 				}
 			} else
 				copyxattr(argv[first], target);
 
-			free(target);
+			return status;
 	}
 
-	return EXIT_SUCCESS;
+
+	/* We should never get here */
+	return EXIT_FAILURE;
 }

diff --git a/misc/install.wrapper.c/setfatter.sh b/misc/install.wrapper.c/setfatter.sh
deleted file mode 100755
index 2e9747e..0000000
--- a/misc/install.wrapper.c/setfatter.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-touch a b c
-setfattr -n user.pax.flags -v "mr" a
-setfattr -n user.blah -v "hithere" a
-setfattr -n user.pax.flags -v p b
-setfattr -n user.pax.flags -v r c

diff --git a/misc/mangle-paxflags/.gitignore b/misc/mangle-paxflags/.gitignore
new file mode 100644
index 0000000..2460008
--- /dev/null
+++ b/misc/mangle-paxflags/.gitignore
@@ -0,0 +1 @@
+!Makefile


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2014-01-18 13:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-18 13:18 [gentoo-commits] proj/elfix:master commit in: misc/mangle-paxflags/, misc/install.wrapper.c/, misc/change-interp/, Anthony G. Basile

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox