Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

325 lines (258 sloc) 6.598 kB
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Cherokee
*
* Authors:
* Alvaro Lopez Ortega <alvaro@alobbs.com>
*
* Copyright (C) 2001-2011 Alvaro Lopez Ortega
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "common-internal.h"
#include "config_reader.h"
#include "util.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define ENTRIES "config"
static ret_t
do_parse_file (cherokee_config_node_t *conf, const char *file)
{
ret_t ret;
cherokee_buffer_t buf = CHEROKEE_BUF_INIT;
ret = cherokee_buffer_read_file (&buf, (char *)file);
if (ret != ret_ok) goto error;
ret = cherokee_config_reader_parse_string (conf, &buf);
if (ret != ret_ok) goto error;
cherokee_buffer_mrproper (&buf);
return ret_ok;
error:
cherokee_buffer_mrproper (&buf);
return ret_error;
}
static ret_t
do_include (cherokee_config_node_t *conf, cherokee_buffer_t *path)
{
int re;
struct stat info;
re = cherokee_stat (path->buf, &info);
if (re < 0) {
LOG_CRITICAL (CHEROKEE_ERROR_CONF_READ_ACCESS_FILE, path->buf);
return ret_error;
}
if (S_ISREG(info.st_mode)) {
return do_parse_file (conf, path->buf);
} else if (S_ISDIR(info.st_mode)) {
DIR *dir;
struct dirent *entry;
int entry_len;
dir = cherokee_opendir (path->buf);
if (dir == NULL) return ret_error;
while ((entry = readdir(dir)) != NULL) {
ret_t ret;
cherokee_buffer_t full_new = CHEROKEE_BUF_INIT;
/* Ignore backup files
*/
entry_len = strlen(entry->d_name);
if (unlikely (entry_len <= 0)) {
continue;
}
if ((entry->d_name[0] == '.') ||
(entry->d_name[0] == '#') ||
(entry->d_name[entry_len-1] == '~'))
{
continue;
}
ret = cherokee_buffer_add_va (&full_new, "%s/%s", path->buf, entry->d_name);
if (unlikely (ret != ret_ok)) {
cherokee_buffer_mrproper (&full_new);
return ret;
}
ret = do_parse_file (conf, full_new.buf);
if (unlikely (ret != ret_ok)) {
cherokee_buffer_mrproper (&full_new);
return ret;
}
cherokee_buffer_mrproper (&full_new);
}
cherokee_closedir (dir);
return ret_ok;
}
SHOULDNT_HAPPEN;
return ret_error;
}
static ret_t
check_config_node_sanity (cherokee_config_node_t *conf)
{
cherokee_list_t *i, *j;
int re;
/* Finds duplicate properties written in lower/upper-case
*/
cherokee_config_node_foreach (i, conf)
{
cherokee_config_node_foreach (j, conf)
{
if (i == j)
continue;
re = cherokee_buffer_case_cmp_buf (&CONFIG_NODE(i)->key,
&CONFIG_NODE(j)->key);
if (re == 0) {
LOG_ERROR (CHEROKEE_ERROR_CONF_READ_CHILDREN_SAME_NODE,
CONFIG_NODE(i)->key.buf, CONFIG_NODE(j)->key.buf);
return ret_error;
}
}
}
return ret_ok;
}
static int
cmp_num (cherokee_list_t *a, cherokee_list_t *b)
{
int an = strtol(CONFIG_NODE(a)->key.buf, NULL, 10);
int bn = strtol(CONFIG_NODE(b)->key.buf, NULL, 10);
if (an == bn) return 0;
if (an < bn) return bn - an;
return - (an - bn);
}
static ret_t
sort_lists (cherokee_config_node_t *conf)
{
int re;
ret_t ret;
cherokee_list_t *i;
cherokee_boolean_t all_num = true;
/* Are all numbers
*/
cherokee_config_node_foreach (i, conf) {
errno = 0;
re = strtol(CONFIG_NODE(i)->key.buf, NULL, 10);
if ((re == 0) && (errno = EINVAL)) {
all_num = false;
break;
}
}
/* Reorder entries
*/
if (all_num) {
cherokee_list_sort (&conf->child, cmp_num);
}
/* Iterate through the children
*/
cherokee_config_node_foreach (i, conf) {
ret = sort_lists (CONFIG_NODE(i));
if (ret != ret_ok) {
return ret;
}
}
return ret_ok;
}
ret_t
cherokee_config_reader_parse_string (cherokee_config_node_t *conf, cherokee_buffer_t *buf)
{
ret_t ret;
char *eol;
char *begin;
char *equal;
char *tmp;
char *eof;
cherokee_buffer_t key = CHEROKEE_BUF_INIT;
cherokee_buffer_t val = CHEROKEE_BUF_INIT;
eof = buf->buf + buf->len;
begin = buf->buf;
do {
/* Skip whites at the begining
*/
while ((begin < eof) &&
((*begin == ' ') || (*begin == '\t') ||
(*begin == '\r') || (*begin == '\n')))
{
begin++;
}
/* Look for the EOL
*/
eol = cherokee_min_str (strchr(begin, '\n'),
strchr(begin, '\r'));
if (eol == NULL) {
eol = eof;
}
/* Check that it's long enough
*/
if (eol - begin <= 4) {
goto next;
}
*eol = '\0';
/* Read the line
*/
if (*begin != '#') {
cuint_t val_len;
equal = strstr (begin, " = ");
if (equal == NULL) goto error;
tmp = equal;
/* Skip whites: end of the key
*/
while (*tmp == ' ')
tmp--;
cherokee_buffer_add (&key, begin, (tmp + 1) - begin);
tmp = equal + 3;
while (*tmp == ' ')
tmp++;
/* Skip whites: end of the value
*/
val_len = strlen(tmp);
while ((val_len >= 1) &&
(tmp[val_len-1] == ' '))
{
val_len--;
}
cherokee_buffer_add (&val, tmp, val_len);
TRACE(ENTRIES, "'%s' => '%s'\n", key.buf, val.buf);
ret = cherokee_config_node_add_buf (conf, &key, &val);
if (ret != ret_ok)
goto error;
}
/* Next loop
*/
next:
begin = eol + 1;
if (begin >= eof) {
break;
}
cherokee_buffer_clean (&key);
cherokee_buffer_clean (&val);
} while (eol != NULL);
cherokee_buffer_mrproper (&key);
cherokee_buffer_mrproper (&val);
/* Sort internal lists
*/
ret = sort_lists (conf);
if (ret != ret_ok)
return ret;
/* Sanity check
*/
ret = check_config_node_sanity (conf);
if (ret != ret_ok)
return ret;
return ret_ok;
error:
LOG_ERROR (CHEROKEE_ERROR_CONF_READ_PARSE, begin);
cherokee_buffer_mrproper (&key);
cherokee_buffer_mrproper (&val);
return ret_error;
}
ret_t
cherokee_config_reader_parse (cherokee_config_node_t *conf, cherokee_buffer_t *path)
{
return do_include (conf, path);
}
Jump to Line
Something went wrong with that request. Please try again.