/* Copyright (C) 2006 Andreas Gruenbacher , SuSE Linux AG. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include "attr/libattr.h" #define ERROR_CONTEXT_MACROS #include "error_context.h" #define ATTR_CONF "/etc/xattr.conf" struct attr_action { struct attr_action *next; char *pattern; int action; }; static struct attr_action *attr_actions; static void free_attr_actions(void) { struct attr_action *tmp; while (attr_actions) { tmp = attr_actions->next; free(attr_actions->pattern); free(attr_actions); attr_actions = tmp; } } static int attr_parse_attr_conf(struct error_context *ctx) { char *text, *t; size_t size_guess = 4096, len; FILE *file; char *pattern = NULL; struct attr_action *new; int action; if (attr_actions) return 0; repeat: text = malloc(size_guess + 1); if (!text) goto fail; if ((file = fopen(ATTR_CONF, "r")) == NULL) { if (errno == ENOENT) return 0; goto fail; } len = fread(text, 1, size_guess, file); if (ferror(file)) goto fail; if (!feof(file)) { fclose(file); file = NULL; free(text); size_guess *= 2; goto repeat; } fclose(file); file = NULL; text[len] = 0; t = text; for (;;) { t += strspn(t, " \t\n"); len = strcspn(t, " \t\n#"); if (t[len] == '#') { if (len) goto parse_error; t += strcspn(t, "\n"); continue; } else if (t[len] == 0) break; else if (t[len] == '\n') goto parse_error; pattern = strndup(t, len); if (!pattern) goto fail; t += len; t += strspn(t, " \t"); len = strcspn(t, " \t\n#"); if (len == 4 && !strncmp(t, "skip", 4)) action = ATTR_ACTION_SKIP; else if (len == 11 && !strncmp(t, "permissions", 11)) action = ATTR_ACTION_PERMISSIONS; else goto parse_error; t += len; t += strspn(t, " \t"); if (*t != '#' && *t != '\n') goto parse_error; new = malloc(sizeof(struct attr_action)); if (!new) goto parse_error; new->next = attr_actions; new->pattern = pattern; new->action = action; attr_actions = new; t += strcspn(t, "\n"); } return 0; parse_error: errno = EINVAL; fail: { const char *q = quote (ctx, ATTR_CONF); error (ctx, "%s", q); quote_free (ctx, q); } free(pattern); if (file) fclose(file); free(text); free_attr_actions(); return -1; } int attr_copy_action(const char *name, struct error_context *ctx) { struct attr_action *action = attr_actions; if (!attr_parse_attr_conf(ctx)) { for (action = attr_actions; action; action = action->next) { if (!fnmatch(action->pattern, name, 0)) return action->action; } } return 0; }