diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cli_new.c | 142 | ||||
-rw-r--r-- | src/cli_objects.c | 2 | ||||
-rw-r--r-- | src/cli_val.h | 1 | ||||
-rw-r--r-- | src/commit.c | 24 |
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 |