# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
-AC_INIT([apply-default-acl], [0.0.4], [michael@orlitzky.com])
+AC_INIT([apply-default-acl], [0.0.5], [michael@orlitzky.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/apply-default-acl.c])
AC_CONFIG_FILES([Makefile src/Makefile])
# Checks for programs.
AC_PROG_CC
-# Checks for header files.
-AC_CHECK_HEADERS([limits.h stdlib.h string.h sys/acl.h unistd.h])
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_HEADER_STDBOOL
+# Predefined header checks.
+AC_HEADER_STAT # sys/stat.h
+AC_HEADER_STDBOOL # stdbool.h
+AC_HEADER_STDC # stdlib.h string.h (implied: errno.h limits.h stdio.h)
AC_TYPE_MODE_T
+# Check for header files not covered by the predefined macros above.
+AC_CHECK_HEADERS([ fcntl.h ftw.h getopt.h libgen.h sys/acl.h sys/libacl.h ])
+AC_CHECK_HEADERS([ sys/types.h unistd.h ])
AC_OUTPUT
#define _GNU_SOURCE
#include <errno.h>
+#include <fcntl.h> /* AT_FOO constants */
#include <ftw.h> /* nftw() et al. */
#include <getopt.h>
#include <libgen.h> /* dirname() */
+/**
+ * @brief Determine whether or not the given path is accessible.
+ *
+ * @param path
+ * The path to test.
+ *
+ * @return true if @c path is accessible to the current effective
+ * user/group, false otherwise.
+ */
+bool path_accessible(const char* path) {
+ if (path == NULL) {
+ return false;
+ }
+
+ /* Test for access using the effective user and group rather than
+ the real one. */
+ int flags = AT_EACCESS;
+
+ /* Don't follow symlinks when checking for a path's existence,
+ since we won't follow them to set its ACLs either. */
+ flags |= AT_SYMLINK_NOFOLLOW;
+
+ /* If the path is relative, interpret it relative to the current
+ working directory (just like the access() system call). */
+ int result = faccessat(AT_FDCWD, path, F_OK, flags);
+
+ if (result == 0) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+
/**
* @brief Determine whether or not the given path is a directory.
*
const char* target = argv[arg_index];
bool reapp_result = false;
+ /* Make sure we can access the given path before we go out of our
+ * way to please it. Doing this check outside of
+ * apply_default_acl() lets us spit out a better error message for
+ * typos, too.
+ */
+ if (!path_accessible(target)) {
+ fprintf(stderr, "%s: %s: no such file or directory\n", argv[0], target);
+ result = EXIT_FAILURE;
+ continue;
+ }
+
if (recursive) {
reapp_result = apply_default_acl_recursive(target, no_exec_mask);
}