summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Grennan <tgrennan@io.vyatta.com>2007-12-13 18:36:43 -0800
committerTom Grennan <tgrennan@io.vyatta.com>2007-12-13 18:36:43 -0800
commit8d6bac43ac6604b3c2a0ac9315a2e5c168299a5a (patch)
tree4764a95a26a97186c638b8c37ce5335d7df85b8e /src
parent9a781e1b6dbdba52ea430499d48730b6b311dd5c (diff)
parentfddadb2df7980fe86deabb0bfa27189d52479a0e (diff)
downloadvyatta-cfg-8d6bac43ac6604b3c2a0ac9315a2e5c168299a5a.tar.gz
vyatta-cfg-8d6bac43ac6604b3c2a0ac9315a2e5c168299a5a.zip
Merge branch 'master' of http://phuket.vyatta.com/vyatta-cfg
Diffstat (limited to 'src')
-rw-r--r--src/cli_new.c142
-rw-r--r--src/cli_objects.c2
-rw-r--r--src/cli_val.h1
-rw-r--r--src/commit.c24
4 files changed, 151 insertions, 18 deletions
diff --git a/src/cli_new.c b/src/cli_new.c
index bbdde10..3f64489 100644
--- a/src/cli_new.c
+++ b/src/cli_new.c
@@ -56,8 +56,13 @@ static int cond_format_lens[DOMAIN_TYPE] =
6 /* MACADDR_TYPE */
};
+struct __slist_t;
+
+typedef struct __slist_t {
+ struct __slist_t *next;
+} slist_t;
+
static int cli_val_len;
-static char *cli_val_alloc;
static char *cli_val_ptr;
static char *exe_string;
@@ -82,6 +87,8 @@ static void free_reuse_list(void);
void free_path(vtw_path *path);
static void free_string(char *str);
static vtw_node * get_node(void);
+void subtract_values(char **lhs, const char *rhs);
+
static void scan_ipv6(char *val, unsigned int *parts);
@@ -233,19 +240,44 @@ release_config_lock()
int
get_config_lock()
{
- int fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_EXCL, 0660);
- if (fd == -1) {
- return -1;
- }
- if (close(fd) == -1) {
- release_config_lock();
- return -1;
- }
- if (atexit(release_config_lock) != 0) {
+ int fd = -1;
+ FILE *lfile = NULL;
+ int ret = -1;
+
+ do {
+ /* create lock file */
+ fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_EXCL, 0660);
+ if (fd == -1) {
+ break;
+ }
+
+ /* write pid into lock file */
+ if ((lfile = fdopen(fd, "w")) == NULL) {
+ break;
+ }
+ if (fprintf(lfile, "%u", getpid()) < 0) {
+ break;
+ }
+ /* fclose also closes fd */
+ if (fclose(lfile) != 0) {
+ break;
+ }
+ /* clean up on exit */
+ if (atexit(release_config_lock) != 0) {
+ break;
+ }
+ ret = 0;
+ } while (0);
+
+ if (ret == -1) {
+ if (lfile) {
+ fclose(lfile);
+ } else if (fd != -1) {
+ close(fd);
+ }
release_config_lock();
- return -1;
}
- return 0;
+ return ret;
}
void internal_error(int line, char *file)
@@ -1515,7 +1547,6 @@ int get_value(char **valpp, vtw_path *pathp)
readcnt = fread(valp, 1, statbuf.st_size, in);
if (readcnt != statbuf.st_size) {
my_free(valp);
- cli_val_alloc = 0;
err = "Error reading value file in [%s]\n";
goto bad_path;
}
@@ -1781,6 +1812,91 @@ boolean validate_value(vtw_def *def, char *cp)
return ret;
}
+typedef struct __value_list {
+ slist_t link;
+ const char *value;
+} value_list;
+
+static void delete_list(slist_t *head)
+{
+ while (head != NULL) {
+ slist_t *elem = head;
+ head = head->next;
+ my_free(elem);
+ }
+}
+
+void subtract_values(char **lhs, const char *rhs)
+{
+ size_t length = 0;
+ const char *line = NULL;
+ char *rhs_copy = NULL, *res = NULL;
+ slist_t *head = NULL, *ptr = NULL;
+ slist_t *new_head = NULL, *new_ptr = NULL;
+
+ if (lhs == NULL || *lhs == NULL || **lhs == '\0' || rhs == NULL || *rhs == '\0')
+ return;
+
+ rhs_copy = my_malloc(strlen(rhs), "subtract_values rhs_copy");
+ strcpy(rhs_copy, rhs);
+
+ head = ptr = my_malloc(sizeof(slist_t), "subtract_values list1");
+ memset(head, 0, sizeof(slist_t));
+
+ line = strtok(rhs_copy, "\n\r");
+ while (line != NULL && *line != '\0') {
+ value_list *elem = NULL;
+
+ elem = (value_list *) my_malloc(sizeof(value_list), "subtract_values elem1");
+ memset(elem, 0, sizeof(value_list));
+ elem->value = line;
+ ptr->next = (slist_t *) elem;
+ ptr = ptr->next;
+ line = strtok(NULL, "\n\r");
+ }
+
+ new_head = new_ptr = my_malloc(sizeof(slist_t), "subtract_values list2");
+ memset(new_head, 0, sizeof(slist_t));
+
+ line = strtok(*lhs, "\n\r");
+ while (line != NULL && *line != '\0') {
+ value_list *elem = NULL;
+
+ ptr = head;
+ while (ptr->next != NULL) {
+ elem = (value_list *) ptr->next;
+ if (strncmp(line, elem->value, strlen(line)) == 0)
+ break;
+ ptr = ptr->next;
+ }
+ if (ptr->next == NULL) {
+ elem = (value_list *) my_malloc(sizeof(value_list), "subtract_values elem2");
+ memset(elem, 0, sizeof(value_list));
+ elem->value = line;
+ new_ptr->next = elem;
+ new_ptr = new_ptr->next;
+ length += strlen(line) + 1;
+ }
+ line = strtok(NULL, "\n\r");
+ }
+
+ new_ptr = new_head->next;
+ res = (char *) my_malloc(length + 1, "subtract_values result");
+ *res = '\0';
+ while (new_ptr != NULL) {
+ strcat(res, ((value_list *) new_ptr)->value);
+ strcat(res, "\n");
+ new_ptr = new_ptr->next;
+ }
+
+ delete_list(head);
+ delete_list(new_head);
+ if (rhs_copy != NULL)
+ my_free(rhs_copy);
+ my_free(*lhs);
+
+ *lhs = res;
+}
int cli_val_read(char *buf, int max_size)
{
diff --git a/src/cli_objects.c b/src/cli_objects.c
index 9bb36f0..8f0f6fe 100644
--- a/src/cli_objects.c
+++ b/src/cli_objects.c
@@ -334,7 +334,7 @@ void init_paths(boolean for_commit)
init_path(&m_path, startp);
switch_path(get_f_seg_c_ptr());
m_path.print_offset = max_len;
- }else
+ } else
init_path(&m_path, mdirp);
init_path(&t_path, tdirp);
diff --git a/src/cli_val.h b/src/cli_val.h
index 7383263..edbda41 100644
--- a/src/cli_val.h
+++ b/src/cli_val.h
@@ -171,6 +171,7 @@ extern void dump_tree(vtw_node *node, int lev);
extern void dump_def(vtw_def *defp);
extern boolean val_cmp(valstruct *left, valstruct *right, vtw_cond_e cond);
extern void out_of_memory(void);
+extern void subtract_values(char **lhs, const char *rhs);
extern boolean validate_value(vtw_def *def,
char *value);
extern void internal_error(int line, char *file);
diff --git a/src/commit.c b/src/commit.c
index d0d2517..b2e1c8a 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -91,7 +91,7 @@ static boolean validate_dir_for_commit()
def_present = TRUE;
memset(&def, 0, sizeof(def));
#ifdef DEBUG1
- printf("Parsing definition\n");
+ printf("Parsing definition %s\n", t_path.path);
#endif
if ((status = parse_def(&def, t_path.path,
@@ -102,7 +102,7 @@ static boolean validate_dir_for_commit()
}
#ifdef DEBUG1
else
- printf("No definition\n");
+ printf("No definition %s\n", t_path.path);
#endif
pop_path(&t_path); /* for PUSH 1 */
@@ -156,11 +156,27 @@ static boolean validate_dir_for_commit()
/* read it */
cp = NULL;
status = get_value(&cp, &m_path);
- if (status == VTWERR_OK){
+ if (status == VTWERR_OK) {
#ifdef DEBUG1
printf("Validating value |%s|\n"
"for path %s\n", cp, m_path.path);
#endif
+
+ // multivalue has to be diff-ed with the pre-existing value.
+ // only the difference should be ran through the validation.
+ // Bug #2509
+ if (def.multi) {
+ char *old_value = NULL;
+ switch_path(APATH); // temporarily switching to the active config path
+ status = get_value(&old_value, &m_path);
+ if (status == VTWERR_OK) {
+ subtract_values(&cp, old_value);
+ }
+ switch_path(CPATH);
+ if (old_value)
+ my_free(old_value);
+ }
+
status = validate_value(&def, cp);
ret = ret && status;
}
@@ -232,7 +248,7 @@ static boolean validate_dir_for_commit()
}
if (def_present && def.tag)
- pop_path(&t_path); /* for PUSH 3a */
+ pop_path(&t_path); /* for PUSH 2a */
if (def_present)
free_def(&def);
#ifdef DEBUG