1 /*- 2 * Copyright (c) 1999-2001 Robert N M Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 /* 29 * getfacl -- POSIX.1e utility to extract ACLs from files and directories 30 * and send the results to stdout 31 */ 32 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/acl.h> 36 #include <sys/stat.h> 37 #include <err.h> 38 #include <errno.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 44 int more_than_one = 0; 45 46 static void 47 usage(void) 48 { 49 50 fprintf(stderr, "getfacl [-d] [files ...]\n"); 51 } 52 53 /* 54 * return an ACL corresponding to the permissions 55 * contained in struct stat 56 */ 57 static acl_t 58 acl_from_stat(struct stat sb) 59 { 60 acl_t acl; 61 acl_entry_t entry; 62 acl_permset_t perms; 63 64 /* create the ACL */ 65 acl = acl_init(3); 66 if (!acl) 67 return NULL; 68 69 /* First entry: ACL_USER_OBJ */ 70 if (acl_create_entry(&acl, &entry) == -1) 71 return NULL; 72 if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1) 73 return NULL; 74 75 if (acl_get_permset(entry, &perms) == -1) 76 return NULL; 77 if (acl_clear_perms(perms) == -1) 78 return NULL; 79 80 /* calculate user mode */ 81 if (sb.st_mode & S_IRUSR) 82 if (acl_add_perm(perms, ACL_READ) == -1) 83 return NULL; 84 if (sb.st_mode & S_IWUSR) 85 if (acl_add_perm(perms, ACL_WRITE) == -1) 86 return NULL; 87 if (sb.st_mode & S_IXUSR) 88 if (acl_add_perm(perms, ACL_EXECUTE) == -1) 89 return NULL; 90 if (acl_set_permset(entry, perms) == -1) 91 return NULL; 92 93 /* Second entry: ACL_GROUP_OBJ */ 94 if (acl_create_entry(&acl, &entry) == -1) 95 return NULL; 96 if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1) 97 return NULL; 98 99 if (acl_get_permset(entry, &perms) == -1) 100 return NULL; 101 if (acl_clear_perms(perms) == -1) 102 return NULL; 103 104 /* calculate group mode */ 105 if (sb.st_mode & S_IRGRP) 106 if (acl_add_perm(perms, ACL_READ) == -1) 107 return NULL; 108 if (sb.st_mode & S_IWGRP) 109 if (acl_add_perm(perms, ACL_WRITE) == -1) 110 return NULL; 111 if (sb.st_mode & S_IXGRP) 112 if (acl_add_perm(perms, ACL_EXECUTE) == -1) 113 return NULL; 114 if (acl_set_permset(entry, perms) == -1) 115 return NULL; 116 117 /* Third entry: ACL_OTHER */ 118 if (acl_create_entry(&acl, &entry) == -1) 119 return NULL; 120 if (acl_set_tag_type(entry, ACL_OTHER) == -1) 121 return NULL; 122 123 if (acl_get_permset(entry, &perms) == -1) 124 return NULL; 125 if (acl_clear_perms(perms) == -1) 126 return NULL; 127 128 /* calculate other mode */ 129 if (sb.st_mode & S_IROTH) 130 if (acl_add_perm(perms, ACL_READ) == -1) 131 return NULL; 132 if (sb.st_mode & S_IWOTH) 133 if (acl_add_perm(perms, ACL_WRITE) == -1) 134 return NULL; 135 if (sb.st_mode & S_IXOTH) 136 if (acl_add_perm(perms, ACL_EXECUTE) == -1) 137 return NULL; 138 if (acl_set_permset(entry, perms) == -1) 139 return NULL; 140 141 return(acl); 142 } 143 144 static int 145 print_acl(char *path, acl_type_t type) 146 { 147 struct stat sb; 148 acl_t acl; 149 char *acl_text; 150 int error; 151 152 error = stat(path, &sb); 153 if (error == -1) { 154 perror(path); 155 return(-1); 156 } 157 158 if (more_than_one) 159 printf("\n"); 160 else 161 more_than_one++; 162 163 printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid); 164 165 acl = acl_get_file(path, type); 166 if (!acl) { 167 if (errno != EOPNOTSUPP) { 168 warn("%s", path); 169 return(-1); 170 } 171 errno = 0; 172 if (type != ACL_TYPE_ACCESS) 173 return(0); 174 acl = acl_from_stat(sb); 175 if (!acl) { 176 perror("acl_from_stat()"); 177 return(-1); 178 } 179 } 180 181 acl_text = acl_to_text(acl, 0); 182 if (!acl_text) { 183 perror(path); 184 return(-1); 185 } 186 187 printf("%s", acl_text); 188 189 acl_free(acl); 190 acl_free(acl_text); 191 192 return(0); 193 } 194 195 static int 196 print_acl_from_stdin(acl_type_t type) 197 { 198 char pathname[PATH_MAX]; 199 int carried_error = 0; 200 201 pathname[sizeof(pathname) - 1] = '\0'; 202 while (fgets(pathname, (int)sizeof(pathname), stdin)) { 203 /* remove the \n */ 204 pathname[strlen(pathname) - 1] = '\0'; 205 if (print_acl(pathname, type) == -1) { 206 carried_error = -1; 207 } 208 } 209 210 return(carried_error); 211 } 212 213 int 214 main(int argc, char *argv[]) 215 { 216 acl_type_t type = ACL_TYPE_ACCESS; 217 int carried_error = 0; 218 int ch, error, i; 219 220 while ((ch = getopt(argc, argv, "d")) != -1) 221 switch(ch) { 222 case 'd': 223 type = ACL_TYPE_DEFAULT; 224 break; 225 default: 226 usage(); 227 return(-1); 228 } 229 argc -= optind; 230 argv += optind; 231 232 if (argc == 0) { 233 error = print_acl_from_stdin(type); 234 return(error); 235 } 236 237 for (i = 0; i < argc; i++) { 238 if (!strcmp(argv[i], "-")) { 239 error = print_acl_from_stdin(type); 240 if (error == -1) 241 carried_error = -1; 242 } else { 243 error = print_acl(argv[i], type); 244 if (error == -1) 245 carried_error = -1; 246 } 247 } 248 249 return(carried_error); 250 } 251