1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 #ifndef lint
  29 static char sccsid[] = "%Z%%M%  %I%     %E% SMI";
  30 #endif
  31 
  32 /*
  33  * getfacl [-ad] file ...
  34  * This command displays discretionary information for a file or files.
  35  * display format:
  36  *      # file: filename
  37  *      # owner: uid
  38  *      # group: gid
  39  *      user::perm
  40  *      user:uid:perm
  41  *      group::perm
  42  *      group:gid:perm
  43  *      mask:perm
  44  *      other:perm
  45  *      default:user::perm
  46  *      default:user:uid:perm
  47  *      default:group::perm
  48  *      default:group:gid:perm
  49  *      default:mask:perm
  50  *      default:other:perm
  51  */
  52 
  53 #include <stdlib.h>
  54 #include <stdio.h>
  55 #include <pwd.h>
  56 #include <grp.h>
  57 #include <locale.h>
  58 #include <sys/acl.h>
  59 #include <errno.h>
  60 
  61 static char     *pruname(uid_t);
  62 static char     *prgname(gid_t);
  63 static char     *display(int);
  64 static void     usage();
  65 
  66 
  67 int
  68 main(int argc, char *argv[])
  69 {
  70         int             c;
  71         int             aflag = 0;
  72         int             dflag = 0;
  73         int             errflag = 0;
  74         int             savecnt;
  75         int             aclcnt;
  76         int             mask;
  77         aclent_t        *aclp;
  78         aclent_t        *tp;
  79         char            *permp;
  80 
  81         (void) setlocale(LC_ALL, "");
  82         (void) textdomain(TEXT_DOMAIN);
  83 
  84         if (argc < 2)
  85                 usage();
  86 
  87         while ((c = getopt(argc, argv, "ad")) != EOF) {
  88                 switch (c) {
  89                 case 'a':
  90                         aflag++;
  91                         break;
  92                 case 'd':
  93                         dflag++;
  94                         break;
  95                 case '?':
  96                         errflag++;
  97                         break;
  98                 }
  99         }
 100         if (errflag)
 101                 usage();
 102 
 103         if (optind >= argc)
 104                 usage();
 105 
 106         for (; optind < argc; optind++) {
 107                 register char *filep;
 108 
 109                 filep = argv[optind];
 110 
 111                 /* Get ACL info of the files */
 112                 errno = 0;
 113                 if ((aclcnt = acl(filep, GETACLCNT, 0, NULL)) < 0) {
 114                         if (errno == ENOSYS) {
 115                                 (void) fprintf(stderr,
 116                                     gettext("File system doesn't support "
 117                                     "aclent_t style ACL's.\n"
 118                                     "See acl(5) for more information on "
 119                                     "Solaris ACL support.\n"));
 120                                 exit(2);
 121                         }
 122                         perror(filep);
 123                         exit(2);
 124                 }
 125                 if (aclcnt < MIN_ACL_ENTRIES) {
 126                         (void) fprintf(stderr,
 127                             gettext("%d: acl count too small from %s\n"),
 128                             aclcnt, filep);
 129                         exit(2);
 130                 }
 131 
 132                 if ((aclp = (aclent_t *)malloc(sizeof (aclent_t) * aclcnt))
 133                     == NULL) {
 134                         (void) fprintf(stderr,
 135                             gettext("Insufficient memory\n"));
 136                         exit(1);
 137                 }
 138 
 139                 errno = 0;
 140                 if (acl(filep, GETACL, aclcnt, aclp) < 0) {
 141                         perror(filep);
 142                         exit(2);
 143                 }
 144 
 145                 /* display ACL: assume it is sorted. */
 146                 (void) printf("\n# file: %s\n", filep);
 147                 savecnt = aclcnt;
 148                 for (tp = aclp; aclcnt--; tp++) {
 149                         if (tp->a_type == USER_OBJ)
 150                                 (void) printf("# owner: %s\n",
 151                                     pruname(tp->a_id));
 152                         if (tp->a_type == GROUP_OBJ)
 153                                 (void) printf("# group: %s\n",
 154                                     prgname(tp->a_id));
 155                         if (tp->a_type == CLASS_OBJ)
 156                                 mask = tp->a_perm;
 157                 }
 158                 aclcnt = savecnt;
 159                 for (tp = aclp; aclcnt--; tp++) {
 160                         switch (tp->a_type) {
 161                         case USER:
 162                                 if (!dflag) {
 163                                         permp = display(tp->a_perm);
 164                                         (void) printf("user:%s:%s\t\t",
 165                                             pruname(tp->a_id), permp);
 166                                         free(permp);
 167                                         permp = display(tp->a_perm & mask);
 168                                         (void) printf(
 169                                             "#effective:%s\n", permp);
 170                                         free(permp);
 171                                 }
 172                                 break;
 173                         case USER_OBJ:
 174                                 if (!dflag) {
 175                                         /* no need to display uid */
 176                                         permp = display(tp->a_perm);
 177                                         (void) printf("user::%s\n", permp);
 178                                         free(permp);
 179                                 }
 180                                 break;
 181                         case GROUP:
 182                                 if (!dflag) {
 183                                         permp = display(tp->a_perm);
 184                                         (void) printf("group:%s:%s\t\t",
 185                                             prgname(tp->a_id), permp);
 186                                         free(permp);
 187                                         permp = display(tp->a_perm & mask);
 188                                         (void) printf(
 189                                             "#effective:%s\n", permp);
 190                                         free(permp);
 191                                 }
 192                                 break;
 193                         case GROUP_OBJ:
 194                                 if (!dflag) {
 195                                         permp = display(tp->a_perm);
 196                                         (void) printf("group::%s\t\t", permp);
 197                                         free(permp);
 198                                         permp = display(tp->a_perm & mask);
 199                                         (void) printf(
 200                                             "#effective:%s\n", permp);
 201                                         free(permp);
 202                                 }
 203                                 break;
 204                         case CLASS_OBJ:
 205                                 if (!dflag) {
 206                                         permp = display(tp->a_perm);
 207                                         (void) printf("mask:%s\n", permp);
 208                                         free(permp);
 209                                 }
 210                                 break;
 211                         case OTHER_OBJ:
 212                                 if (!dflag) {
 213                                         permp = display(tp->a_perm);
 214                                         (void) printf("other:%s\n", permp);
 215                                         free(permp);
 216                                 }
 217                                 break;
 218                         case DEF_USER:
 219                                 if (!aflag) {
 220                                         permp = display(tp->a_perm);
 221                                         (void) printf("default:user:%s:%s\n",
 222                                             pruname(tp->a_id), permp);
 223                                         free(permp);
 224                                 }
 225                                 break;
 226                         case DEF_USER_OBJ:
 227                                 if (!aflag) {
 228                                         permp = display(tp->a_perm);
 229                                         (void) printf("default:user::%s\n",
 230                                             permp);
 231                                         free(permp);
 232                                 }
 233                                 break;
 234                         case DEF_GROUP:
 235                                 if (!aflag) {
 236                                         permp = display(tp->a_perm);
 237                                         (void) printf("default:group:%s:%s\n",
 238                                             prgname(tp->a_id), permp);
 239                                         free(permp);
 240                                 }
 241                                 break;
 242                         case DEF_GROUP_OBJ:
 243                                 if (!aflag) {
 244                                         permp = display(tp->a_perm);
 245                                         (void) printf("default:group::%s\n",
 246                                             permp);
 247                                         free(permp);
 248                                 }
 249                                 break;
 250                         case DEF_CLASS_OBJ:
 251                                 if (!aflag) {
 252                                         permp = display(tp->a_perm);
 253                                         (void) printf("default:mask:%s\n",
 254                                             permp);
 255                                         free(permp);
 256                                 }
 257                                 break;
 258                         case DEF_OTHER_OBJ:
 259                                 if (!aflag) {
 260                                         permp = display(tp->a_perm);
 261                                         (void) printf("default:other:%s\n",
 262                                             permp);
 263                                         free(permp);
 264                                 }
 265                                 break;
 266                         default:
 267                                 (void) fprintf(stderr,
 268                                     gettext("unrecognized entry\n"));
 269                                 break;
 270                         }
 271                 }
 272                 free(aclp);
 273         }
 274         return (0);
 275 }
 276 
 277 static char *
 278 display(int perm)
 279 {
 280         char    *buf;
 281 
 282         buf = malloc(4);
 283         if (buf == NULL) {
 284                 (void) fprintf(stderr, gettext("Insufficient memory\n"));
 285                 exit(1);
 286         }
 287 
 288         if (perm & 4)
 289                 buf[0] = 'r';
 290         else
 291                 buf[0] = '-';
 292         if (perm & 2)
 293                 buf[1] = 'w';
 294         else
 295                 buf[1] = '-';
 296         if (perm & 1)
 297                 buf[2] = 'x';
 298         else
 299                 buf[2] = '-';
 300         buf[3] = '\0';
 301         return (buf);
 302 }
 303 
 304 static char *
 305 pruname(uid_t uid)
 306 {
 307         struct passwd   *passwdp;
 308         static char     uidp[10];       /* big enough */
 309 
 310         passwdp = getpwuid(uid);
 311         if (passwdp == (struct passwd *)NULL) {
 312                 /* could not get passwd information: display uid instead */
 313                 (void) sprintf(uidp, "%u", uid);
 314                 return (uidp);
 315         } else
 316                 return (passwdp->pw_name);
 317 }
 318 
 319 static char *
 320 prgname(gid_t gid)
 321 {
 322         struct group    *groupp;
 323         static char     gidp[10];       /* big enough */
 324 
 325         groupp = getgrgid(gid);
 326         if (groupp == (struct group *)NULL) {
 327                 /* could not get group information: display gid instead */
 328                 (void) sprintf(gidp, "%u", gid);
 329                 return (gidp);
 330         } else
 331                 return (groupp->gr_name);
 332 }
 333 
 334 static void
 335 usage()
 336 {
 337         (void) fprintf(stderr,
 338             gettext("usage: getfacl [-ad] file ... \n"));
 339         exit(1);
 340 }