예제 #1
0
파일: xattrs.c 프로젝트: mfragkoulis/tar
/* convert unix permissions into an ACL ... needed due to "default" ACLs */
static acl_t
perms2acl (int perms)
{
  char val[] = "user::---,group::---,other::---";
  /*            0123456789 123456789 123456789 123456789 */

  /* user */
  if (perms & 0400)
    val[6] = 'r';
  if (perms & 0200)
    val[7] = 'w';
  if (perms & 0100)
    val[8] = 'x';

  /* group */
  if (perms & 0040)
    val[17] = 'r';
  if (perms & 0020)
    val[18] = 'w';
  if (perms & 0010)
    val[19] = 'x';

  /* other */
  if (perms & 0004)
    val[28] = 'r';
  if (perms & 0002)
    val[29] = 'w';
  if (perms & 0001)
    val[30] = 'x';

  return acl_from_text (val);
}
예제 #2
0
파일: acl.c 프로젝트: grke/burp
static int do_set_acl(struct asfd *asfd, const char *path,
	const char *acltext, int acltype, struct cntr *cntr)
{
	acl_t acl;
	int ret=-1;
	if(!(acl=acl_from_text(acltext)))
	{
		logp("acl_from_text error on %s (%s): %s\n",
			path, acltext, strerror(errno));
		logw(asfd, cntr, "acl_from_text error on %s (%s): %s\n",
			path, acltext, strerror(errno));
		goto end;
	}
	if(acl_valid(acl))
	{
		logp("acl_valid error on %s: %s", path, strerror(errno));
		logw(asfd, cntr, "acl_valid error on %s: %s\n",
			path, strerror(errno));
		goto end;
	}
	if(acl_set_file(path, acltype, acl))
	{
		logp("acl set error on %s: %s", path, strerror(errno));
		logw(asfd, cntr, "acl set error on %s: %s\n",
			path, strerror(errno));
		goto end;
	}
	ret=0;
end:
	if(acl) acl_free(acl);
	return ret;
}
예제 #3
0
파일: file.c 프로젝트: rodrigc/bz-vimage
/*
 * read acl text from a file and return the corresponding acl
 */
acl_t
get_acl_from_file(const char *filename)
{
	FILE *file;
	char buf[BUFSIZ];

	if (filename == NULL)
		err(1, "(null) filename in get_acl_from_file()");

	bzero(&buf, sizeof(buf));

	if (strcmp(filename, "-") == 0) {
		if (have_stdin != 0)
			err(1, "cannot specify more than one stdin");
		file = stdin;
		have_stdin = 1;
	} else {
		file = fopen(filename, "r");
		if (file == NULL)
			err(1, "fopen() %s failed", filename);
	}

	fread(buf, sizeof(buf), (size_t)1, file);
	if (ferror(file) != 0) {
		fclose(file);
		err(1, "error reading from %s", filename);
	} else if (feof(file) == 0) {
		fclose(file);
		errx(1, "line too long in %s", filename);
	}

	fclose(file);

	return (acl_from_text(buf));
}
예제 #4
0
파일: acl1.c 프로젝트: 1587/ltp
/*  acl with user entries used for the test */
acl_t test_acl_user_create(void)
{
	char acl_text[] =
	    "u::rwx,u:user1:rwx,u:user2:rw-,u:user3:r--,u:user4:r-x,u:user5:---,g::r-x,o::r-x,m::rwx";
	acl_t acl;
	acl = acl_from_text(acl_text);
	return acl;
}
예제 #5
0
파일: acl1.c 프로젝트: 1587/ltp
acl_t test_acl_grp_create(void)
{
	char acl_text[] =
	    "u::rwx,g:grp1:rwx,g:grp2:rw-,g:grp3:r--,g:grp4:r-x,g:grp5:---,g::---,o::r-x,m::rwx";
	acl_t acl;
	acl = acl_from_text(acl_text);
	return acl;
}
예제 #6
0
파일: winacl.c 프로젝트: Arcko/freenas
/* create directory and file ACL's */
static void
make_acls(struct windows_acl_info *w)
{
	char *ptr;
	char buf[8192];
	acl_t acl;

	/* set defaults if none specified */
	if (w->flags & WA_RESET) {
		if (w->owner_entry == NULL)
			setarg(&w->owner_entry, WA_ENTRY_OWNER);
		if (w->group_entry == NULL)
			setarg(&w->group_entry, WA_ENTRY_GROUP);
		if (w->everyone_entry == NULL)
			setarg(&w->everyone_entry, WA_ENTRY_EVERYONE);
	}

	/* create an acl string */
	ptr = &buf[0];
	if (w->owner_entry != NULL)
		copyarg(&ptr, w->owner_entry);
	if (w->group_entry != NULL)
		copyarg(&ptr, w->group_entry);
	if (w->everyone_entry != NULL)
		copyarg(&ptr, w->everyone_entry);

	/* turn our acl string into an acl */
	if ((acl = acl_from_text(buf)) == NULL)
		err(EX_OSERR, "acl_from_text() failed");

	/* create a directory acl */
	if (w->flags & WA_DIRECTORIES) {
		if ((w->dacl = acl_dup(acl)) == NULL)
			err(EX_OSERR, "acl_dup() failed");
	}

	/* create a file acl */
	if (w->flags & WA_FILES) {
		if ((w->facl = acl_dup(acl)) == NULL)
			err(EX_OSERR, "acl_dup() failed");
		remove_inherit_flags(&w->facl);
	}

	acl_free(acl);
}
예제 #7
0
static acl_t
acl_from_mode(mode_t mode)
{
	char acl_text[] = "u::---,g::---,o::---";
	acl_t acl;

	if (mode & S_IRUSR) acl_text[ 3] = 'r';
	if (mode & S_IWUSR) acl_text[ 4] = 'w';
	if (mode & S_IXUSR) acl_text[ 5] = 'x';
	if (mode & S_IRGRP) acl_text[10] = 'r';
	if (mode & S_IWGRP) acl_text[11] = 'w';
	if (mode & S_IXGRP) acl_text[12] = 'x';
	if (mode & S_IROTH) acl_text[17] = 'r';
	if (mode & S_IWOTH) acl_text[18] = 'w';
	if (mode & S_IXOTH) acl_text[19] = 'x';

	return acl_from_text (acl_text);
}
예제 #8
0
파일: xattrs.c 프로젝트: mfragkoulis/tar
/* Set the "system.posix_acl_access/system.posix_acl_default" extended
   attribute.  Called only when acls_option > 0. */
static void
xattrs__acls_set (struct tar_stat_info const *st,
                  char const *file_name, int type,
                  char *ptr, size_t len, bool def)
{
  acl_t acl;

  if (ptr)
    {
      /* assert (strlen (ptr) == len); */
      ptr = fixup_extra_acl_fields (ptr);
      acl = acl_from_text (ptr);
    }
  else if (def)
    {
      /* No "default" IEEE 1003.1e ACL set for directory.  At this moment,
         FILE_NAME may already have inherited default acls from parent
         directory;  clean them up. */
      if (acl_delete_def_file_at (chdir_fd, file_name))
        WARNOPT (WARN_XATTR_WRITE,
                (0, errno,
                 _("acl_delete_def_file_at: Cannot drop default POSIX ACLs "
                   "for file '%s'"),
                 file_name));
      return;
    }
  else
    acl = perms2acl (st->stat.st_mode);

  if (!acl)
    {
      call_arg_warn ("acl_from_text", file_name);
      return;
    }

  if (acl_set_file_at (chdir_fd, file_name, type, acl) == -1)
    /* warn even if filesystem does not support acls */
    WARNOPT (WARN_XATTR_WRITE,
	     (0, errno,
	      _ ("acl_set_file_at: Cannot set POSIX ACLs for file '%s'"),
	      file_name));

  acl_free (acl);
}
예제 #9
0
/* Set the ACL of the given file to a given list in long text form.
   @param path          Path to the file
   @param text          The input text (0 terminated, ACL long text form)
   @param flag          Bitfield for control purposes
                        bit0=  set default ACL rather than access ACL
                        bit5=  in case of symbolic link: manipulate link target
                        bit6= tolerate inappropriate presence or absence of
                              directory default ACL
   @return              > 0 ok
                         0 no suitable ACL manipulation adapter available
                        -1  failure of system ACL service (see errno)
                        -2 attempt to manipulate ACL of a symbolic link
                           without bit5 resp. with no suitable link target
*/
int aaip_set_acl_text(char *path, char *text, int flag)
{

#ifdef Libisofs_with_aaip_acL

 int ret;
 acl_t acl= NULL;
 struct stat stbuf;

 if(flag & 32)
   ret= stat(path, &stbuf);
 else
   ret= lstat(path, &stbuf);
 if(ret == -1)
   return(-1);
 if((stbuf.st_mode & S_IFMT) == S_IFLNK)
   return(-2);

 acl= acl_from_text(text);
 if(acl == NULL) {
   ret= -1; goto ex;
 }

 /* Note: no ACL_TYPE_DEFAULT in FreeBSD */
 if(flag & 1)
   {ret= 0; goto ex;}

 ret= acl_set_file(path, ACL_TYPE_ACCESS, acl);

 if(ret == -1)
   goto ex;
 ret= 1;
ex:
 if(acl != NULL)
   acl_free(acl);
 return(ret);

#else /* Libisofs_with_aaip_acL */

 return(0);

#endif /* ! Libisofs_with_aaip_acL */

}
예제 #10
0
static acl_t
acl_from_mode (mode_t mode)
{
#  if HAVE_ACL_FREE_TEXT /* Tru64 */
  char acl_text[] = "u::---,g::---,o::---,";
#  else /* FreeBSD, IRIX */
  char acl_text[] = "u::---,g::---,o::---";
#  endif

  if (mode & S_IRUSR) acl_text[ 3] = 'r';
  if (mode & S_IWUSR) acl_text[ 4] = 'w';
  if (mode & S_IXUSR) acl_text[ 5] = 'x';
  if (mode & S_IRGRP) acl_text[10] = 'r';
  if (mode & S_IWGRP) acl_text[11] = 'w';
  if (mode & S_IXGRP) acl_text[12] = 'x';
  if (mode & S_IROTH) acl_text[17] = 'r';
  if (mode & S_IWOTH) acl_text[18] = 'w';
  if (mode & S_IXOTH) acl_text[19] = 'x';

  return acl_from_text (acl_text);
}
예제 #11
0
파일: set-acl.c 프로젝트: Distrotech/acl
int main(int argc, char *argv[])
{
	acl_t acl;
	int n, ret = 0;

	progname = basename(argv[0]);

	if (argc < 3) {
		printf("%s -- set access control list of files\n"
			"Usage: %s acl file ...\n",
			progname, progname);
		return 1;
	}

	acl = acl_from_text(argv[1]);
	if (!acl) {
		fprintf(stderr, "%s: `%s': %s\n",
			progname, argv[1], strerror(errno));
		return 1;
	}
	if (acl_valid(acl) != 0) {
		fprintf(stderr, "%s: `%s': invalid/incomplete acl\n",
			progname, argv[1]);
		acl_free(acl);
		return 1;
	}

	for (n = 2; n < argc; n++) {
		if (acl_set_file(argv[n], ACL_TYPE_ACCESS, acl) != 0) {
			fprintf(stderr, "%s: setting acl of %s: %s\n",
				progname, argv[n], strerror(errno));
			ret = 1;
		}
	}

	acl_free(acl);

	return ret;
}
예제 #12
0
파일: acl.c 프로젝트: vanElden/burp
static int do_set_acl(struct asfd *asfd, const char *path,
	const char *acltext, size_t alen,
	int acltype, struct cntr *cntr)
{
	acl_t acl;
	int ret=-1;
	if(!(acl=acl_from_text(acltext)))
	{
		logp("acl_from_text error on %s (%s): %s\n",
			path, acltext, strerror(errno));
		logw(asfd, cntr, "acl_from_text error on %s (%s): %s\n",
			path, acltext, strerror(errno));
		goto end;
	}
//#ifndef HAVE_FREEBSD_OS // Bacula says that acl_valid fails on valid input
			// on freebsd. It works OK for me on FreeBSD 8.2.
	if(acl_valid(acl))
	{
		logp("acl_valid error on %s: %s", path, strerror(errno));
		logw(asfd, cntr, "acl_valid error on %s: %s\n",
			path, strerror(errno));
		goto end;
	}
//#endif
	if(acl_set_file(path, acltype, acl))
	{
		logp("acl set error on %s: %s", path, strerror(errno));
		logw(asfd, cntr, "acl set error on %s: %s\n",
			path, strerror(errno));
		goto end;
	}
	ret=0;
end:
	if(acl) acl_free(acl);
	return ret; 
}
예제 #13
0
static unsigned int
call_syscall(struct syscall_desc *scall, char *argv[])
{
	struct stat64 sb;
	long long flags;
	unsigned int i;
	char *endp;
	int name, rval;
	union {
		char *str;
		long long num;
	} args[MAX_ARGS];
#ifdef HAS_FREEBSD_ACL
	int entry_id = ACL_FIRST_ENTRY;
	acl_t acl, newacl;
	acl_entry_t entry, newentry;
#endif

	/*
	 * Verify correctness of the arguments.
	 */
	for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
		if (scall->sd_args[i] == TYPE_NONE) {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
				break;
			fprintf(stderr, "too many arguments [%s]\n", argv[i]);
			exit(1);
		} else {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
				if (scall->sd_args[i] & TYPE_OPTIONAL)
					break;
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
				if (strcmp(argv[i], "NULL") == 0)
					args[i].str = NULL;
				else if (strcmp(argv[i], "DEADCODE") == 0)
					args[i].str = (void *)0xdeadc0de;
				else
					args[i].str = argv[i];
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_NUMBER) {
				args[i].num = strtoll(argv[i], &endp, 0);
				if (*endp != '\0' &&
				    !isspace((unsigned char)*endp)) {
					fprintf(stderr,
					    "invalid argument %u, number expected [%s]\n",
					    i, endp);
					exit(1);
				}
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_DESCRIPTOR) {
				if (strcmp(argv[i], "AT_FDCWD") == 0) {
					args[i].num = AT_FDCWD;
				} else if (strcmp(argv[i], "BADFD") == 0) {
					/* In case AT_FDCWD is -1 on some systems... */
					if (AT_FDCWD == -1)
						args[i].num = -2;
					else
						args[i].num = -1;
				} else {
					int pos;

					pos = strtoll(argv[i], &endp, 0);
					if (*endp != '\0' &&
					    !isspace((unsigned char)*endp)) {
						fprintf(stderr,
						    "invalid argument %u, number expected [%s]\n",
						    i, endp);
						exit(1);
					}
					args[i].num = descriptor_get(pos);
				}
			}
		}
	}
	/*
	 * Call the given syscall.
	 */
#define	NUM(n)	(args[(n)].num)
#define	STR(n)	(args[(n)].str)
	switch (scall->sd_action) {
	case ACTION_OPEN:
		flags = str2flags(open_flags, STR(1));
		if (flags & O_CREAT) {
			if (i == 2) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags, (mode_t)NUM(2));
		} else {
			if (i == 3) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_OPENAT:
		flags = str2flags(open_flags, STR(2));
		if (flags & O_CREAT) {
			if (i == 3) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags,
			    (mode_t)NUM(3));
		} else {
			if (i == 4) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_CREATE:
		rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
		if (rval >= 0)
			close(rval);
		break;
	case ACTION_UNLINK:
		rval = unlink(STR(0));
		break;
	case ACTION_UNLINKAT:
		rval = unlinkat(NUM(0), STR(1),
		    (int)str2flags(unlinkat_flags, STR(2)));
		break;
	case ACTION_MKDIR:
		rval = mkdir(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKDIRAT:
		rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_RMDIR:
		rval = rmdir(STR(0));
		break;
	case ACTION_LINK:
		rval = link(STR(0), STR(1));
		break;
	case ACTION_LINKAT:
		rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
		    (int)str2flags(linkat_flags, STR(4)));
		break;
	case ACTION_SYMLINK:
		rval = symlink(STR(0), STR(1));
		break;
	case ACTION_SYMLINKAT:
		rval = symlinkat(STR(0), NUM(1), STR(2));
		break;
	case ACTION_RENAME:
		rval = rename(STR(0), STR(1));
		break;
	case ACTION_RENAMEAT:
		rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
		break;
	case ACTION_MKFIFO:
		rval = mkfifo(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKFIFOAT:
		rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_MKNOD:
	case ACTION_MKNODAT:
	    {
		mode_t ntype;
		dev_t dev;
		int fa;

		switch (scall->sd_action) {
		case ACTION_MKNOD:
			fa = 0;
			break;
		case ACTION_MKNODAT:
			fa = 1;
			break;
		default:
			abort();
		}

		dev = makedev(NUM(fa + 3), NUM(fa + 4));
		if (strcmp(STR(fa + 1), "c") == 0)	/* character device */
			ntype = S_IFCHR;
		else if (strcmp(STR(fa + 1), "b") == 0)	/* block device */
			ntype = S_IFBLK;
		else if (strcmp(STR(fa + 1), "f") == 0)	/* fifo special */
			ntype = S_IFIFO;
		else if (strcmp(STR(fa + 1), "d") == 0)	/* directory */
			ntype = S_IFDIR;
		else if (strcmp(STR(fa + 1), "o") == 0)	/* regular file */
			ntype = S_IFREG;
		else {
			fprintf(stderr, "wrong argument 1\n");
			exit(1);
		}
		switch (scall->sd_action) {
		case ACTION_MKNOD:
			rval = mknod(STR(0), ntype | NUM(2), dev);
			break;
		case ACTION_MKNODAT:
			rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
			break;
		default:
			abort();
		}
		break;
	    }
	case ACTION_BIND:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_BINDAT
	case ACTION_BINDAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CONNECT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_CONNECTAT
	case ACTION_CONNECTAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CHMOD:
		rval = chmod(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_FCHMOD:
		rval = fchmod(NUM(0), (mode_t)NUM(1));
		break;
#ifdef HAS_LCHMOD
	case ACTION_LCHMOD:
		rval = lchmod(STR(0), (mode_t)NUM(1));
		break;
#endif
	case ACTION_FCHMODAT:
		rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
		    str2flags(fchmodat_flags, STR(3)));
		break;
	case ACTION_CHOWN:
		rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWN:
		rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_LCHOWN:
		rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWNAT:
		rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
		    (int)str2flags(fchownat_flags, STR(4)));
		break;
#ifdef HAS_CHFLAGS
	case ACTION_CHFLAGS:
		rval = chflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_FCHFLAGS
	case ACTION_FCHFLAGS:
		rval = fchflags(NUM(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_CHFLAGSAT
	case ACTION_CHFLAGSAT:
		rval = chflagsat(NUM(0), STR(1),
		    (unsigned long)str2flags(chflags_flags, STR(2)),
		    (int)str2flags(chflagsat_flags, STR(3)));
		break;
#endif
#ifdef HAS_LCHFLAGS
	case ACTION_LCHFLAGS:
		rval = lchflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
	case ACTION_TRUNCATE:
		rval = truncate64(STR(0), NUM(1));
		break;
	case ACTION_FTRUNCATE:
		rval = ftruncate64(NUM(0), NUM(1));
		break;
	case ACTION_STAT:
		rval = stat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_FSTAT:
		rval = fstat64(NUM(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_LSTAT:
		rval = lstat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_FSTATAT:
		rval = fstatat(NUM(0), STR(1), &sb,
		    (int)str2flags(fstatat_flags, STR(2)));
		if (rval == 0) {
			show_stats(&sb, STR(3));
			return (i);
		}
		break;
	case ACTION_PATHCONF:
	case ACTION_FPATHCONF:
	case ACTION_LPATHCONF:
	    {
		long lrval;

		name = str2name(pathconf_names, STR(1));
		if (name == -1) {
			fprintf(stderr, "unknown name %s", STR(1));
			exit(1);
		}
		errno = 0;
		switch (scall->sd_action) {
		case ACTION_PATHCONF:
			lrval = pathconf(STR(0), name);
			break;
		case ACTION_FPATHCONF:
			lrval = fpathconf(NUM(0), name);
			break;
		case ACTION_LPATHCONF:
			lrval = lpathconf(STR(0), name);
			break;
		default:
			abort();
		}
		if (lrval == -1 && errno == 0) {
			printf("unlimited\n");
			return (i);
		} else if (lrval >= 0) {
			printf("%ld\n", lrval);
			return (i);
		}
		rval = -1;
		break;
	    }
#ifdef HAS_FREEBSD_ACL
	case ACTION_PREPENDACL:
		rval = -1;

		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			break;

		newacl = acl_from_text(STR(1));
		if (acl == NULL)
			break;

		while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
			entry_id = ACL_NEXT_ENTRY;

			if (acl_create_entry_np(&acl, &entry, 0))
				break;

			if (acl_copy_entry(entry, newentry))
				break;
		}

		rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
		break;
	case ACTION_READACL:
		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			rval = -1;
		else
			rval = 0;
		break;
#endif
	case ACTION_WRITE:
		rval = write(NUM(0), STR(1), strlen(STR(1)));
		break;
	default:
		fprintf(stderr, "unsupported syscall\n");
		exit(1);
	}
#undef STR
#undef NUM
	if (rval < 0) {
		const char *serrno;

		serrno = err2str(errno);
		fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
		printf("%s\n", serrno);
		exit(1);
	}
	printf("0\n");
	return (i);
}
예제 #14
0
int
main(int argc, char *argv[])
{
	char *file;
	int switch_flag = 0;            /* ensure only one switch is used */
	int args_required = 2;	
	int failed = 0;			/* exit status */
	int c;				/* For use by getopt(3) */
	int dflag = 0;			/* a Default ACL is desired */
	int bflag = 0;			/* a both ACLs are desired */
	int Rflag = 0;			/* set to true to remove an acl */
	int Dflag = 0;			/* set to true to remove default acls */
	int Bflag = 0;			/* set to true to remove both acls */
	int lflag = 0;			/* set to true to list acls */
	acl_t acl = NULL;		/* File ACL */
	acl_t dacl = NULL;		/* Directory Default ACL */

	program = basename(argv[0]);

	setlocale(LC_CTYPE, "");
	setlocale(LC_MESSAGES, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	/* parse arguments */
	while ((c = getopt(argc, argv, "bdlRDBr")) != -1) {
		if (switch_flag) 
			usage();
		switch_flag = 1;

		switch (c) {
			case 'b':
				bflag = 1;
				args_required = 3;
				break;
			case 'd':
				dflag = 1;
				args_required = 2;
				break;
			case 'R':
				Rflag = 1;
				args_required = 1;
				break;
			case 'D':
				Dflag = 1;
				args_required = 1;
				break;
			case 'B':
				Bflag = 1;
				args_required = 1;
				break;
			case 'l':
				lflag = 1;
				args_required = 1;
				break;
			case 'r':
				rflag = 1;
				args_required = 1;
				break;
			default:
				usage();
				break;
		}
	}

	/* if not enough arguments quit */
	if ((argc - optind) < args_required)
		usage();

        /* list the acls */
	if (lflag) {
		for (; optind < argc; optind++) {	
			file = argv[optind];
			if (!list_acl(file))
				failed++;
		}
		return(failed);
	}

	/* remove the acls */
	if (Rflag || Dflag || Bflag) {
		for (; optind < argc; optind++) {	
			file = argv[optind];
			if (!Dflag &&
			    (acl_delete_file(file, ACL_TYPE_ACCESS) == -1)) {
				fprintf(stderr, _(
			"%s: error removing access acl on \"%s\": %s\n"),
					program, file, strerror(errno));
				failed++;
			}
			if (!Rflag &&
			    (acl_delete_file(file, ACL_TYPE_DEFAULT) == -1)) {
				fprintf(stderr, _(
			"%s: error removing default acl on \"%s\": %s\n"),
					program, file, strerror(errno));
				failed++;
			}
		}
		return(failed);
	}

	/* file access acl */
	if (! dflag) { 
		acl = acl_from_text(argv[optind]);
		failed = acl_check(acl, &c);
		if (failed < 0) {
			fprintf(stderr, "%s: %s - %s\n",
				program, argv[optind], strerror(errno));
			return 1;
		}
		else if (failed > 0) {
			fprintf(stderr, _(
				"%s: access ACL '%s': %s at entry %d\n"),
				program, argv[optind], acl_error(failed), c);
			return 1;
		}
		optind++;
	}


	/* directory default acl */
	if (bflag || dflag) {
		dacl = acl_from_text(argv[optind]);
		failed = acl_check(dacl, &c);
		if (failed < 0) {
			fprintf(stderr, "%s: %s - %s\n",
				program, argv[optind], strerror(errno));
			return 1;
		}
		else if (failed > 0) {
			fprintf(stderr, _(
				"%s: access ACL '%s': %s at entry %d\n"),
				program, argv[optind], acl_error(failed), c);
			return 1;
		}
		optind++;
	}

	/* place acls on files */
	for (; optind < argc; optind++)
		failed += set_acl(acl, dacl, argv[optind]);

	if (acl)
		acl_free(acl);
	if (dacl)
		acl_free(dacl);

	return(failed);
}
예제 #15
0
파일: fstest.c 프로젝트: VRciF/springy
int do_setfacl(const char *path, const char *options, const char *textacl)
{
	int r;
	int type;
	acl_t acl;
	int dob;
	int dok;
	int dom;
	struct stat st;
	char textmode[30];

	r = 0;
	dob = strchr(options,'b') != (char*)NULL;
	dok = strchr(options,'k') != (char*)NULL;
	dom = strchr(options,'m') != (char*)NULL;
	if ((dom && !textacl)
	    || (!dom && (textacl || (!dok && !dob) || strchr(options,'d')))) {
		errno = EBADRQC; /* "bad request" */
		r = -1;
	} else {
		if (dob || dok) {
			r = acl_delete_def_file(path);
		}
		if (dob && !r) {
			if (!stat(path,&st)) {
				sprintf(textmode,"u::%c%c%c,g::%c%c%c,o::%c%c%c",
					(st.st_mode & 0400 ? 'r' : '-'),
					(st.st_mode & 0200 ? 'w' : '-'),
					(st.st_mode & 0100 ? 'x' : '-'),
					(st.st_mode & 0040 ? 'r' : '-'),
					(st.st_mode & 0020 ? 'w' : '-'),
					(st.st_mode & 0010 ? 'x' : '-'),
					(st.st_mode & 004 ? 'r' : '-'),
					(st.st_mode & 002 ? 'w' : '-'),
					(st.st_mode & 001 ? 'x' : '-'));
				acl = acl_from_text(textmode);
				if (acl) {
					r = acl_set_file(path,ACL_TYPE_ACCESS,acl);
					acl_free(acl);
				} else
					r = -1;
			} else
				r = -1;
		}
		if (!r && dom) {
			if (strchr(options,'d'))
				type = ACL_TYPE_DEFAULT;
			else
				type = ACL_TYPE_ACCESS;
			acl = acl_from_text(textacl);
			if (acl) {
				r = acl_set_file(path,type,acl);
				acl_free(acl);
			} else
				r = -1;
		}
	}
	if (r)
		r = -errno;
	return (r);
}
예제 #16
0
int
set_acl (char const *name, int desc, mode_t mode)
{
#if USE_ACL && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
  /* POSIX 1003.1e draft 17 (abandoned) specific version.  */

  /* We must also have have_acl_from_text and acl_delete_def_file.
     (acl_delete_def_file could be emulated with acl_init followed
      by acl_set_file, but acl_set_file with an empty acl is
      unspecified.)  */

# ifndef HAVE_ACL_FROM_TEXT
#  error Must have acl_from_text (see POSIX 1003.1e draft 17).
# endif
# ifndef HAVE_ACL_DELETE_DEF_FILE
#  error Must have acl_delete_def_file (see POSIX 1003.1e draft 17).
# endif

  acl_t acl;
  int ret;

  if (HAVE_ACL_FROM_MODE)
    {
      acl = acl_from_mode (mode);
      if (!acl)
	{
	  error (0, errno, "%s", quote (name));
	  return -1;
	}
    }
  else
    {
      char acl_text[] = "u::---,g::---,o::---";

      if (mode & S_IRUSR) acl_text[ 3] = 'r';
      if (mode & S_IWUSR) acl_text[ 4] = 'w';
      if (mode & S_IXUSR) acl_text[ 5] = 'x';
      if (mode & S_IRGRP) acl_text[10] = 'r';
      if (mode & S_IWGRP) acl_text[11] = 'w';
      if (mode & S_IXGRP) acl_text[12] = 'x';
      if (mode & S_IROTH) acl_text[17] = 'r';
      if (mode & S_IWOTH) acl_text[18] = 'w';
      if (mode & S_IXOTH) acl_text[19] = 'x';

      acl = acl_from_text (acl_text);
      if (!acl)
	{
	  error (0, errno, "%s", quote (name));
	  return -1;
	}
    }
  if (HAVE_ACL_SET_FD && desc != -1)
    ret = acl_set_fd (desc, acl);
  else
    ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
  if (ret != 0)
    {
      int saved_errno = errno;
      acl_free (acl);

      if (ACL_NOT_WELL_SUPPORTED (errno))
	{
	  if (chmod_or_fchmod (name, desc, mode) != 0)
	    saved_errno = errno;
	  else
	    return 0;
	}
      error (0, saved_errno, _("setting permissions for %s"), quote (name));
      return -1;
    }
  else
    acl_free (acl);

  if (S_ISDIR (mode) && acl_delete_def_file (name))
    {
      error (0, errno, _("setting permissions for %s"), quote (name));
      return -1;
    }

  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
    {
      /* We did not call chmod so far, so the special bits have not yet
         been set.  */

      if (chmod_or_fchmod (name, desc, mode))
	{
	  error (0, errno, _("preserving permissions for %s"), quote (name));
	  return -1;
	}
    }
  return 0;
#else
   int ret = chmod_or_fchmod (name, desc, mode);
   if (ret)
     error (0, errno, _("setting permissions for %s"), quote (name));
   return ret;
#endif
}
예제 #17
0
compare_acls(acl_t acl, struct archive_test_acl_t *myacls, int n)
#endif
{
	int *marker;
	int matched;
	int i;
#if HAVE_SUN_ACL
	int e;
	aclent_t *acl_entry;
#else
	int entry_id = ACL_FIRST_ENTRY;
	acl_entry_t acl_entry;
#endif

	/* Count ACL entries in myacls array and allocate an indirect array. */
	marker = malloc(sizeof(marker[0]) * n);
	if (marker == NULL)
		return;
	for (i = 0; i < n; i++)
		marker[i] = i;

	/*
	 * Iterate over acls in system acl object, try to match each
	 * one with an item in the myacls array.
	 */
#if HAVE_SUN_ACL
	for(e = 0; e < acl->acl_cnt; e++) {
		acl_entry = &((aclent_t *)acl->acl_aclp)[e];
#else
	while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
		/* After the first time... */
		entry_id = ACL_NEXT_ENTRY;
#endif

		/* Search for a matching entry (tag and qualifier) */
		for (i = 0, matched = 0; i < n && !matched; i++) {
			if (acl_match(acl_entry, &myacls[marker[i]])) {
				/* We found a match; remove it. */
				marker[i] = marker[n - 1];
				n--;
				matched = 1;
			}
		}

		/* TODO: Print out more details in this case. */
		failure("ACL entry on file that shouldn't be there");
		assert(matched == 1);
	}

	/* Dump entries in the myacls array that weren't in the system acl. */
	for (i = 0; i < n; ++i) {
		failure(" ACL entry missing from file: "
		    "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
		    myacls[marker[i]].type, myacls[marker[i]].permset,
		    myacls[marker[i]].tag, myacls[marker[i]].qual,
		    myacls[marker[i]].name);
		assert(0); /* Record this as a failure. */
	}
	free(marker);
}

#endif


/*
 * Verify ACL restore-to-disk.  This test is Platform-specific.
 */

DEFINE_TEST(test_acl_platform_posix1e_restore)
{
#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
	skipping("POSIX.1e ACLs are not supported on this platform");
#else	/* HAVE_SUN_ACL || HAVE_POSIX_ACL */
	struct stat st;
	struct archive *a;
	struct archive_entry *ae;
	int n, fd;
	char *func;
#if HAVE_SUN_ACL
	acl_t *acl, *acl2;
#else
	acl_t acl;
#endif

	/*
	 * First, do a quick manual set/read of ACL data to
	 * verify that the local filesystem does support ACLs.
	 * If it doesn't, we'll simply skip the remaining tests.
	 */
#if HAVE_SUN_ACL
	n = acl_fromtext("user::rwx,user:1:rw-,group::rwx,group:15:r-x,other:rwx,mask:rwx", &acl);
	failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
	assertEqualInt(0, n);
#else
	acl = acl_from_text("u::rwx,u:1:rw,g::rwx,g:15:rx,o::rwx,m::rwx");
	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
	assert((void *)acl != NULL);
#endif

	/* Create a test file and try ACL on it. */
	fd = open("pretest", O_WRONLY | O_CREAT | O_EXCL, 0777);
	failure("Could not create test file?!");
	if (!assert(fd >= 0)) {
		acl_free(acl);
		return;
	}

#if HAVE_SUN_ACL
	n = facl_get(fd, 0, &acl2);
	if (n != 0) {
		close(fd);
		acl_free(acl);
	}
	if (errno == ENOSYS) {
		skipping("POSIX.1e ACLs are not supported on this filesystem");
		return;
	}
	failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
	assertEqualInt(0, n);

	if (acl2->acl_type != ACLENT_T) {
		acl_free(acl2);
		skipping("POSIX.1e ACLs are not supported on this filesystem");
		return;
	}
	acl_free(acl2);

	func = "facl_set()";
	n = facl_set(fd, acl);
#else
	func = "acl_set_fd()";
	n = acl_set_fd(fd, acl);
#endif
	acl_free(acl);
	if (n != 0) {
#if HAVE_SUN_ACL
		if (errno == ENOSYS)
#else
		if (errno == EOPNOTSUPP || errno == EINVAL)
#endif
		{
			close(fd);
			skipping("POSIX.1e ACLs are not supported on this filesystem");
			return;
		}
	}
	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
	assertEqualInt(0, n);

#if HAVE_SUN_ACL

#endif
	close(fd);

	/* Create a write-to-disk object. */
	assert(NULL != (a = archive_write_disk_new()));
	archive_write_disk_set_options(a,
	    ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);

	/* Populate an archive entry with some metadata, including ACL info */
	ae = archive_entry_new();
	assert(ae != NULL);
	archive_entry_set_pathname(ae, "test0");
	archive_entry_set_mtime(ae, 123456, 7890);
	archive_entry_set_size(ae, 0);
	assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
	archive_entry_free(ae);

	/* Close the archive. */
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));

	/* Verify the data on disk. */
	assertEqualInt(0, stat("test0", &st));
	assertEqualInt(st.st_mtime, 123456);
#if HAVE_SUN_ACL
	n = acl_get("test0", 0, &acl);
	failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
	assertEqualInt(0, n);
#else
	acl = acl_get_file("test0", ACL_TYPE_ACCESS);
	failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
	assert(acl != (acl_t)NULL);
#endif
	compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0]));
	acl_free(acl);
#endif	/* HAVE_SUN_ACL || HAVE_POSIX_ACL */
}

/*
 * Verify ACL read-from-disk.  This test is Platform-specific.
 */
DEFINE_TEST(test_acl_platform_posix1e_read)
{
#if !HAVE_SUN_ACL && !HAVE_POSIX_ACL
	skipping("POSIX.1e ACLs are not supported on this platform");
#else
	struct archive *a;
	struct archive_entry *ae;
	int n, fd, flags, dflags;
	char *func, *acl_text;
	const char *acl1_text, *acl2_text, *acl3_text;
#if HAVE_SUN_ACL
	acl_t *acl, *acl1, *acl2, *acl3;
#else
	acl_t acl1, acl2, acl3;
#endif

	/*
	 * Manually construct a directory and two files with
	 * different ACLs.  This also serves to verify that ACLs
	 * are supported on the local filesystem.
	 */

	/* Create a test file f1 with acl1 */
#if HAVE_SUN_ACL
	acl1_text = "user::rwx,"
	    "group::rwx,"
	    "other:rwx,"
	    "user:1:rw-,"
	    "group:15:r-x,"
	    "mask:rwx";
	n = acl_fromtext(acl1_text, &acl1);
	failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
	assertEqualInt(0, n);
#else
	acl1_text = "user::rwx\n"
	    "group::rwx\n"
	    "other::rwx\n"
	    "user:1:rw-\n"
	    "group:15:r-x\n"
	    "mask::rwx";
	acl1 = acl_from_text(acl1_text);
	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
	assert((void *)acl1 != NULL);
#endif
	fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
	failure("Could not create test file?!");
	if (!assert(fd >= 0)) {
		acl_free(acl1);
		return;
	}
#if HAVE_SUN_ACL
	/* Check if Solaris filesystem supports POSIX.1e ACLs */
	n = facl_get(fd, 0, &acl);
	if (n != 0)
		close(fd);
	if (n != 0 && errno == ENOSYS) {
		acl_free(acl1);
		skipping("POSIX.1e ACLs are not supported on this filesystem");
		return;
	}
	failure("facl_get(): errno = %d (%s)", errno, strerror(errno));
	assertEqualInt(0, n);

	if (acl->acl_type != ACLENT_T) {
		acl_free(acl);
		acl_free(acl1);
		close(fd);
		skipping("POSIX.1e ACLs are not supported on this filesystem");
		return;
	}

	func = "facl_set()";
	n = facl_set(fd, acl1);
#else
	func = "acl_set_fd()";
	n = acl_set_fd(fd, acl1);
#endif
	acl_free(acl1);

	if (n != 0) {
#if HAVE_SUN_ACL
		if (errno == ENOSYS)
#else
		if (errno == EOPNOTSUPP || errno == EINVAL)
#endif
		{
			close(fd);
			skipping("POSIX.1e ACLs are not supported on this filesystem");
			return;
		}
	}
	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
	assertEqualInt(0, n);

	close(fd);

	assertMakeDir("d", 0700);

	/*
	 * Create file d/f1 with acl2
	 *
	 * This differs from acl1 in the u:1: and g:15: permissions.
	 *
	 * This file deliberately has the same name but a different ACL.
	 * Github Issue #777 explains how libarchive's directory traversal
	 * did not always correctly enter directories before attempting
	 * to read ACLs, resulting in reading the ACL from a like-named
	 * file in the wrong directory.
	 */
#if HAVE_SUN_ACL
	acl2_text = "user::rwx,"
	    "group::rwx,"
	    "other:---,"
	    "user:1:r--,"
	    "group:15:r--,"
	    "mask:rwx";
	n = acl_fromtext(acl2_text, &acl2);
	failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
	assertEqualInt(0, n);
#else
	acl2_text = "user::rwx\n"
	    "group::rwx\n"
	    "other::---\n"
	    "user:1:r--\n"
	    "group:15:r--\n"
	    "mask::rwx";
	acl2 = acl_from_text(acl2_text);
	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
	assert((void *)acl2 != NULL);
#endif
	fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
	failure("Could not create test file?!");
	if (!assert(fd >= 0)) {
		acl_free(acl2);
		return;
	}
#if HAVE_SUN_ACL
	func = "facl_set()";
	n = facl_set(fd, acl2);
#else
	func = "acl_set_fd()";
	n = acl_set_fd(fd, acl2);
#endif
	acl_free(acl2);
	if (n != 0)
		close(fd);
	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
	assertEqualInt(0, n);
	close(fd);

	/* Create nested directory d2 with default ACLs */
	assertMakeDir("d/d2", 0755);

#if HAVE_SUN_ACL
	acl3_text = "user::rwx,"
	    "group::r-x,"
	    "other:r-x,"
	    "user:2:r--,"
	    "group:16:-w-,"
	    "mask:rwx,"
	    "default:user::rwx,"
	    "default:user:1:r--,"
	    "default:group::r-x,"
	    "default:group:15:r--,"
	    "default:mask:rwx,"
	    "default:other:r-x";
	n = acl_fromtext(acl3_text, &acl3);
	failure("acl_fromtext(): errno = %d (%s)", errno, strerror(errno));
	assertEqualInt(0, n);
#else
	acl3_text = "user::rwx\n"
	    "user:1:r--\n"
	    "group::r-x\n"
	    "group:15:r--\n"
	    "mask::rwx\n"
	    "other::r-x";
	acl3 = acl_from_text(acl3_text);
	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
	assert((void *)acl3 != NULL);
#endif

#if HAVE_SUN_ACL
	func = "acl_set()";
	n = acl_set("d/d2", acl3);
#else
	func = "acl_set_file()";
	n = acl_set_file("d/d2", ACL_TYPE_DEFAULT, acl3);
#endif
	acl_free(acl3);

	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
	assertEqualInt(0, n);

	/* Create a read-from-disk object. */
	assert(NULL != (a = archive_read_disk_new()));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
	assert(NULL != (ae = archive_entry_new()));

#if HAVE_SUN_ACL
	flags = ARCHIVE_ENTRY_ACL_TYPE_POSIX1E
	    | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
	    | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS;
	dflags = flags;
#else
	flags = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
	dflags = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
#endif

	/* Walk the dir until we see both of the files */
	while (ARCHIVE_OK == archive_read_next_header2(a, ae)) {
		archive_read_disk_descend(a);
		if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
			acl_text = archive_entry_acl_to_text(ae, NULL, flags);
			assertEqualString(acl_text, acl1_text);
			free(acl_text);
		} else if (strcmp(archive_entry_pathname(ae), "./d/f1") == 0) {
			acl_text = archive_entry_acl_to_text(ae, NULL, flags);
			assertEqualString(acl_text, acl2_text);
			free(acl_text);
		} else if (strcmp(archive_entry_pathname(ae), "./d/d2") == 0) {
			acl_text = archive_entry_acl_to_text(ae, NULL, dflags);
			assertEqualString(acl_text, acl3_text);
			free(acl_text);
		}
	}

	archive_entry_free(ae);
	assertEqualInt(ARCHIVE_OK, archive_free(a));
#endif
}
예제 #18
0
int
qset_acl (char const *name, int desc, mode_t mode)
{
#if USE_ACL
# if HAVE_ACL_GET_FILE
  /* POSIX 1003.1e draft 17 (abandoned) specific version.  */
  /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
#  if !HAVE_ACL_TYPE_EXTENDED
  /* Linux, FreeBSD, IRIX, Tru64 */

  /* We must also have acl_from_text and acl_delete_def_file.
     (acl_delete_def_file could be emulated with acl_init followed
      by acl_set_file, but acl_set_file with an empty acl is
      unspecified.)  */

#   ifndef HAVE_ACL_FROM_TEXT
#    error Must have acl_from_text (see POSIX 1003.1e draft 17).
#   endif
#   ifndef HAVE_ACL_DELETE_DEF_FILE
#    error Must have acl_delete_def_file (see POSIX 1003.1e draft 17).
#   endif

  acl_t acl;
  int ret;

  if (HAVE_ACL_FROM_MODE) /* Linux */
    {
      acl = acl_from_mode (mode);
      if (!acl)
        return -1;
    }
  else /* FreeBSD, IRIX, Tru64 */
    {
      /* If we were to create the ACL using the functions acl_init(),
         acl_create_entry(), acl_set_tag_type(), acl_set_qualifier(),
         acl_get_permset(), acl_clear_perm[s](), acl_add_perm(), we
         would need to create a qualifier.  I don't know how to do this.
         So create it using acl_from_text().  */

#   if HAVE_ACL_FREE_TEXT /* Tru64 */
      char acl_text[] = "u::---,g::---,o::---,";
#   else /* FreeBSD, IRIX */
      char acl_text[] = "u::---,g::---,o::---";
#   endif

      if (mode & S_IRUSR) acl_text[ 3] = 'r';
      if (mode & S_IWUSR) acl_text[ 4] = 'w';
      if (mode & S_IXUSR) acl_text[ 5] = 'x';
      if (mode & S_IRGRP) acl_text[10] = 'r';
      if (mode & S_IWGRP) acl_text[11] = 'w';
      if (mode & S_IXGRP) acl_text[12] = 'x';
      if (mode & S_IROTH) acl_text[17] = 'r';
      if (mode & S_IWOTH) acl_text[18] = 'w';
      if (mode & S_IXOTH) acl_text[19] = 'x';

      acl = acl_from_text (acl_text);
      if (!acl)
        return -1;
    }
  if (HAVE_ACL_SET_FD && desc != -1)
    ret = acl_set_fd (desc, acl);
  else
    ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
  if (ret != 0)
    {
      int saved_errno = errno;
      acl_free (acl);

      if (ACL_NOT_WELL_SUPPORTED (errno))
        return chmod_or_fchmod (name, desc, mode);
      else
        {
          errno = saved_errno;
          return -1;
        }
    }
  else
    acl_free (acl);

  if (S_ISDIR (mode) && acl_delete_def_file (name))
    return -1;

  if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX)))
    {
      /* We did not call chmod so far, and either the mode and the ACL are
         separate or special bits are to be set which don't fit into ACLs.  */
      return chmod_or_fchmod (name, desc, mode);
    }
  return 0;

#  else /* HAVE_ACL_TYPE_EXTENDED */
  /* MacOS X */

  /* On MacOS X,  acl_get_file (name, ACL_TYPE_ACCESS)
     and          acl_get_file (name, ACL_TYPE_DEFAULT)
     always return NULL / EINVAL.  You have to use
                  acl_get_file (name, ACL_TYPE_EXTENDED)
     or           acl_get_fd (open (name, ...))
     to retrieve an ACL.
     On the other hand,
                  acl_set_file (name, ACL_TYPE_ACCESS, acl)
     and          acl_set_file (name, ACL_TYPE_DEFAULT, acl)
     have the same effect as
                  acl_set_file (name, ACL_TYPE_EXTENDED, acl):
     Each of these calls sets the file's ACL.  */

  acl_t acl;
  int ret;

  /* Remove the ACL if the file has ACLs.  */
  if (HAVE_ACL_GET_FD && desc != -1)
    acl = acl_get_fd (desc);
  else
    acl = acl_get_file (name, ACL_TYPE_EXTENDED);
  if (acl)
    {
      acl_free (acl);

      acl = acl_init (0);
      if (acl)
        {
          if (HAVE_ACL_SET_FD && desc != -1)
            ret = acl_set_fd (desc, acl);
          else
            ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
          if (ret != 0)
            {
              int saved_errno = errno;

              acl_free (acl);

              if (ACL_NOT_WELL_SUPPORTED (saved_errno))
                return chmod_or_fchmod (name, desc, mode);
              else
                {
                  errno = saved_errno;
                  return -1;
                }
            }
          acl_free (acl);
        }
    }

  /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly.  */
  return chmod_or_fchmod (name, desc, mode);
#  endif

# elif HAVE_FACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */

  int done_setacl = 0;

#  ifdef ACE_GETACL
  /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
     file systems (whereas the other ones are used in UFS file systems).  */

  /* The flags in the ace_t structure changed in a binary incompatible way
     when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
     How to distinguish the two conventions at runtime?
     We fetch the existing ACL.  In the old convention, usually three ACEs have
     a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400.
     In the new convention, these values are not used.  */
  int convention;

  {
    int count;
    ace_t *entries;

    for (;;)
      {
        if (desc != -1)
          count = facl (desc, ACE_GETACLCNT, 0, NULL);
        else
          count = acl (name, ACE_GETACLCNT, 0, NULL);
        if (count <= 0)
          {
            convention = -1;
            break;
          }
        entries = (ace_t *) malloc (count * sizeof (ace_t));
        if (entries == NULL)
          {
            errno = ENOMEM;
            return -1;
          }
        if ((desc != -1
             ? facl (desc, ACE_GETACL, count, entries)
             : acl (name, ACE_GETACL, count, entries))
            == count)
          {
            int i;

            convention = 0;
            for (i = 0; i < count; i++)
              if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
                {
                  convention = 1;
                  break;
                }
            free (entries);
            break;
          }
        /* Huh? The number of ACL entries changed since the last call.
           Repeat.  */
        free (entries);
      }
  }

  if (convention >= 0)
    {
      ace_t entries[6];
      int count;
      int ret;

      if (convention)
        {
          /* Running on Solaris 10.  */
          entries[0].a_type = OLD_ALLOW;
          entries[0].a_flags = OLD_ACE_OWNER;
          entries[0].a_who = 0; /* irrelevant */
          entries[0].a_access_mask = (mode >> 6) & 7;
          entries[1].a_type = OLD_ALLOW;
          entries[1].a_flags = OLD_ACE_GROUP;
          entries[1].a_who = 0; /* irrelevant */
          entries[1].a_access_mask = (mode >> 3) & 7;
          entries[2].a_type = OLD_ALLOW;
          entries[2].a_flags = OLD_ACE_OTHER;
          entries[2].a_who = 0;
          entries[2].a_access_mask = mode & 7;
          count = 3;
        }
      else
        {
예제 #19
0
static int32_t eacls(xar_t x, xar_file_t f, const char *file) {
#ifdef HAVE_SYS_ACL_H
#if !defined(__APPLE__)
	const char *t;
	acl_t a;
	const char *type;

	xar_prop_get(f, "type", &type);
	if( !type || (strcmp(type, "symlink") == 0) )
		return 0;


	xar_prop_get(f, "acl/default", &t);
	if( t ) {
		a = acl_from_text(t);
		if( !a ) {
			xar_err_new(x);
			xar_err_set_errno(x, errno);
			xar_err_set_string(x, "Error extracting default acl from toc");
			xar_err_set_file(x, f);
			xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
		} else {
			if( acl_set_file(file, ACL_TYPE_DEFAULT, a) != 0 ) {
				xar_err_new(x);
				xar_err_set_errno(x, errno);
				xar_err_set_string(x, "Error setting default acl");
				xar_err_set_file(x, f);
				xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
			}
		}
	}

	xar_prop_get(f, "acl/access", &t);
	if( t ) {
		a = acl_from_text(t);
		if( !a ) {
			xar_err_new(x);
			xar_err_set_errno(x, errno);
			xar_err_set_string(x, "Error extracting access acl from toc");
			xar_err_set_file(x, f);
			xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
		} else {
			if( acl_set_file(file, ACL_TYPE_ACCESS, a) != 0 ) {
				xar_err_new(x);
				xar_err_set_errno(x, errno);
				xar_err_set_string(x, "Error setting access acl");
				xar_err_set_file(x, f);
				xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
			}
			acl_free(a);
		}
	}
#else /* !__APPLE__ */
	const char *t;
	acl_t a;

	xar_prop_get(f, "acl/appleextended", &t);
	if( t ) {
		a = acl_from_text(t);
		if( !a ) {
			xar_err_new(x);
			xar_err_set_errno(x, errno);
			xar_err_set_string(x, "Error extracting access acl from toc");
			xar_err_set_file(x, f);
			xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
		} else {
			if( acl_set_file(file, ACL_TYPE_ACCESS, a) != 0 ) {
				xar_err_new(x);
				xar_err_set_errno(x, errno);
				xar_err_set_string(x, "Error setting access acl");
				xar_err_set_file(x, f);
				xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
			}
			acl_free(a);
		}
	}
#endif /* !__APPLE__ */
#endif
	return 0;
}