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