]> gitweb.michael.orlitzky.com - apply-default-acl.git/blob - src/apply-default-acl.c
src: add prototypes for all functions.
[apply-default-acl.git] / src / apply-default-acl.c
1 /**
2 * @file apply-default-acl.c
3 *
4 * @brief The command-line interface.
5 *
6 */
7
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() */
15
16 #include "libadacl.h"
17
18 /* We exit with EXIT_FAILURE for small errors, but we need something
19 * else for big ones. */
20 #define EXIT_ERROR 2
21
22 /* Prototypes */
23 bool path_accessible(const char* path);
24 void usage(const char* program_name);
25
26
27 /**
28 * @brief Determine whether or not the given path is accessible.
29 *
30 * @param path
31 * The path to test.
32 *
33 * @return true if @c path is accessible to the current effective
34 * user/group, false otherwise.
35 */
36 bool path_accessible(const char* path) {
37 if (path == NULL) {
38 return false;
39 }
40
41 /* Test for access using the effective user and group rather than
42 the real one. */
43 int flags = AT_EACCESS;
44
45 /* Don't follow symlinks when checking for a path's existence,
46 since we won't follow them to set its ACLs either. */
47 flags |= AT_SYMLINK_NOFOLLOW;
48
49 /* If the path is relative, interpret it relative to the current
50 working directory (just like the access() system call). */
51 if (faccessat(AT_FDCWD, path, F_OK, flags) == 0) {
52 return true;
53 }
54 else {
55 return false;
56 }
57 }
58
59
60 /**
61 * @brief Display program usage information.
62 *
63 * @param program_name
64 * The program name to use in the output.
65 *
66 */
67 void usage(const char* program_name) {
68 if (program_name == NULL) {
69 /* ??? */
70 return;
71 }
72
73 printf("Apply any applicable default ACLs to the given files or "
74 "directories.\n\n");
75 printf("Usage: %s [flags] <target1> [<target2> [ <target3>...]]\n\n",
76 program_name);
77 printf("Flags:\n");
78 printf(" -h, --help Print this help message\n");
79 printf(" -r, --recursive Act on any given directories recursively\n");
80
81 return;
82 }
83
84
85
86
87 /**
88 * @brief Call apply_default_acl (possibly recursively) on each
89 * command-line argument.
90 *
91 * @return Either @c EXIT_FAILURE or @c EXIT_SUCCESS. If everything
92 * goes as expected, we return @c EXIT_SUCCESS. Otherwise, we return
93 * @c EXIT_FAILURE.
94 */
95 int main(int argc, char* argv[]) {
96
97 if (argc < 2) {
98 usage(argv[0]);
99 return EXIT_FAILURE;
100 }
101
102 bool recursive = false;
103
104 struct option long_options[] = {
105 /* These options set a flag. */
106 {"help", no_argument, NULL, 'h'},
107 {"recursive", no_argument, NULL, 'r'},
108 {NULL, 0, NULL, 0}
109 };
110
111 int opt = 0;
112
113 while ((opt = getopt_long(argc, argv, "hrx", long_options, NULL)) != -1) {
114 switch (opt) {
115 case 'h':
116 usage(argv[0]);
117 return EXIT_SUCCESS;
118 case 'r':
119 recursive = true;
120 break;
121 default:
122 usage(argv[0]);
123 return EXIT_FAILURE;
124 }
125 }
126
127 int result = EXIT_SUCCESS;
128
129 int arg_index = 1;
130 int reapp_result = ACL_SUCCESS;
131 for (arg_index = optind; arg_index < argc; arg_index++) {
132 const char* target = argv[arg_index];
133
134 /* Make sure we can access the given path before we go out of our
135 * way to please it. Doing this check outside of
136 * apply_default_acl() lets us spit out a better error message for
137 * typos, too.
138 */
139 if (!path_accessible(target)) {
140 perror(target);
141 result = EXIT_FAILURE;
142 continue;
143 }
144
145 reapp_result = apply_default_acl(target, recursive);
146
147 if (result == EXIT_SUCCESS && reapp_result == ACL_FAILURE) {
148 /* We don't want to turn an error into a (less-severe) failure. */
149 result = EXIT_FAILURE;
150 }
151 if (reapp_result == ACL_ERROR) {
152 /* Turn both success and failure into an error, if we encounter one. */
153 result = EXIT_ERROR;
154 }
155 }
156
157 return result;
158 }