Blame tools/parse.c

rpm-build 0a0c83
/*
rpm-build 0a0c83
  File: parse.c
rpm-build 0a0c83
  (Linux Access Control List Management)
rpm-build 0a0c83
rpm-build 0a0c83
  Copyright (C) 1999, 2000
rpm-build 0a0c83
  Andreas Gruenbacher, <a.gruenbacher@bestbits.at>
rpm-build 0a0c83
 	
rpm-build 0a0c83
  This program is free software; you can redistribute it and/or
rpm-build 0a0c83
  modify it under the terms of the GNU Lesser General Public
rpm-build 0a0c83
  License as published by the Free Software Foundation; either
rpm-build 0a0c83
  version 2.1 of the License, or (at your option) any later version.
rpm-build 0a0c83
rpm-build 0a0c83
  This program is distributed in the hope that it will be useful,
rpm-build 0a0c83
  but WITHOUT ANY WARRANTY; without even the implied warranty of
rpm-build 0a0c83
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
rpm-build 0a0c83
  Lesser General Public License for more details.
rpm-build 0a0c83
rpm-build 0a0c83
  You should have received a copy of the GNU Lesser General Public
rpm-build 0a0c83
  License along with this library; if not, write to the Free Software
rpm-build 0a0c83
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
rpm-build 0a0c83
*/
rpm-build 0a0c83
rpm-build 0a0c83
#include "config.h"
rpm-build 0a0c83
#include <stdio.h>
rpm-build 0a0c83
#include <stdlib.h>
rpm-build 0a0c83
#include <string.h>
rpm-build 0a0c83
#include <errno.h>
rpm-build 0a0c83
#include <limits.h>
rpm-build 0a0c83
rpm-build 0a0c83
#include <sys/types.h>
rpm-build 0a0c83
#include <sys/stat.h>
rpm-build 0a0c83
#include <pwd.h>
rpm-build 0a0c83
#include <grp.h>
rpm-build 0a0c83
#include "sys/acl.h"
rpm-build 0a0c83
rpm-build 0a0c83
#include "sequence.h"
rpm-build 0a0c83
#include "parse.h"
rpm-build 0a0c83
#include "misc.h"
rpm-build 0a0c83
rpm-build 0a0c83
#define SKIP_WS(x) ({ \
rpm-build 0a0c83
	while (*(x)==' ' || *(x)=='\t' || *(x)=='\n' || *(x)=='\r') \
rpm-build 0a0c83
		(x)++; \
rpm-build 0a0c83
	})
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
skip_tag_name(
rpm-build 0a0c83
	const char **text_p,
rpm-build 0a0c83
	const char *token)
rpm-build 0a0c83
{
rpm-build 0a0c83
	size_t len = strlen(token);
rpm-build 0a0c83
	const char *text = *text_p;
rpm-build 0a0c83
rpm-build 0a0c83
	SKIP_WS(text);
rpm-build 0a0c83
	if (strncmp(text, token, len) == 0) {
rpm-build 0a0c83
		text += len;
rpm-build 0a0c83
		goto delimiter;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (*text == *token) {
rpm-build 0a0c83
		text++;
rpm-build 0a0c83
		goto delimiter;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
rpm-build 0a0c83
delimiter:
rpm-build 0a0c83
	SKIP_WS(text);
rpm-build 0a0c83
	if (*text == ':') {
rpm-build 0a0c83
		*text_p = text+1;
rpm-build 0a0c83
		return 1;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (*text == ',' || *text == '\0') {
rpm-build 0a0c83
		*text_p = text;
rpm-build 0a0c83
		return 1;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static char *
rpm-build 0a0c83
get_token(
rpm-build 0a0c83
	const char **text_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *token = NULL, *t;
rpm-build 0a0c83
	const char *bp, *ep;
rpm-build 0a0c83
rpm-build 0a0c83
	bp = *text_p;
rpm-build 0a0c83
	SKIP_WS(bp);
rpm-build 0a0c83
	ep = bp;
rpm-build 0a0c83
rpm-build 0a0c83
	while (*ep!='\0' && *ep!='\r' && *ep!='\n' && *ep!=':' && *ep!=',')
rpm-build 0a0c83
		ep++;
rpm-build 0a0c83
	if (ep == bp)
rpm-build 0a0c83
		goto after_token;
rpm-build 0a0c83
	token = (char*)malloc(ep - bp + 1);
rpm-build 0a0c83
	if (token == NULL)
rpm-build 0a0c83
		goto after_token;
rpm-build 0a0c83
	memcpy(token, bp, ep - bp);
rpm-build 0a0c83
rpm-build 0a0c83
	/* Trim trailing whitespace */
rpm-build 0a0c83
	t = token + (ep - bp - 1);
rpm-build 0a0c83
	while (t >= token &&
rpm-build 0a0c83
	       (*t==' ' || *t=='\t' || *t=='\n' || *t=='\r'))
rpm-build 0a0c83
		t--;
rpm-build 0a0c83
	*(t+1) = '\0';
rpm-build 0a0c83
rpm-build 0a0c83
after_token:
rpm-build 0a0c83
	if (*ep == ':')
rpm-build 0a0c83
		ep++;
rpm-build 0a0c83
	*text_p = ep;
rpm-build 0a0c83
	return token;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
get_id(
rpm-build 0a0c83
	const char *token,
rpm-build 0a0c83
	id_t *id_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *ep;
rpm-build 0a0c83
	long l;
rpm-build 0a0c83
	l = strtol(token, &ep, 0);
rpm-build 0a0c83
	if (*ep != '\0')
rpm-build 0a0c83
		return -1;
rpm-build 0a0c83
	if (l < 0) {
rpm-build 0a0c83
		/*
rpm-build 0a0c83
		  Negative values are interpreted as 16-bit numbers,
rpm-build 0a0c83
		  so that id -2 maps to 65534 (nobody/nogroup), etc.
rpm-build 0a0c83
		*/
rpm-build 0a0c83
		l &= 0xFFFF;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	*id_p = l;
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
get_uid(
rpm-build 0a0c83
	const char *token,
rpm-build 0a0c83
	uid_t *uid_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct passwd *passwd;
rpm-build 0a0c83
rpm-build 0a0c83
	if (get_id(token, (id_t *)uid_p) == 0)
rpm-build 0a0c83
		goto accept;
rpm-build 0a0c83
	passwd = getpwnam(token);
rpm-build 0a0c83
	if (passwd) {
rpm-build 0a0c83
		*uid_p = passwd->pw_uid;
rpm-build 0a0c83
		goto accept;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return -1;
rpm-build 0a0c83
rpm-build 0a0c83
accept:
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
get_gid(
rpm-build 0a0c83
	const char *token,
rpm-build 0a0c83
	gid_t *gid_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct group *group;
rpm-build 0a0c83
rpm-build 0a0c83
	if (get_id(token, (id_t *)gid_p) == 0)
rpm-build 0a0c83
		goto accept;
rpm-build 0a0c83
	group = getgrnam(token);
rpm-build 0a0c83
	if (group) {
rpm-build 0a0c83
		*gid_p = group->gr_gid;
rpm-build 0a0c83
		goto accept;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return -1;
rpm-build 0a0c83
rpm-build 0a0c83
accept:
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
/*
rpm-build 0a0c83
	Parses the next acl entry in text_p.
rpm-build 0a0c83
rpm-build 0a0c83
	Returns:
rpm-build 0a0c83
		-1 on error, 0 on success.
rpm-build 0a0c83
*/
rpm-build 0a0c83
rpm-build 0a0c83
cmd_t
rpm-build 0a0c83
parse_acl_cmd(
rpm-build 0a0c83
	const char **text_p,
rpm-build 0a0c83
	int seq_cmd,
rpm-build 0a0c83
	int parse_mode)
rpm-build 0a0c83
{
rpm-build 0a0c83
	cmd_t cmd = cmd_init();
rpm-build 0a0c83
	char *str;
rpm-build 0a0c83
	const char *backup;
rpm-build 0a0c83
	int error, perm_chars;
rpm-build 0a0c83
	if (!cmd)
rpm-build 0a0c83
		return NULL;
rpm-build 0a0c83
rpm-build 0a0c83
	cmd->c_cmd = seq_cmd;
rpm-build 0a0c83
	if (parse_mode & SEQ_PROMOTE_ACL)
rpm-build 0a0c83
		cmd->c_type = ACL_TYPE_DEFAULT;
rpm-build 0a0c83
	else
rpm-build 0a0c83
		cmd->c_type = ACL_TYPE_ACCESS;
rpm-build 0a0c83
	cmd->c_id   = ACL_UNDEFINED_ID;
rpm-build 0a0c83
	cmd->c_perm = 0;
rpm-build 0a0c83
rpm-build 0a0c83
	if (parse_mode & SEQ_PARSE_DEFAULT) {
rpm-build 0a0c83
		/* check for default acl entry */
rpm-build 0a0c83
		backup = *text_p;
rpm-build 0a0c83
		if (skip_tag_name(text_p, "default")) {
rpm-build 0a0c83
			if (parse_mode & SEQ_PROMOTE_ACL) {
rpm-build 0a0c83
				/* if promoting from acl to default acl and
rpm-build 0a0c83
				   a default acl entry is found, fail. */
rpm-build 0a0c83
				*text_p = backup;
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			cmd->c_type = ACL_TYPE_DEFAULT;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* parse acl entry type */
rpm-build 0a0c83
	switch (**text_p) {
rpm-build 0a0c83
		case 'u':  /* user */
rpm-build 0a0c83
			skip_tag_name(text_p, "user");
rpm-build 0a0c83
rpm-build 0a0c83
user_entry:
rpm-build 0a0c83
			backup = *text_p;
rpm-build 0a0c83
			str = get_token(text_p);
rpm-build 0a0c83
			if (str) {
rpm-build 0a0c83
				cmd->c_tag = ACL_USER;
rpm-build 0a0c83
				error = get_uid(__acl_unquote(str), &cmd->c_id);
rpm-build 0a0c83
				free(str);
rpm-build 0a0c83
				if (error) {
rpm-build 0a0c83
					*text_p = backup;
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				}
rpm-build 0a0c83
			} else {
rpm-build 0a0c83
				cmd->c_tag = ACL_USER_OBJ;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			break;
rpm-build 0a0c83
rpm-build 0a0c83
		case 'g':  /* group */
rpm-build 0a0c83
			if (!skip_tag_name(text_p, "group"))
rpm-build 0a0c83
				goto user_entry;
rpm-build 0a0c83
rpm-build 0a0c83
			backup = *text_p;
rpm-build 0a0c83
			str = get_token(text_p);
rpm-build 0a0c83
			if (str) {
rpm-build 0a0c83
				cmd->c_tag = ACL_GROUP;
rpm-build 0a0c83
				error = get_gid(__acl_unquote(str), &cmd->c_id);
rpm-build 0a0c83
				free(str);
rpm-build 0a0c83
				if (error) {
rpm-build 0a0c83
					*text_p = backup;
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				}
rpm-build 0a0c83
			} else {
rpm-build 0a0c83
				cmd->c_tag = ACL_GROUP_OBJ;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			break;
rpm-build 0a0c83
rpm-build 0a0c83
		case 'o':  /* other */
rpm-build 0a0c83
			if (!skip_tag_name(text_p, "other"))
rpm-build 0a0c83
				goto user_entry;
rpm-build 0a0c83
			/* skip empty entry qualifier field (this field may
rpm-build 0a0c83
			   be missing for compatibility with Solaris.) */
rpm-build 0a0c83
			SKIP_WS(*text_p);
rpm-build 0a0c83
			if (**text_p == ':')
rpm-build 0a0c83
				(*text_p)++;
rpm-build 0a0c83
			cmd->c_tag = ACL_OTHER;
rpm-build 0a0c83
			break;
rpm-build 0a0c83
rpm-build 0a0c83
		case 'm':  /* mask */
rpm-build 0a0c83
			if (!skip_tag_name(text_p, "mask"))
rpm-build 0a0c83
				goto user_entry;
rpm-build 0a0c83
			/* skip empty entry qualifier field (this field may
rpm-build 0a0c83
			   be missing for compatibility with Solaris.) */
rpm-build 0a0c83
			SKIP_WS(*text_p);
rpm-build 0a0c83
			if (**text_p == ':')
rpm-build 0a0c83
				(*text_p)++;
rpm-build 0a0c83
			cmd->c_tag = ACL_MASK;
rpm-build 0a0c83
			break;
rpm-build 0a0c83
rpm-build 0a0c83
		default:  /* assume "user:" */
rpm-build 0a0c83
			goto user_entry;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	SKIP_WS(*text_p);
rpm-build 0a0c83
	if (**text_p == ',' || **text_p == '\0') {
rpm-build 0a0c83
		if (parse_mode & SEQ_PARSE_NO_PERM)
rpm-build 0a0c83
			return cmd;
rpm-build 0a0c83
		else
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (!(parse_mode & SEQ_PARSE_WITH_PERM))
rpm-build 0a0c83
		return cmd;
rpm-build 0a0c83
rpm-build 0a0c83
	/* parse permissions */
rpm-build 0a0c83
	SKIP_WS(*text_p);
rpm-build 0a0c83
	if (**text_p >= '0' && **text_p <= '7') {
rpm-build 0a0c83
		cmd->c_perm = 0;
rpm-build 0a0c83
		while (**text_p == '0')
rpm-build 0a0c83
			(*text_p)++;
rpm-build 0a0c83
		if (**text_p >= '1' && **text_p <= '7') {
rpm-build 0a0c83
			cmd->c_perm = (*(*text_p)++ - '0');
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		return cmd;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	for (perm_chars=0;; perm_chars++, (*text_p)++) {
rpm-build 0a0c83
		switch(**text_p) {
rpm-build 0a0c83
			case 'r': /* read */
rpm-build 0a0c83
				if (cmd->c_perm & CMD_PERM_READ)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				cmd->c_perm |= CMD_PERM_READ;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'w':  /* write */
rpm-build 0a0c83
				if (cmd->c_perm & CMD_PERM_WRITE)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				cmd->c_perm |= CMD_PERM_WRITE;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'x':  /* execute */
rpm-build 0a0c83
				if (cmd->c_perm & CMD_PERM_EXECUTE)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				cmd->c_perm |= CMD_PERM_EXECUTE;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'X':  /* execute only if directory or some
rpm-build 0a0c83
				      entries already have execute permissions
rpm-build 0a0c83
				      set */
rpm-build 0a0c83
				if (cmd->c_perm & CMD_PERM_COND_EXECUTE)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				cmd->c_perm |= CMD_PERM_COND_EXECUTE;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case '-':
rpm-build 0a0c83
				/* ignore */
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			default:
rpm-build 0a0c83
				if (perm_chars == 0)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				return cmd;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return cmd;
rpm-build 0a0c83
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	cmd_free(cmd);
rpm-build 0a0c83
	return NULL;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
/*
rpm-build 0a0c83
	Parse a comma-separated list of acl entries.
rpm-build 0a0c83
rpm-build 0a0c83
	which is set to the index of the first character that was not parsed,
rpm-build 0a0c83
	or -1 in case of success.
rpm-build 0a0c83
*/
rpm-build 0a0c83
int
rpm-build 0a0c83
parse_acl_seq(
rpm-build 0a0c83
	seq_t seq,
rpm-build 0a0c83
	const char *text_p,
rpm-build 0a0c83
	int *which,
rpm-build 0a0c83
	int seq_cmd,
rpm-build 0a0c83
	int parse_mode)
rpm-build 0a0c83
{
rpm-build 0a0c83
	const char *initial_text_p = text_p;
rpm-build 0a0c83
	cmd_t cmd;
rpm-build 0a0c83
rpm-build 0a0c83
	if (which)
rpm-build 0a0c83
		*which = -1;
rpm-build 0a0c83
rpm-build 0a0c83
	while (*text_p != '\0') {
rpm-build 0a0c83
		cmd = parse_acl_cmd(&text_p, seq_cmd, parse_mode);
rpm-build 0a0c83
		if (cmd == NULL) {
rpm-build 0a0c83
			errno = EINVAL;
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (seq_append(seq, cmd) != 0) {
rpm-build 0a0c83
			cmd_free(cmd);
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		SKIP_WS(text_p);
rpm-build 0a0c83
		if (*text_p != ',')
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		text_p++;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	if (*text_p != '\0') {
rpm-build 0a0c83
		errno = EINVAL;
rpm-build 0a0c83
		goto fail;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	if (which)
rpm-build 0a0c83
		*which = (text_p - initial_text_p);
rpm-build 0a0c83
	return -1;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
int
rpm-build 0a0c83
read_acl_comments(
rpm-build 0a0c83
	FILE *file,
rpm-build 0a0c83
	int *lineno,
rpm-build 0a0c83
	char **path_p,
rpm-build 0a0c83
	uid_t *uid_p,
rpm-build 0a0c83
	gid_t *gid_p,
rpm-build 0a0c83
	mode_t *flags)
rpm-build 0a0c83
{
rpm-build 0a0c83
	int c;
rpm-build 0a0c83
	/*
rpm-build 0a0c83
	  Max PATH_MAX bytes even for UTF-8 path names and additional 9
rpm-build 0a0c83
	  bytes for "# file: ". Not a good solution but for now it is the
rpm-build 0a0c83
	  best I can do without too much impact on the code. [tw]
rpm-build 0a0c83
	*/
rpm-build 0a0c83
	char *line, *cp, *p;
rpm-build 0a0c83
	int comments_read = 0;
rpm-build 0a0c83
	
rpm-build 0a0c83
	if (path_p)
rpm-build 0a0c83
		*path_p = NULL;
rpm-build 0a0c83
	if (uid_p)
rpm-build 0a0c83
		*uid_p = ACL_UNDEFINED_ID;
rpm-build 0a0c83
	if (gid_p)
rpm-build 0a0c83
		*gid_p = ACL_UNDEFINED_ID;
rpm-build 0a0c83
	if (flags)
rpm-build 0a0c83
		*flags = 0;
rpm-build 0a0c83
rpm-build 0a0c83
	for(;;) {
rpm-build 0a0c83
		c = fgetc(file);
rpm-build 0a0c83
		if (c == EOF)
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		if (c==' ' || c=='\t' || c=='\r' || c=='\n') {
rpm-build 0a0c83
			if (c=='\n')
rpm-build 0a0c83
				(*lineno)++;
rpm-build 0a0c83
			continue;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (c != '#') {
rpm-build 0a0c83
			ungetc(c, file);
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (lineno)
rpm-build 0a0c83
			(*lineno)++;
rpm-build 0a0c83
rpm-build 0a0c83
		line = __acl_next_line(file);
rpm-build 0a0c83
		if (line == NULL)
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		
rpm-build 0a0c83
		comments_read = 1;
rpm-build 0a0c83
rpm-build 0a0c83
		p = strrchr(line, '\0');
rpm-build 0a0c83
		while (p > line &&
rpm-build 0a0c83
		       (*(p-1)=='\r' || *(p-1)=='\n')) {
rpm-build 0a0c83
		       	p--;
rpm-build 0a0c83
			*p = '\0';
rpm-build 0a0c83
		}
rpm-build 0a0c83
		
rpm-build 0a0c83
		cp = line;
rpm-build 0a0c83
		SKIP_WS(cp);
rpm-build 0a0c83
		if (strncmp(cp, "file:", 5) == 0) {
rpm-build 0a0c83
			cp += 5;
rpm-build 0a0c83
			SKIP_WS(cp);
rpm-build 0a0c83
			cp = __acl_unquote(cp);
rpm-build 0a0c83
			
rpm-build 0a0c83
			if (path_p) {
rpm-build 0a0c83
				if (*path_p)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				*path_p = (char*)malloc(strlen(cp)+1);
rpm-build 0a0c83
				if (!*path_p)
rpm-build 0a0c83
					return -1;
rpm-build 0a0c83
				strcpy(*path_p, cp);
rpm-build 0a0c83
			}
rpm-build 0a0c83
		} else if (strncmp(cp, "owner:", 6) == 0) {
rpm-build 0a0c83
			cp += 6;
rpm-build 0a0c83
			SKIP_WS(cp);
rpm-build 0a0c83
				
rpm-build 0a0c83
			if (uid_p) {
rpm-build 0a0c83
				if (*uid_p != ACL_UNDEFINED_ID)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				if (get_uid(__acl_unquote(cp), uid_p) != 0)
rpm-build 0a0c83
					continue;
rpm-build 0a0c83
			}
rpm-build 0a0c83
		} else if (strncmp(cp, "group:", 6) == 0) {
rpm-build 0a0c83
			cp += 6;
rpm-build 0a0c83
			SKIP_WS(cp);
rpm-build 0a0c83
				
rpm-build 0a0c83
			if (gid_p) {
rpm-build 0a0c83
				if (*gid_p != ACL_UNDEFINED_ID)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				if (get_gid(__acl_unquote(cp), gid_p) != 0)
rpm-build 0a0c83
					continue;
rpm-build 0a0c83
			}
rpm-build 0a0c83
		} else if (strncmp(cp, "flags:", 6) == 0) {
rpm-build 0a0c83
			mode_t f = 0;
rpm-build 0a0c83
rpm-build 0a0c83
			cp += 6;
rpm-build 0a0c83
			SKIP_WS(cp);
rpm-build 0a0c83
rpm-build 0a0c83
			if (cp[0] == 's')
rpm-build 0a0c83
				f |= S_ISUID;
rpm-build 0a0c83
			else if (cp[0] != '-')
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			if (cp[1] == 's')
rpm-build 0a0c83
				f |= S_ISGID;
rpm-build 0a0c83
			else if (cp[1] != '-')
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			if (cp[2] == 't')
rpm-build 0a0c83
				f |= S_ISVTX;
rpm-build 0a0c83
			else if (cp[2] != '-')
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			if (cp[3] != '\0')
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
rpm-build 0a0c83
			if (flags)
rpm-build 0a0c83
				*flags = f;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (ferror(file))
rpm-build 0a0c83
		return -1;
rpm-build 0a0c83
	return comments_read;
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	if (path_p && *path_p) {
rpm-build 0a0c83
		free(*path_p);
rpm-build 0a0c83
		*path_p = NULL;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return -EINVAL;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
int
rpm-build 0a0c83
read_acl_seq(
rpm-build 0a0c83
	FILE *file,
rpm-build 0a0c83
	seq_t seq,
rpm-build 0a0c83
	int seq_cmd,
rpm-build 0a0c83
	int parse_mode,
rpm-build 0a0c83
	int *lineno,
rpm-build 0a0c83
	int *which)
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *line;
rpm-build 0a0c83
	const char *cp;
rpm-build 0a0c83
	cmd_t cmd;
rpm-build 0a0c83
rpm-build 0a0c83
	if (which)
rpm-build 0a0c83
		*which = -1;
rpm-build 0a0c83
rpm-build 0a0c83
	while ((line = __acl_next_line(file))) {
rpm-build 0a0c83
		if (lineno)
rpm-build 0a0c83
			(*lineno)++;
rpm-build 0a0c83
rpm-build 0a0c83
		cp = line;
rpm-build 0a0c83
		SKIP_WS(cp);
rpm-build 0a0c83
		if (*cp == '\0') {
rpm-build 0a0c83
			if (!(parse_mode & SEQ_PARSE_MULTI))
rpm-build 0a0c83
				continue;
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		} else if (*cp == '#') {
rpm-build 0a0c83
			continue;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		cmd = parse_acl_cmd(&cp, seq_cmd, parse_mode);
rpm-build 0a0c83
		if (cmd == NULL) {
rpm-build 0a0c83
			errno = EINVAL;
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (seq_append(seq, cmd) != 0) {
rpm-build 0a0c83
			cmd_free(cmd);
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		SKIP_WS(cp);
rpm-build 0a0c83
		if (*cp != '\0' && *cp != '#') {
rpm-build 0a0c83
			errno = EINVAL;
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	if (ferror(file))
rpm-build 0a0c83
		goto fail;
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	if (which)
rpm-build 0a0c83
		*which = (cp - line);
rpm-build 0a0c83
	return -1;
rpm-build 0a0c83
}
rpm-build 0a0c83