/* getfacl.c
- Copyright 2000, 2001, 2002 Red Hat Inc.
-
Written by Corinna Vinschen <vinschen@redhat.com>
This file is part of Cygwin.
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
-#include <sys/types.h>
#include <sys/acl.h>
+#include <acl/libacl.h>
#include <sys/stat.h>
+#include <cygwin/version.h>
#include <string.h>
+#include <errno.h>
-static const char version[] = "$Revision$";
static char *prog_name;
-char *
-permstr (mode_t perm)
-{
- static char pbuf[4];
-
- pbuf[0] = (perm & S_IROTH) ? 'r' : '-';
- pbuf[1] = (perm & S_IWOTH) ? 'w' : '-';
- pbuf[2] = (perm & S_IXOTH) ? 'x' : '-';
- pbuf[3] = '\0';
- return pbuf;
-}
-
const char *
username (uid_t uid)
{
struct passwd *pw;
if ((pw = getpwuid (uid)))
- strcpy (ubuf, pw->pw_name);
+ snprintf (ubuf, sizeof ubuf, "%s", pw->pw_name);
else
- sprintf (ubuf, "%d <unknown>", uid);
+ sprintf (ubuf, "%lu <unknown>", (unsigned long)uid);
return ubuf;
}
struct group *gr;
if ((gr = getgrgid (gid)))
- strcpy (gbuf, gr->gr_name);
+ snprintf (gbuf, sizeof gbuf, "%s", gr->gr_name);
else
- sprintf (gbuf, "%d <unknown>", gid);
+ sprintf (gbuf, "%lu <unknown>", (unsigned long)gid);
return gbuf;
}
-static void
+static void __attribute__ ((__noreturn__))
usage (FILE * stream)
{
fprintf (stream, "Usage: %s [-adn] FILE [FILE2...]\n"
- "Display file and directory access control lists (ACLs).\n"
- "\n"
- " -a, --all display the filename, the owner, the group, and\n"
- " the ACL of the file\n"
- " -d, --dir display the filename, the owner, the group, and\n"
- " the default ACL of the directory, if it exists\n"
- " -h, --help output usage information and exit\n"
- " -n, --noname display user and group IDs instead of names\n"
- " -v, --version output version information and exit\n"
- "\n"
- "When multiple files are specified on the command line, a blank\n"
- "line separates the ACLs for each file.\n", prog_name);
- if (stream == stdout)
+ "\n"
+ "Display file and directory access control lists (ACLs).\n"
+ "\n"
+ " -a, --access display the file access control list only\n"
+ " -d, --default display the default access control list only\n"
+ " -c, --omit-header do not display the comment header\n"
+ " -e, --all-effective print all effective rights\n"
+ " -E, --no-effective print no effective rights\n"
+ " -n, --numeric print numeric user/group identifiers\n"
+ " -V, --version print version and exit\n"
+ " -h, --help this help text\n"
+ "\n"
+ "When multiple files are specified on the command line, a blank\n"
+ "line separates the ACLs for each file.\n", prog_name);
+ if (stream == stdout)
{
fprintf (stream, ""
- "For each argument that is a regular file, special file or\n"
- "directory, getfacl displays the owner, the group, and the ACL.\n"
- "For directories getfacl displays additionally the default ACL.\n"
- "\n"
- "With no options specified, getfacl displays the filename, the\n"
- "owner, the group, and both the ACL and the default ACL, if it\n"
- "exists.\n"
- "\n"
- "The format for ACL output is as follows:\n"
- " # file: filename\n"
- " # owner: name or uid\n"
- " # group: name or uid\n"
- " user::perm\n"
- " user:name or uid:perm\n"
- " group::perm\n"
- " group:name or gid:perm\n"
- " mask:perm\n"
- " other:perm\n"
- " default:user::perm\n"
- " default:user:name or uid:perm\n"
- " default:group::perm\n"
- " default:group:name or gid:perm\n"
- " default:mask:perm\n"
- " default:other:perm\n"
- "\n");
+ "For each argument that is a regular file, special file or\n"
+ "directory, getfacl displays the owner, the group, and the ACL.\n"
+ "For directories getfacl displays additionally the default ACL.\n"
+ "\n"
+ "With no options specified, getfacl displays the filename, the\n"
+ "owner, the group, the setuid (s), setgid (s), and sticky (t)\n"
+ "bits if available, and both the ACL and the default ACL, if it\n"
+ "exists.\n"
+ "\n"
+ "The format for ACL output is as follows:\n"
+ " # file: filename\n"
+ " # owner: name or uid\n"
+ " # group: name or uid\n"
+ " # flags: sst\n"
+ " user::perm\n"
+ " user:name or uid:perm\n"
+ " group::perm\n"
+ " group:name or gid:perm\n"
+ " mask::perm\n"
+ " other::perm\n"
+ " default:user::perm\n"
+ " default:user:name or uid:perm\n"
+ " default:group::perm\n"
+ " default:group:name or gid:perm\n"
+ " default:mask::perm\n"
+ " default:other::perm\n"
+ "\n");
}
+ exit (stream == stdout ? 0 : 1);
}
struct option longopts[] = {
+ {"access", no_argument, NULL, 'a'},
{"all", no_argument, NULL, 'a'},
+ {"omit-header", no_argument, NULL, 'c'},
+ {"all-effective", no_argument, NULL, 'e'},
+ {"no-effective", no_argument, NULL, 'E'},
+ {"default", no_argument, NULL, 'd'},
{"dir", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
- {"noname", no_argument, NULL, 'n'},
- {"version", no_argument, NULL, 'v'},
+ {"noname", no_argument, NULL, 'n'}, /* Backward compat */
+ {"numeric", no_argument, NULL, 'n'},
+ {"version", no_argument, NULL, 'V'},
{0, no_argument, NULL, 0}
};
+const char *opts = "acdeEhnV";
static void
print_version ()
{
- const char *v = strchr (version, ':');
- int len;
- if (!v)
- {
- v = "?";
- len = 1;
- }
- else
- {
- v += 2;
- len = strchr (v, ' ') - v;
- }
- printf ("\
-getfacl (cygwin) %.*s\n\
-ACL Utility\n\
-Copyright (c) 2000, 2001, 2002 Red Hat, Inc.\n\
-Compiled on %s\n\
-", len, v, __DATE__);
+ printf ("getfacl (cygwin) %d.%d.%d\n"
+ "Get POSIX ACL information\n"
+ "Copyright (C) 2000 - %s Cygwin Authors\n"
+ "This is free software; see the source for copying conditions. There is NO\n"
+ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+ CYGWIN_VERSION_DLL_MAJOR / 1000,
+ CYGWIN_VERSION_DLL_MAJOR % 1000,
+ CYGWIN_VERSION_DLL_MINOR,
+ strrchr (__DATE__, ' ') + 1);
}
int
main (int argc, char **argv)
{
- extern int optind;
- int c, i;
+ int c;
+ int ret = 0;
int aopt = 0;
+ int copt = 0;
+ int eopt = 0;
int dopt = 0;
int nopt = 0;
- int first = 1;
+ int options = 0;
+ int istty = isatty (fileno (stdout));
struct stat st;
- aclent_t acls[MAX_ACL_ENTRIES];
- prog_name = strrchr (argv[0], '/');
- if (prog_name == NULL)
- prog_name = strrchr (argv[0], '\\');
- if (prog_name == NULL)
- prog_name = argv[0];
- else
- prog_name++;
+ prog_name = program_invocation_short_name;
- while ((c = getopt_long (argc, argv, "adhnv", longopts, NULL)) != EOF)
+ while ((c = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
switch (c)
{
case 'a':
aopt = 1;
break;
+ case 'c':
+ copt = 1;
+ break;
case 'd':
dopt = 1;
break;
+ case 'e':
+ eopt = 1;
+ break;
+ case 'E':
+ eopt = -1;
+ break;
case 'h':
usage (stdout);
- return 0;
case 'n':
nopt = 1;
break;
- case 'v':
+ case 'V':
print_version ();
return 0;
default:
- usage (stderr);
+ fprintf (stderr, "Try `%s --help' for more information.\n", prog_name);
return 1;
}
if (optind > argc - 1)
+ usage (stderr);
+ if (nopt)
+ options |= TEXT_NUMERIC_IDS;
+ if (eopt > 0)
+ options |= TEXT_ALL_EFFECTIVE;
+ else if (!eopt)
+ options |= TEXT_SOME_EFFECTIVE;
+ if (istty)
+ options |= TEXT_SMART_INDENT;
+ for (; optind < argc; ++optind)
{
- usage (stderr);
- return 1;
- }
- while ((c = optind++) < argc)
- {
- if (stat (argv[c], &st))
- {
- perror (argv[0]);
- continue;
- }
- if (!first)
- putchar ('\n');
- first = 0;
- printf ("# file: %s\n", argv[c]);
- if (nopt)
- {
- printf ("# owner: %d\n", st.st_uid);
- printf ("# group: %d\n", st.st_gid);
- }
- else
- {
- printf ("# owner: %s\n", username (st.st_uid));
- printf ("# group: %s\n", groupname (st.st_gid));
- }
- if ((c = acl (argv[c], GETACL, MAX_ACL_ENTRIES, acls)) < 0)
+ acl_t access_acl = NULL, default_acl = NULL;
+ char *access_txt, *default_txt;
+
+ if (stat (argv[optind], &st)
+ || (!dopt
+ && !(access_acl = acl_get_file (argv[optind], ACL_TYPE_ACCESS)))
+ || (!aopt && S_ISDIR (st.st_mode)
+ && !(default_acl = acl_get_file (argv[optind],
+ ACL_TYPE_DEFAULT))))
+ goto err;
+ if (!copt)
{
- perror (argv[0]);
- continue;
+ printf ("# file: %s\n", argv[optind]);
+ if (nopt)
+ {
+ printf ("# owner: %lu\n", (unsigned long)st.st_uid);
+ printf ("# group: %lu\n", (unsigned long)st.st_gid);
+ }
+ else
+ {
+ printf ("# owner: %s\n", username (st.st_uid));
+ printf ("# group: %s\n", groupname (st.st_gid));
+ }
+ if (st.st_mode & (S_ISUID | S_ISGID | S_ISVTX))
+ printf ("# flags: %c%c%c\n", (st.st_mode & S_ISUID) ? 's' : '-',
+ (st.st_mode & S_ISGID) ? 's' : '-',
+ (st.st_mode & S_ISVTX) ? 't' : '-');
}
- for (i = 0; i < c; ++i)
+ if (access_acl)
{
- if (acls[i].a_type & ACL_DEFAULT)
+ if (!(access_txt = acl_to_any_text (access_acl, NULL, '\n', options)))
{
- if (aopt)
- continue;
- printf ("default:");
+ acl_free (access_acl);
+ goto err;
}
- else if (dopt)
- continue;
- switch (acls[i].a_type & ~ACL_DEFAULT)
+ printf ("%s\n", access_txt);
+ acl_free (access_txt);
+ acl_free (access_acl);
+ }
+ if (default_acl)
+ {
+ if (!(default_txt = acl_to_any_text (default_acl, "default:",
+ '\n', options)))
{
- case USER_OBJ:
- printf ("user::");
- break;
- case USER:
- if (nopt)
- printf ("user:%d:", acls[i].a_id);
- else
- printf ("user:%s:", username (acls[i].a_id));
- break;
- case GROUP_OBJ:
- printf ("group::");
- break;
- case GROUP:
- if (nopt)
- printf ("group:%d:", acls[i].a_id);
- else
- printf ("group:%s:", groupname (acls[i].a_id));
- break;
- case CLASS_OBJ:
- printf ("mask::");
- break;
- case OTHER_OBJ:
- printf ("other::");
- break;
+ acl_free (default_acl);
+ goto err;
}
- printf ("%s\n", permstr (acls[i].a_perm));
+ printf ("%s\n", default_txt);
+ acl_free (default_txt);
+ acl_free (default_acl);
}
+ putchar ('\n');
+ continue;
+ err:
+ fprintf (stderr, "%s: %s: %s\n\n",
+ prog_name, argv[optind], strerror (errno));
+ ret = 2;
}
- return 0;
+ return ret;
}