]>
gitweb.michael.orlitzky.com - apply-default-acl.git/blob - src/apply-default-acl.c
2 * @file apply-default-acl.c
4 * @brief The command-line interface.
8 #include <errno.h> /* EINVAL */
9 #include <fcntl.h> /* AT_FOO constants */
10 #include <getopt.h> /* getopt_long() */
11 #include <stdbool.h> /* the "bool" type */
12 #include <stdio.h> /* perror() */
13 #include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
14 #include <unistd.h> /* faccessat() */
18 /* We exit with EXIT_FAILURE for small errors, but we need something
19 * else for big ones. */
24 * @brief Determine whether or not the given path is accessible.
29 * @return true if @c path is accessible to the current effective
30 * user/group, false otherwise.
32 bool path_accessible(const char* path
) {
37 /* Test for access using the effective user and group rather than
39 int flags
= AT_EACCESS
;
41 /* Don't follow symlinks when checking for a path's existence,
42 since we won't follow them to set its ACLs either. */
43 flags
|= AT_SYMLINK_NOFOLLOW
;
45 /* If the path is relative, interpret it relative to the current
46 working directory (just like the access() system call). */
47 if (faccessat(AT_FDCWD
, path
, F_OK
, flags
) == 0) {
57 * @brief Display program usage information.
60 * The program name to use in the output.
63 void usage(const char* program_name
) {
64 if (program_name
== NULL
) {
69 printf("Apply any applicable default ACLs to the given files or "
71 printf("Usage: %s [flags] <target1> [<target2> [ <target3>...]]\n\n",
74 printf(" -h, --help Print this help message\n");
75 printf(" -r, --recursive Act on any given directories recursively\n");
76 printf(" -x, --no-exec-mask Apply execute permissions unconditionally\n");
85 * @brief Call apply_default_acl (possibly recursively) on each
86 * command-line argument.
88 * @return Either @c EXIT_FAILURE or @c EXIT_SUCCESS. If everything
89 * goes as expected, we return @c EXIT_SUCCESS. Otherwise, we return
92 int main(int argc
, char* argv
[]) {
99 bool recursive
= false;
100 bool no_exec_mask
= false;
102 struct option long_options
[] = {
103 /* These options set a flag. */
104 {"help", no_argument
, NULL
, 'h'},
105 {"recursive", no_argument
, NULL
, 'r'},
106 {"no-exec-mask", no_argument
, NULL
, 'x'},
112 while ((opt
= getopt_long(argc
, argv
, "hrx", long_options
, NULL
)) != -1) {
129 int result
= EXIT_SUCCESS
;
132 int reapp_result
= ACL_SUCCESS
;
133 for (arg_index
= optind
; arg_index
< argc
; arg_index
++) {
134 const char* target
= argv
[arg_index
];
136 /* Make sure we can access the given path before we go out of our
137 * way to please it. Doing this check outside of
138 * apply_default_acl() lets us spit out a better error message for
141 if (!path_accessible(target
)) {
143 result
= EXIT_FAILURE
;
147 reapp_result
= apply_default_acl(target
, no_exec_mask
, recursive
);
149 if (result
== EXIT_SUCCESS
&& reapp_result
== ACL_FAILURE
) {
150 /* We don't want to turn an error into a (less-severe) failure. */
151 result
= EXIT_FAILURE
;
153 if (reapp_result
== ACL_ERROR
) {
154 /* Turn both success and failure into an error, if we encounter one. */