getfacl.c revision 75491
154359Sroberto/*- 254359Sroberto * Copyright (c) 1999-2001 Robert N M Watson 354359Sroberto * All rights reserved. 454359Sroberto * 582498Sroberto * Redistribution and use in source and binary forms, with or without 654359Sroberto * modification, are permitted provided that the following conditions 754359Sroberto * are met: 854359Sroberto * 1. Redistributions of source code must retain the above copyright 954359Sroberto * notice, this list of conditions and the following disclaimer. 1054359Sroberto * 2. Redistributions in binary form must reproduce the above copyright 1154359Sroberto * notice, this list of conditions and the following disclaimer in the 1254359Sroberto * documentation and/or other materials provided with the distribution. 1354359Sroberto * 1454359Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1554359Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1654359Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1754359Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1854359Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1954359Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2054359Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2154359Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2254359Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2354359Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2454359Sroberto * SUCH DAMAGE. 2554359Sroberto * 2654359Sroberto * $FreeBSD: head/bin/getfacl/getfacl.c 75491 2001-04-13 19:24:28Z jedgar $ 2754359Sroberto */ 2854359Sroberto/* 2954359Sroberto * getfacl -- POSIX.1e utility to extract ACLs from files and directories 3054359Sroberto * and send the results to stdout 3154359Sroberto */ 3254359Sroberto 3354359Sroberto#include <sys/types.h> 3454359Sroberto#include <sys/param.h> 3554359Sroberto#include <sys/acl.h> 3654359Sroberto#include <sys/stat.h> 3754359Sroberto#include <err.h> 3854359Sroberto#include <errno.h> 3954359Sroberto#include <stdio.h> 4054359Sroberto#include <stdlib.h> 4154359Sroberto#include <unistd.h> 4254359Sroberto 4354359Srobertoint more_than_one = 0; 4454359Sroberto 4554359Srobertostatic void 4654359Srobertousage(void) 4754359Sroberto{ 4854359Sroberto 4954359Sroberto fprintf(stderr, "getfacl [-d] [files ...]\n"); 5054359Sroberto} 5154359Sroberto 5254359Sroberto/* 53290000Sglebius * return an ACL corresponding to the permissions 54290000Sglebius * contained in struct stat 55290000Sglebius */ 56290000Sglebiusstatic acl_t 57290000Sglebiusacl_from_stat(struct stat sb) 58290000Sglebius{ 59290000Sglebius acl_t acl; 60290000Sglebius acl_entry_t entry; 61290000Sglebius acl_permset_t perms; 62290000Sglebius 63290000Sglebius /* create the ACL */ 64290000Sglebius acl = acl_init(3); 65290000Sglebius if (!acl) 66290000Sglebius return NULL; 67290000Sglebius 6854359Sroberto /* First entry: ACL_USER_OBJ */ 6954359Sroberto if (acl_create_entry(&acl, &entry) == -1) 7054359Sroberto return NULL; 71290000Sglebius if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1) 7254359Sroberto return NULL; 7354359Sroberto 74290000Sglebius if (acl_get_permset(entry, &perms) == -1) 75200576Sroberto return NULL; 76200576Sroberto if (acl_clear_perms(perms) == -1) 77200576Sroberto return NULL; 78200576Sroberto 79200576Sroberto /* calculate user mode */ 80132451Sroberto if (sb.st_mode & S_IRUSR) 81132451Sroberto if (acl_add_perm(perms, ACL_READ) == -1) 8254359Sroberto return NULL; 8354359Sroberto if (sb.st_mode & S_IWUSR) 8454359Sroberto if (acl_add_perm(perms, ACL_WRITE) == -1) 8554359Sroberto return NULL; 8654359Sroberto if (sb.st_mode & S_IXUSR) 8754359Sroberto if (acl_add_perm(perms, ACL_EXECUTE) == -1) 8854359Sroberto return NULL; 8954359Sroberto if (acl_set_permset(entry, perms) == -1) 90290000Sglebius return NULL; 91290000Sglebius 92290000Sglebius /* Second entry: ACL_GROUP_OBJ */ 93290000Sglebius if (acl_create_entry(&acl, &entry) == -1) 94290000Sglebius return NULL; 9554359Sroberto if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1) 9654359Sroberto return NULL; 9754359Sroberto 9854359Sroberto if (acl_get_permset(entry, &perms) == -1) 9954359Sroberto return NULL; 10054359Sroberto if (acl_clear_perms(perms) == -1) 10154359Sroberto return NULL; 10254359Sroberto 10354359Sroberto /* calculate group mode */ 10454359Sroberto if (sb.st_mode & S_IRGRP) 10554359Sroberto if (acl_add_perm(perms, ACL_READ) == -1) 10654359Sroberto return NULL; 10754359Sroberto if (sb.st_mode & S_IWGRP) 10854359Sroberto if (acl_add_perm(perms, ACL_WRITE) == -1) 10954359Sroberto return NULL; 110290000Sglebius if (sb.st_mode & S_IXGRP) 11154359Sroberto if (acl_add_perm(perms, ACL_EXECUTE) == -1) 112132451Sroberto return NULL; 113132451Sroberto if (acl_set_permset(entry, perms) == -1) 114132451Sroberto return NULL; 115132451Sroberto 116132451Sroberto /* Third entry: ACL_OTHER */ 117132451Sroberto if (acl_create_entry(&acl, &entry) == -1) 118290000Sglebius return NULL; 119290000Sglebius if (acl_set_tag_type(entry, ACL_OTHER) == -1) 120290000Sglebius return NULL; 121132451Sroberto 122132451Sroberto if (acl_get_permset(entry, &perms) == -1) 123132451Sroberto return NULL; 124132451Sroberto if (acl_clear_perms(perms) == -1) 125290000Sglebius return NULL; 126290000Sglebius 127290000Sglebius /* calculate other mode */ 128290000Sglebius if (sb.st_mode & S_IROTH) 129290000Sglebius if (acl_add_perm(perms, ACL_READ) == -1) 13054359Sroberto return NULL; 131290000Sglebius if (sb.st_mode & S_IWOTH) 132290000Sglebius if (acl_add_perm(perms, ACL_WRITE) == -1) 133290000Sglebius return NULL; 134290000Sglebius if (sb.st_mode & S_IXOTH) 135290000Sglebius if (acl_add_perm(perms, ACL_EXECUTE) == -1) 136290000Sglebius return NULL; 137290000Sglebius if (acl_set_permset(entry, perms) == -1) 138290000Sglebius return NULL; 139290000Sglebius 140290000Sglebius return(acl); 141290000Sglebius} 142290000Sglebius 143290000Sglebiusstatic int 144290000Sglebiusprint_acl(char *path, acl_type_t type) 145290000Sglebius{ 146290000Sglebius struct stat sb; 147290000Sglebius acl_t acl; 148290000Sglebius char *acl_text; 149290000Sglebius int error; 150290000Sglebius 151290000Sglebius error = stat(path, &sb); 152290000Sglebius if (error == -1) { 153290000Sglebius perror(path); 154290000Sglebius return(-1); 155290000Sglebius } 156290000Sglebius 157290000Sglebius if (more_than_one) 158290000Sglebius printf("\n"); 159290000Sglebius else 160290000Sglebius more_than_one++; 161290000Sglebius 162290000Sglebius printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid); 163290000Sglebius 164290000Sglebius acl = acl_get_file(path, type); 165290000Sglebius if (!acl) { 166290000Sglebius if (errno != EOPNOTSUPP) { 167290000Sglebius warn("%s", path); 168290000Sglebius return(-1); 169290000Sglebius } 170290000Sglebius errno = 0; 171290000Sglebius if (type != ACL_TYPE_ACCESS) 172290000Sglebius return(0); 173290000Sglebius acl = acl_from_stat(sb); 174290000Sglebius if (!acl) { 175290000Sglebius perror("acl_from_stat()"); 176290000Sglebius return(-1); 177290000Sglebius } 178290000Sglebius } 179290000Sglebius 180290000Sglebius acl_text = acl_to_text(acl, 0); 181290000Sglebius if (!acl_text) { 182290000Sglebius perror(path); 183290000Sglebius return(-1); 184290000Sglebius } 185290000Sglebius 186290000Sglebius printf("%s", acl_text); 187290000Sglebius 188290000Sglebius acl_free(acl); 189290000Sglebius acl_free(acl_text); 190290000Sglebius 191290000Sglebius return(0); 192290000Sglebius} 193290000Sglebius 194290000Sglebiusstatic int 195290000Sglebiusprint_acl_from_stdin(acl_type_t type) 196290000Sglebius{ 197290000Sglebius char pathname[PATH_MAX]; 198290000Sglebius int carried_error = 0; 199290000Sglebius 200290000Sglebius pathname[sizeof(pathname) - 1] = '\0'; 201290000Sglebius while (fgets(pathname, sizeof(pathname), stdin)) { 202290000Sglebius /* remove the \n */ 203290000Sglebius pathname[strlen(pathname) - 1] = '\0'; 204290000Sglebius if (print_acl(pathname, type) == -1) { 205290000Sglebius carried_error = -1; 206290000Sglebius } 207290000Sglebius } 208290000Sglebius 209290000Sglebius return(carried_error); 210290000Sglebius} 211290000Sglebius 212290000Sglebiusint 213290000Sglebiusmain(int argc, char *argv[]) 214290000Sglebius{ 215290000Sglebius acl_type_t type = ACL_TYPE_ACCESS; 216290000Sglebius int carried_error = 0; 217290000Sglebius int ch, error, i; 218290000Sglebius 219290000Sglebius while ((ch = getopt(argc, argv, "d")) != -1) 220290000Sglebius switch(ch) { 221290000Sglebius case 'd': 222290000Sglebius type = ACL_TYPE_DEFAULT; 223290000Sglebius break; 224290000Sglebius default: 225290000Sglebius usage(); 226290000Sglebius return(-1); 227290000Sglebius } 228290000Sglebius argc -= optind; 229290000Sglebius argv += optind; 230290000Sglebius 231290000Sglebius if (argc == 0) { 232290000Sglebius error = print_acl_from_stdin(type); 233290000Sglebius return(error); 234290000Sglebius } 235290000Sglebius 236290000Sglebius for (i = 0; i < argc; i++) { 237290000Sglebius if (!strcmp(argv[i], "-")) { 238290000Sglebius error = print_acl_from_stdin(type); 239290000Sglebius if (error == -1) 240290000Sglebius carried_error = -1; 241290000Sglebius } else { 242290000Sglebius error = print_acl(argv[i], type); 243290000Sglebius if (error == -1) 244290000Sglebius carried_error = -1; 245290000Sglebius } 246290000Sglebius } 247290000Sglebius 248290000Sglebius return(carried_error); 249290000Sglebius} 250290000Sglebius