|
Packit Service |
a2ae7a |
/*
|
|
Packit Service |
a2ae7a |
* internal.c: internal data structures and helpers
|
|
Packit Service |
a2ae7a |
*
|
|
Packit Service |
a2ae7a |
* Copyright (C) 2007-2016 David Lutterkort
|
|
Packit Service |
a2ae7a |
*
|
|
Packit Service |
a2ae7a |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
a2ae7a |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
a2ae7a |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
a2ae7a |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit Service |
a2ae7a |
*
|
|
Packit Service |
a2ae7a |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
a2ae7a |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
a2ae7a |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
a2ae7a |
* Lesser General Public License for more details.
|
|
Packit Service |
a2ae7a |
*
|
|
Packit Service |
a2ae7a |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
a2ae7a |
* License along with this library; if not, write to the Free Software
|
|
Packit Service |
a2ae7a |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit Service |
a2ae7a |
*
|
|
Packit Service |
a2ae7a |
* Author: David Lutterkort <dlutter@redhat.com>
|
|
Packit Service |
a2ae7a |
*/
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
#include <config.h>
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
#include <ctype.h>
|
|
Packit Service |
a2ae7a |
#include <stdio.h>
|
|
Packit Service |
a2ae7a |
#include <stdarg.h>
|
|
Packit Service |
a2ae7a |
#include <locale.h>
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
#include "internal.h"
|
|
Packit Service |
a2ae7a |
#include "memory.h"
|
|
Packit Service |
a2ae7a |
#include "fa.h"
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
#ifndef MIN
|
|
Packit Service |
a2ae7a |
# define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
Packit Service |
a2ae7a |
#endif
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
/* Cap file reads somwhat arbitrarily at 32 MB */
|
|
Packit Service |
a2ae7a |
#define MAX_READ_LEN (32*1024*1024)
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int pathjoin(char **path, int nseg, ...) {
|
|
Packit Service |
a2ae7a |
va_list ap;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
va_start(ap, nseg);
|
|
Packit Service |
a2ae7a |
for (int i=0; i < nseg; i++) {
|
|
Packit Service |
a2ae7a |
const char *seg = va_arg(ap, const char *);
|
|
Packit Service |
a2ae7a |
if (seg == NULL)
|
|
Packit Service |
a2ae7a |
seg = "()";
|
|
Packit Service |
a2ae7a |
int len = strlen(seg) + 1;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (*path != NULL) {
|
|
Packit Service |
a2ae7a |
len += strlen(*path) + 1;
|
|
Packit Service |
a2ae7a |
if (REALLOC_N(*path, len) == -1) {
|
|
Packit Service |
a2ae7a |
FREE(*path);
|
|
Packit Service |
a2ae7a |
va_end(ap);
|
|
Packit Service |
a2ae7a |
return -1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
if (strlen(*path) == 0 || (*path)[strlen(*path)-1] != SEP)
|
|
Packit Service |
a2ae7a |
strcat(*path, "/");
|
|
Packit Service |
a2ae7a |
if (seg[0] == SEP)
|
|
Packit Service |
a2ae7a |
seg += 1;
|
|
Packit Service |
a2ae7a |
strcat(*path, seg);
|
|
Packit Service |
a2ae7a |
} else {
|
|
Packit Service |
a2ae7a |
if ((*path = malloc(len)) == NULL) {
|
|
Packit Service |
a2ae7a |
va_end(ap);
|
|
Packit Service |
a2ae7a |
return -1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
strcpy(*path, seg);
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
va_end(ap);
|
|
Packit Service |
a2ae7a |
return 0;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
/* Like gnulib's fread_file, but read no more than the specified maximum
|
|
Packit Service |
a2ae7a |
number of bytes. If the length of the input is <= max_len, and
|
|
Packit Service |
a2ae7a |
upon error while reading that data, it works just like fread_file.
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
Taken verbatim from libvirt's util.c
|
|
Packit Service |
a2ae7a |
*/
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
static char *
|
|
Packit Service |
a2ae7a |
fread_file_lim (FILE *stream, size_t max_len, size_t *length)
|
|
Packit Service |
a2ae7a |
{
|
|
Packit Service |
a2ae7a |
char *buf = NULL;
|
|
Packit Service |
a2ae7a |
size_t alloc = 0;
|
|
Packit Service |
a2ae7a |
size_t size = 0;
|
|
Packit Service |
a2ae7a |
int save_errno;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
for (;;) {
|
|
Packit Service |
a2ae7a |
size_t count;
|
|
Packit Service |
a2ae7a |
size_t requested;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (size + BUFSIZ + 1 > alloc) {
|
|
Packit Service |
a2ae7a |
char *new_buf;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
alloc += alloc / 2;
|
|
Packit Service |
a2ae7a |
if (alloc < size + BUFSIZ + 1)
|
|
Packit Service |
a2ae7a |
alloc = size + BUFSIZ + 1;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
new_buf = realloc (buf, alloc);
|
|
Packit Service |
a2ae7a |
if (!new_buf) {
|
|
Packit Service |
a2ae7a |
save_errno = errno;
|
|
Packit Service |
a2ae7a |
break;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
buf = new_buf;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
/* Ensure that (size + requested <= max_len); */
|
|
Packit Service |
a2ae7a |
requested = MIN (size < max_len ? max_len - size : 0,
|
|
Packit Service |
a2ae7a |
alloc - size - 1);
|
|
Packit Service |
a2ae7a |
count = fread (buf + size, 1, requested, stream);
|
|
Packit Service |
a2ae7a |
size += count;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (count != requested || requested == 0) {
|
|
Packit Service |
a2ae7a |
save_errno = errno;
|
|
Packit Service |
a2ae7a |
if (ferror (stream))
|
|
Packit Service |
a2ae7a |
break;
|
|
Packit Service |
a2ae7a |
buf[size] = '\0';
|
|
Packit Service |
a2ae7a |
*length = size;
|
|
Packit Service |
a2ae7a |
return buf;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
free (buf);
|
|
Packit Service |
a2ae7a |
errno = save_errno;
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
char* xfread_file(FILE *fp) {
|
|
Packit Service |
a2ae7a |
char *result;
|
|
Packit Service |
a2ae7a |
size_t len;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (!fp)
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
result = fread_file_lim(fp, MAX_READ_LEN, &len;;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (result != NULL
|
|
Packit Service |
a2ae7a |
&& len <= MAX_READ_LEN
|
|
Packit Service |
a2ae7a |
&& (int) len == len)
|
|
Packit Service |
a2ae7a |
return result;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
free(result);
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
char* xread_file(const char *path) {
|
|
Packit Service |
a2ae7a |
FILE *fp;
|
|
Packit Service |
a2ae7a |
char *result;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
fp = fopen(path, "r");
|
|
Packit Service |
a2ae7a |
if (!fp)
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
result = xfread_file(fp);
|
|
Packit Service |
a2ae7a |
fclose(fp);
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
return result;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
/*
|
|
Packit Service |
a2ae7a |
* Escape/unescape of string literals
|
|
Packit Service |
a2ae7a |
*/
|
|
Packit Service |
a2ae7a |
static const char *const escape_chars = "\a\b\t\n\v\f\r";
|
|
Packit Service |
a2ae7a |
static const char *const escape_names = "abtnvfr";
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
char *unescape(const char *s, int len, const char *extra) {
|
|
Packit Service |
a2ae7a |
size_t size;
|
|
Packit Service |
a2ae7a |
const char *n;
|
|
Packit Service |
a2ae7a |
char *result, *t;
|
|
Packit Service |
a2ae7a |
int i;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (len < 0 || len > strlen(s))
|
|
Packit Service |
a2ae7a |
len = strlen(s);
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
size = 0;
|
|
Packit Service |
a2ae7a |
for (i=0; i < len; i++, size++) {
|
|
Packit Service |
a2ae7a |
if (s[i] == '\\' && strchr(escape_names, s[i+1])) {
|
|
Packit Service |
a2ae7a |
i += 1;
|
|
Packit Service |
a2ae7a |
} else if (s[i] == '\\' && extra && strchr(extra, s[i+1])) {
|
|
Packit Service |
a2ae7a |
i += 1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (ALLOC_N(result, size + 1) < 0)
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
for (i = 0, t = result; i < len; i++, size++) {
|
|
Packit Service |
a2ae7a |
if (s[i] == '\\' && (n = strchr(escape_names, s[i+1])) != NULL) {
|
|
Packit Service |
a2ae7a |
*t++ = escape_chars[n - escape_names];
|
|
Packit Service |
a2ae7a |
i += 1;
|
|
Packit Service |
a2ae7a |
} else if (s[i] == '\\' && extra && strchr(extra, s[i+1]) != NULL) {
|
|
Packit Service |
a2ae7a |
*t++ = s[i+1];
|
|
Packit Service |
a2ae7a |
i += 1;
|
|
Packit Service |
a2ae7a |
} else {
|
|
Packit Service |
a2ae7a |
*t++ = s[i];
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
return result;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
char *escape(const char *text, int cnt, const char *extra) {
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int len = 0;
|
|
Packit Service |
a2ae7a |
char *esc = NULL, *e;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (cnt < 0 || cnt > strlen(text))
|
|
Packit Service |
a2ae7a |
cnt = strlen(text);
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
for (int i=0; i < cnt; i++) {
|
|
Packit Service |
a2ae7a |
if (text[i] && (strchr(escape_chars, text[i]) != NULL))
|
|
Packit Service |
a2ae7a |
len += 2; /* Escaped as '\x' */
|
|
Packit Service |
a2ae7a |
else if (text[i] && extra && (strchr(extra, text[i]) != NULL))
|
|
Packit Service |
a2ae7a |
len += 2; /* Escaped as '\x' */
|
|
Packit Service |
a2ae7a |
else if (! isprint(text[i]))
|
|
Packit Service |
a2ae7a |
len += 4; /* Escaped as '\ooo' */
|
|
Packit Service |
a2ae7a |
else
|
|
Packit Service |
a2ae7a |
len += 1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
if (ALLOC_N(esc, len+1) < 0)
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
e = esc;
|
|
Packit Service |
a2ae7a |
for (int i=0; i < cnt; i++) {
|
|
Packit Service |
a2ae7a |
char *p;
|
|
Packit Service |
a2ae7a |
if (text[i] && ((p = strchr(escape_chars, text[i])) != NULL)) {
|
|
Packit Service |
a2ae7a |
*e++ = '\\';
|
|
Packit Service |
a2ae7a |
*e++ = escape_names[p - escape_chars];
|
|
Packit Service |
a2ae7a |
} else if (text[i] && extra && (strchr(extra, text[i]) != NULL)) {
|
|
Packit Service |
a2ae7a |
*e++ = '\\';
|
|
Packit Service |
a2ae7a |
*e++ = text[i];
|
|
Packit Service |
a2ae7a |
} else if (! isprint(text[i])) {
|
|
Packit Service |
a2ae7a |
sprintf(e, "\\%03o", (unsigned char) text[i]);
|
|
Packit Service |
a2ae7a |
e += 4;
|
|
Packit Service |
a2ae7a |
} else {
|
|
Packit Service |
a2ae7a |
*e++ = text[i];
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
return esc;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int print_chars(FILE *out, const char *text, int cnt) {
|
|
Packit Service |
a2ae7a |
int total = 0;
|
|
Packit Service |
a2ae7a |
char *esc;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (text == NULL) {
|
|
Packit Service |
a2ae7a |
fprintf(out, "nil");
|
|
Packit Service |
a2ae7a |
return 3;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
if (cnt < 0)
|
|
Packit Service |
a2ae7a |
cnt = strlen(text);
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
esc = escape(text, cnt, "\"");
|
|
Packit Service |
a2ae7a |
total = strlen(esc);
|
|
Packit Service |
a2ae7a |
if (out != NULL)
|
|
Packit Service |
a2ae7a |
fprintf(out, "%s", esc);
|
|
Packit Service |
a2ae7a |
free(esc);
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
return total;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
char *format_pos(const char *text, int pos) {
|
|
Packit Service |
a2ae7a |
static const int window = 28;
|
|
Packit Service |
a2ae7a |
char *buf = NULL, *left = NULL, *right = NULL;
|
|
Packit Service |
a2ae7a |
int before = pos;
|
|
Packit Service |
a2ae7a |
int llen, rlen;
|
|
Packit Service |
a2ae7a |
int r;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (before > window)
|
|
Packit Service |
a2ae7a |
before = window;
|
|
Packit Service |
a2ae7a |
left = escape(text + pos - before, before, NULL);
|
|
Packit Service |
a2ae7a |
if (left == NULL)
|
|
Packit Service |
a2ae7a |
goto done;
|
|
Packit Service |
a2ae7a |
right = escape(text + pos, window, NULL);
|
|
Packit Service |
a2ae7a |
if (right == NULL)
|
|
Packit Service |
a2ae7a |
goto done;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
llen = strlen(left);
|
|
Packit Service |
a2ae7a |
rlen = strlen(right);
|
|
Packit Service |
a2ae7a |
if (llen < window && rlen < window) {
|
|
Packit Service |
a2ae7a |
r = asprintf(&buf, "%*s%s|=|%s%-*s\n", window - llen, "<", left,
|
|
Packit Service |
a2ae7a |
right, window - rlen, ">");
|
|
Packit Service |
a2ae7a |
} else if (strlen(left) < window) {
|
|
Packit Service |
a2ae7a |
r = asprintf(&buf, "%*s%s|=|%s>\n", window - llen, "<", left, right);
|
|
Packit Service |
a2ae7a |
} else if (strlen(right) < window) {
|
|
Packit Service |
a2ae7a |
r = asprintf(&buf, "<%s|=|%s%-*s\n", left, right, window - rlen, ">");
|
|
Packit Service |
a2ae7a |
} else {
|
|
Packit Service |
a2ae7a |
r = asprintf(&buf, "<%s|=|%s>\n", left, right);
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
if (r < 0) {
|
|
Packit Service |
a2ae7a |
buf = NULL;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
done:
|
|
Packit Service |
a2ae7a |
free(left);
|
|
Packit Service |
a2ae7a |
free(right);
|
|
Packit Service |
a2ae7a |
return buf;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
void print_pos(FILE *out, const char *text, int pos) {
|
|
Packit Service |
a2ae7a |
char *format = format_pos(text, pos);
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (format != NULL) {
|
|
Packit Service |
a2ae7a |
fputs(format, out);
|
|
Packit Service |
a2ae7a |
FREE(format);
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int __aug_init_memstream(struct memstream *ms) {
|
|
Packit Service |
a2ae7a |
MEMZERO(ms, 1);
|
|
Packit Service |
a2ae7a |
#if HAVE_OPEN_MEMSTREAM
|
|
Packit Service |
a2ae7a |
ms->stream = open_memstream(&(ms->buf), &(ms->size));
|
|
Packit Service |
a2ae7a |
return ms->stream == NULL ? -1 : 0;
|
|
Packit Service |
a2ae7a |
#else
|
|
Packit Service |
a2ae7a |
ms->stream = tmpfile();
|
|
Packit Service |
a2ae7a |
if (ms->stream == NULL) {
|
|
Packit Service |
a2ae7a |
return -1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
return 0;
|
|
Packit Service |
a2ae7a |
#endif
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int __aug_close_memstream(struct memstream *ms) {
|
|
Packit Service |
a2ae7a |
#if !HAVE_OPEN_MEMSTREAM
|
|
Packit Service |
a2ae7a |
rewind(ms->stream);
|
|
Packit Service |
a2ae7a |
ms->buf = fread_file_lim(ms->stream, MAX_READ_LEN, &(ms->size));
|
|
Packit Service |
a2ae7a |
#endif
|
|
Packit Service |
a2ae7a |
if (fclose(ms->stream) == EOF) {
|
|
Packit Service |
a2ae7a |
FREE(ms->buf);
|
|
Packit Service |
a2ae7a |
ms->size = 0;
|
|
Packit Service |
a2ae7a |
return -1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
return 0;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int tree_sibling_index(struct tree *tree) {
|
|
Packit Service |
a2ae7a |
struct tree *siblings = tree->parent->children;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int cnt = 0, ind = 0;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
list_for_each(t, siblings) {
|
|
Packit Service |
a2ae7a |
if (streqv(t->label, tree->label)) {
|
|
Packit Service |
a2ae7a |
cnt += 1;
|
|
Packit Service |
a2ae7a |
if (t == tree)
|
|
Packit Service |
a2ae7a |
ind = cnt;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (cnt > 1) {
|
|
Packit Service |
a2ae7a |
return ind;
|
|
Packit Service |
a2ae7a |
} else {
|
|
Packit Service |
a2ae7a |
return 0;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
char *path_expand(struct tree *tree, const char *ppath) {
|
|
Packit Service |
a2ae7a |
char *path;
|
|
Packit Service |
a2ae7a |
const char *label;
|
|
Packit Service |
a2ae7a |
char *escaped = NULL;
|
|
Packit Service |
a2ae7a |
int r;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int ind = tree_sibling_index(tree);
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (ppath == NULL)
|
|
Packit Service |
a2ae7a |
ppath = "";
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (tree->label == NULL)
|
|
Packit Service |
a2ae7a |
label = "(none)";
|
|
Packit Service |
a2ae7a |
else
|
|
Packit Service |
a2ae7a |
label = tree->label;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
r = pathx_escape_name(label, &escaped);
|
|
Packit Service |
a2ae7a |
if (r < 0)
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (escaped != NULL)
|
|
Packit Service |
a2ae7a |
label = escaped;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (ind > 0) {
|
|
Packit Service |
a2ae7a |
r = asprintf(&path, "%s/%s[%d]", ppath, label, ind);
|
|
Packit Service |
a2ae7a |
} else {
|
|
Packit Service |
a2ae7a |
r = asprintf(&path, "%s/%s", ppath, label);
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
free(escaped);
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (r == -1)
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
return path;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
char *path_of_tree(struct tree *tree) {
|
|
Packit Service |
a2ae7a |
int depth, i;
|
|
Packit Service |
a2ae7a |
struct tree *t, **anc;
|
|
Packit Service |
a2ae7a |
char *path = NULL;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
for (t = tree, depth = 1; ! ROOT_P(t); depth++, t = t->parent);
|
|
Packit Service |
a2ae7a |
if (ALLOC_N(anc, depth) < 0)
|
|
Packit Service |
a2ae7a |
return NULL;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
for (t = tree, i = depth - 1; i >= 0; i--, t = t->parent)
|
|
Packit Service |
a2ae7a |
anc[i] = t;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
for (i = 0; i < depth; i++) {
|
|
Packit Service |
a2ae7a |
char *p = path_expand(anc[i], path);
|
|
Packit Service |
a2ae7a |
free(path);
|
|
Packit Service |
a2ae7a |
path = p;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
FREE(anc);
|
|
Packit Service |
a2ae7a |
return path;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
/* User-facing path cleaning */
|
|
Packit Service |
a2ae7a |
static char *cleanstr(char *path, const char sep) {
|
|
Packit Service |
a2ae7a |
if (path == NULL || strlen(path) == 0)
|
|
Packit Service |
a2ae7a |
return path;
|
|
Packit Service |
a2ae7a |
char *e = path + strlen(path) - 1;
|
|
Packit Service |
a2ae7a |
while (e >= path && (*e == sep || isspace(*e)))
|
|
Packit Service |
a2ae7a |
*e-- = '\0';
|
|
Packit Service |
a2ae7a |
return path;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
char *cleanpath(char *path) {
|
|
Packit Service |
a2ae7a |
if (path == NULL || strlen(path) == 0)
|
|
Packit Service |
a2ae7a |
return path;
|
|
Packit Service |
a2ae7a |
if (STREQ(path, "/"))
|
|
Packit Service |
a2ae7a |
return path;
|
|
Packit Service |
a2ae7a |
return cleanstr(path, SEP);
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
const char *xstrerror(int errnum, char *buf, size_t len) {
|
|
Packit Service |
a2ae7a |
#ifdef HAVE_STRERROR_R
|
|
Packit Service |
a2ae7a |
# ifdef __USE_GNU
|
|
Packit Service |
a2ae7a |
/* Annoying linux specific API contract */
|
|
Packit Service |
a2ae7a |
return strerror_r(errnum, buf, len);
|
|
Packit Service |
a2ae7a |
# else
|
|
Packit Service |
a2ae7a |
strerror_r(errnum, buf, len);
|
|
Packit Service |
a2ae7a |
return buf;
|
|
Packit Service |
a2ae7a |
# endif
|
|
Packit Service |
a2ae7a |
#else
|
|
Packit Service |
a2ae7a |
int n = snprintf(buf, len, "errno=%d", errnum);
|
|
Packit Service |
a2ae7a |
return (0 < n && n < len
|
|
Packit Service |
a2ae7a |
? buf : "internal error: buffer too small in xstrerror");
|
|
Packit Service |
a2ae7a |
#endif
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
int xasprintf(char **strp, const char *format, ...) {
|
|
Packit Service |
a2ae7a |
va_list args;
|
|
Packit Service |
a2ae7a |
int result;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
va_start (args, format);
|
|
Packit Service |
a2ae7a |
result = vasprintf (strp, format, args);
|
|
Packit Service |
a2ae7a |
va_end (args);
|
|
Packit Service |
a2ae7a |
if (result < 0)
|
|
Packit Service |
a2ae7a |
*strp = NULL;
|
|
Packit Service |
a2ae7a |
return result;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
/* From libvirt's src/xen/block_stats.c */
|
|
Packit Service |
a2ae7a |
int xstrtoint64(char const *s, int base, int64_t *result) {
|
|
Packit Service |
a2ae7a |
long long int lli;
|
|
Packit Service |
a2ae7a |
char *p;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
errno = 0;
|
|
Packit Service |
a2ae7a |
lli = strtoll(s, &p, base);
|
|
Packit Service |
a2ae7a |
if (errno || !(*p == 0 || *p == '\n') || p == s || (int64_t) lli != lli)
|
|
Packit Service |
a2ae7a |
return -1;
|
|
Packit Service |
a2ae7a |
*result = lli;
|
|
Packit Service |
a2ae7a |
return 0;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
void calc_line_ofs(const char *text, size_t pos, size_t *line, size_t *ofs) {
|
|
Packit Service |
a2ae7a |
*line = 1;
|
|
Packit Service |
a2ae7a |
*ofs = 0;
|
|
Packit Service |
a2ae7a |
for (const char *t = text; t < text + pos; t++) {
|
|
Packit Service |
a2ae7a |
*ofs += 1;
|
|
Packit Service |
a2ae7a |
if (*t == '\n') {
|
|
Packit Service |
a2ae7a |
*ofs = 0;
|
|
Packit Service |
a2ae7a |
*line += 1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
#if HAVE_USELOCALE
|
|
Packit Service |
a2ae7a |
int regexp_c_locale(ATTRIBUTE_UNUSED char **u, ATTRIBUTE_UNUSED size_t *len) {
|
|
Packit Service |
a2ae7a |
/* On systems with uselocale, we are ok, since we make sure that we
|
|
Packit Service |
a2ae7a |
* switch to the "C" locale any time we enter through the public API
|
|
Packit Service |
a2ae7a |
*/
|
|
Packit Service |
a2ae7a |
return 0;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
#else
|
|
Packit Service |
a2ae7a |
int regexp_c_locale(char **u, size_t *len) {
|
|
Packit Service |
a2ae7a |
/* Without uselocale, we need to expand character ranges */
|
|
Packit Service |
a2ae7a |
int r;
|
|
Packit Service |
a2ae7a |
char *s = *u;
|
|
Packit Service |
a2ae7a |
size_t s_len, u_len;
|
|
Packit Service |
a2ae7a |
if (len == NULL) {
|
|
Packit Service |
a2ae7a |
len = &u_len;
|
|
Packit Service |
a2ae7a |
s_len = strlen(s);
|
|
Packit Service |
a2ae7a |
} else {
|
|
Packit Service |
a2ae7a |
s_len = *len;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
r = fa_expand_char_ranges(s, s_len, u, len);
|
|
Packit Service |
a2ae7a |
if (r != 0) {
|
|
Packit Service |
a2ae7a |
*u = s;
|
|
Packit Service |
a2ae7a |
*len = s_len;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
if (r < 0)
|
|
Packit Service |
a2ae7a |
return -1;
|
|
Packit Service |
a2ae7a |
/* Syntax errors will be caught when the result is compiled */
|
|
Packit Service |
a2ae7a |
if (r > 0)
|
|
Packit Service |
a2ae7a |
return 0;
|
|
Packit Service |
a2ae7a |
free(s);
|
|
Packit Service |
a2ae7a |
return 1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
#endif
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
#if ENABLE_DEBUG
|
|
Packit Service |
a2ae7a |
bool debugging(const char *category) {
|
|
Packit Service |
a2ae7a |
const char *debug = getenv("AUGEAS_DEBUG");
|
|
Packit Service |
a2ae7a |
const char *s;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
if (debug == NULL)
|
|
Packit Service |
a2ae7a |
return false;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
for (s = debug; s != NULL; ) {
|
|
Packit Service |
a2ae7a |
if (STREQLEN(s, category, strlen(category)))
|
|
Packit Service |
a2ae7a |
return true;
|
|
Packit Service |
a2ae7a |
s = strchr(s, ':');
|
|
Packit Service |
a2ae7a |
if (s != NULL)
|
|
Packit Service |
a2ae7a |
s+=1;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
return false;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
FILE *debug_fopen(const char *format, ...) {
|
|
Packit Service |
a2ae7a |
va_list ap;
|
|
Packit Service |
a2ae7a |
FILE *result = NULL;
|
|
Packit Service |
a2ae7a |
const char *dir;
|
|
Packit Service |
a2ae7a |
char *name = NULL, *path = NULL;
|
|
Packit Service |
a2ae7a |
int r;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
dir = getenv("AUGEAS_DEBUG_DIR");
|
|
Packit Service |
a2ae7a |
if (dir == NULL)
|
|
Packit Service |
a2ae7a |
goto error;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
va_start(ap, format);
|
|
Packit Service |
a2ae7a |
r = vasprintf(&name, format, ap);
|
|
Packit Service |
a2ae7a |
va_end(ap);
|
|
Packit Service |
a2ae7a |
if (r < 0)
|
|
Packit Service |
a2ae7a |
goto error;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
r = xasprintf(&path, "%s/%s", dir, name);
|
|
Packit Service |
a2ae7a |
if (r < 0)
|
|
Packit Service |
a2ae7a |
goto error;
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
result = fopen(path, "w");
|
|
Packit Service |
a2ae7a |
|
|
Packit Service |
a2ae7a |
error:
|
|
Packit Service |
a2ae7a |
free(name);
|
|
Packit Service |
a2ae7a |
free(path);
|
|
Packit Service |
a2ae7a |
return result;
|
|
Packit Service |
a2ae7a |
}
|
|
Packit Service |
a2ae7a |
#endif
|
|
Packit Service |
a2ae7a |
/*
|
|
Packit Service |
a2ae7a |
* Local variables:
|
|
Packit Service |
a2ae7a |
* indent-tabs-mode: nil
|
|
Packit Service |
a2ae7a |
* c-indent-level: 4
|
|
Packit Service |
a2ae7a |
* c-basic-offset: 4
|
|
Packit Service |
a2ae7a |
* tab-width: 4
|
|
Packit Service |
a2ae7a |
* End:
|
|
Packit Service |
a2ae7a |
*/
|