(root)/
attr-2.5.1/
libattr/
attr_copy_action.c
       1  /*
       2    Copyright (C) 2006 Andreas Gruenbacher <agruen@suse.de>, SuSE Linux AG.
       3  
       4    This program is free software; you can redistribute it and/or
       5    modify it under the terms of the GNU Lesser General Public
       6    License as published by the Free Software Foundation; either
       7    version 2.1 of the License, or (at your option) any later version.
       8  
       9    This program is distributed in the hope that it will be useful,
      10    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12    Lesser General Public License for more details.
      13  
      14    You should have received a copy of the GNU Lesser General Public License
      15    along with this manual.  If not, see <http://www.gnu.org/licenses/>.
      16  */
      17  
      18  #include "config.h"
      19  
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <errno.h>
      23  #include <string.h>
      24  #include <stdarg.h>
      25  #include <fnmatch.h>
      26  
      27  #include "attr/libattr.h"
      28  #define ERROR_CONTEXT_MACROS
      29  #include "error_context.h"
      30  
      31  #define ATTR_CONF SYSCONFDIR "/xattr.conf"
      32  
      33  struct attr_action {
      34  	struct attr_action *next;
      35  	char *pattern;
      36  	int action;
      37  };
      38  
      39  static struct attr_action *attr_actions;
      40  
      41  static void
      42  free_attr_actions(void)
      43  {
      44  	struct attr_action *tmp;
      45  
      46  	while (attr_actions) {
      47  		tmp = attr_actions->next;
      48  		free(attr_actions->pattern);
      49  		free(attr_actions);
      50  		attr_actions = tmp;
      51  	}
      52  }
      53  
      54  static int
      55  attr_parse_attr_conf(struct error_context *ctx)
      56  {
      57  	char *text = NULL, *t;
      58  	size_t size_guess = 4096, len;
      59  	FILE *file;
      60  	char *pattern = NULL;
      61  	struct attr_action *new;
      62  	int action;
      63  
      64  	if (attr_actions)
      65  		return 0;
      66  
      67  repeat:
      68  	if ((file = fopen(ATTR_CONF, "r")) == NULL) {
      69  		if (errno == ENOENT)
      70  			return 0;
      71  		goto fail;
      72  	}
      73  
      74  	text = malloc(size_guess + 1);
      75  	if (!text)
      76  		goto fail;
      77  
      78  	len = fread(text, 1, size_guess, file);
      79  	if (ferror(file))
      80  		goto fail;
      81  	if (!feof(file)) {
      82  		fclose(file);
      83  		file = NULL;
      84  		free(text);
      85  		text = NULL;
      86  		size_guess *= 2;
      87  		goto repeat;
      88  	}
      89  	fclose(file);
      90  	file = NULL;
      91  
      92  	text[len] = 0;
      93  	t = text;
      94  	for (;;) {
      95  		t += strspn(t, " \t\n");
      96  		len = strcspn(t, " \t\n#");
      97  		if (t[len] == '#') {
      98  			if (len)
      99  				goto parse_error;
     100  			t += strcspn(t, "\n");
     101  			continue;
     102  		} else if (t[len] == 0)
     103  			break;
     104  		else if (t[len] == '\n')
     105  			goto parse_error;
     106  		pattern = strndup(t, len);
     107  		if (!pattern)
     108  			goto fail;
     109  		t += len;
     110  
     111  		t += strspn(t, " \t");
     112  		len = strcspn(t, " \t\n#");
     113  		if (len == 4 && !strncmp(t, "skip", 4))
     114  			action = ATTR_ACTION_SKIP;
     115  		else if (len == 11 && !strncmp(t, "permissions", 11))
     116  			action = ATTR_ACTION_PERMISSIONS;
     117  		else
     118  			goto parse_error;
     119  		t += len;
     120  		t += strspn(t, " \t");
     121  		if (*t != '#' && *t != '\n')
     122  			goto parse_error;
     123  
     124  		new = malloc(sizeof(struct attr_action));
     125  		if (!new)
     126  			goto parse_error;
     127  		new->next = attr_actions;
     128  		new->pattern = pattern;
     129  		new->action = action;
     130  		attr_actions = new;
     131  
     132  		t += strcspn(t, "\n");
     133  	}
     134  	free(text);
     135  	return 0;
     136  
     137  parse_error:
     138  	errno = EINVAL;
     139  
     140  fail:
     141  	{
     142  		const char *q = quote (ctx, ATTR_CONF);
     143  		error (ctx, "%s", q);
     144  		quote_free (ctx, q);
     145  	}
     146  
     147  	free(pattern);
     148  	if (file)
     149  		fclose(file);
     150  	free(text);
     151  	free_attr_actions();
     152  	return -1;
     153  }
     154  
     155  int
     156  attr_copy_action(const char *name, struct error_context *ctx)
     157  {
     158  	struct attr_action *action = attr_actions;
     159  
     160  	if (!attr_parse_attr_conf(ctx)) {
     161  		for (action = attr_actions; action; action = action->next) {
     162  			if (!fnmatch(action->pattern, name, 0))
     163  				return action->action;
     164  		}
     165  	}
     166  	return 0;
     167  }