summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli_new.c214
-rw-r--r--src/commit.c14
-rw-r--r--src/delete.c4
3 files changed, 159 insertions, 73 deletions
diff --git a/src/cli_new.c b/src/cli_new.c
index d4380d5..e3a7955 100644
--- a/src/cli_new.c
+++ b/src/cli_new.c
@@ -14,6 +14,8 @@
#include "cli_val.h"
#include "cli_parse.h"
#include <regex.h>
+#include <errno.h>
+#include <time.h>
#include "cli_objects.h"
#include "cli_val_engine.h"
@@ -56,12 +58,6 @@ 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_ptr;
@@ -229,6 +225,7 @@ void di(vtw_sorted *srtp)
}
#define LOCK_FILE "/opt/vyatta/config/.lock"
+#define COMMIT_CMD "/opt/vyatta/sbin/my_commit"
static void
release_config_lock()
@@ -237,22 +234,133 @@ release_config_lock()
/* error ignored */
}
-int
-get_config_lock()
+/* try to clean up orphaned lock file. return -1 if failed */
+static int
+try_lock_cleanup()
+{
+ char buf[128];
+ char proc[128];
+ FILE *f = NULL;
+ int ret = -1;
+ struct stat statb;
+
+ do {
+ /* get the proc entry */
+ if ((f = fopen(LOCK_FILE, "r")) == NULL) {
+ break;
+ }
+ if (fgets(proc, 128, f) == NULL) {
+ break;
+ }
+ /* read the proc entry */
+ if (stat(proc, &statb) == -1) {
+ if (errno == ENOENT) {
+ /* proc entry doesn't exist. can clean up the lock now */
+ ret = 0;
+ break;
+ }
+ }
+ fclose(f);
+ if ((f = fopen(proc, "r")) == NULL) {
+ /* can't open proc entry. assume we can't clean up */
+ break;
+ }
+ if (fgets(buf, 128, f) == NULL) {
+ /* can't read proc entry. assume we can't clean up */
+ break;
+ }
+ /* check if the process is commit */
+ if (strcmp(buf, COMMIT_CMD) == 0) {
+ /* it is commit. can't clean up */
+ break;
+ }
+ /* can clean up the lock */
+ ret = 0;
+ } while (0);
+ if (f) {
+ fclose(f);
+ }
+ if (ret == 0) {
+ unlink(LOCK_FILE);
+ if (stat(LOCK_FILE, &statb) != -1 || errno != ENOENT) {
+ /* proc entry still exists. cleanup failed */
+ ret = -1;
+ }
+ }
+ return ret;
+}
+
+static int
+create_lock_file(int try_cleanup)
{
- int fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_EXCL, 0660);
+ int fd = -1;
+ int i = 0;
+ struct timespec req;
+
+#define LOCK_WAIT_TIME 2
+#define LOCK_NUM_RETRIES 5
+ req.tv_sec = LOCK_WAIT_TIME;
+ req.tv_nsec = 0;
+ fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_EXCL, 0660);
if (fd == -1) {
- return -1;
+ for (i = 0; i < LOCK_NUM_RETRIES; i++) {
+ nanosleep(&req, NULL);
+ fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_EXCL, 0660);
+ if (fd >= 0) {
+ break;
+ }
+ }
}
- if (close(fd) == -1) {
- release_config_lock();
- return -1;
+ if (fd == -1 && try_cleanup) {
+ if (try_lock_cleanup() != -1) {
+ /* cleanup succeeded */
+ fd = create_lock_file(0);
+ }
}
- if (atexit(release_config_lock) != 0) {
+ return fd;
+}
+
+int
+get_config_lock()
+{
+ int fd = -1;
+ FILE *lfile = NULL;
+ int ret = -1;
+
+ do {
+ /* create lock file */
+ fd = create_lock_file(1);
+ if (fd == -1) {
+ break;
+ }
+
+ /* write pid into lock file */
+ if ((lfile = fdopen(fd, "w")) == NULL) {
+ break;
+ }
+ if (fprintf(lfile, "/proc/%u/cmdline", 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)
@@ -1787,85 +1895,59 @@ 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;
+ size_t length = 0, lhs_cnt = 0, rhs_cnt = 0, i;
const char *line = NULL;
char *rhs_copy = NULL, *res = NULL;
- slist_t *head = NULL, *ptr = NULL;
- slist_t *new_head = NULL, *new_ptr = NULL;
+ const char **head = NULL, **ptr = NULL;
+ const char **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));
+ rhs_copy = strdup(rhs);
+ length = strlen(rhs) / 2;
+ head = ptr = my_malloc(length, "subtract_values list1");
+ memset(head, 0, length);
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;
+ *ptr = line;
+ ptr++;
+ rhs_cnt++;
line = strtok(NULL, "\n\r");
}
- new_head = new_ptr = my_malloc(sizeof(slist_t), "subtract_values list2");
- memset(new_head, 0, sizeof(slist_t));
+ length = strlen(*lhs) / 2;
+ new_head = new_ptr = my_malloc(length, "subtract_values list2");
+ memset(new_head, 0, length);
+ length = 0;
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)
+ for (i = 0; i < rhs_cnt; i++) {
+ if (strncmp(line, head[i], 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;
+ if (i >= rhs_cnt) {
+ *new_ptr = line;
length += strlen(line) + 1;
+ new_ptr++;
+ lhs_cnt++;
}
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);
+ for (i = 0; i < lhs_cnt; i++) {
+ strcat(res, new_head[i]);
strcat(res, "\n");
- new_ptr = new_ptr->next;
}
- delete_list(head);
- delete_list(new_head);
+ my_free(head);
+ my_free(new_head);
if (rhs_copy != NULL)
my_free(rhs_copy);
my_free(*lhs);
diff --git a/src/commit.c b/src/commit.c
index 400328e..c3219e5 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -157,6 +157,7 @@ static boolean validate_dir_for_commit()
cp = NULL;
status = get_value(&cp, &m_path);
if (status == VTWERR_OK) {
+ size_t value_size = 0;
#ifdef DEBUG1
printf("Validating value |%s|\n"
"for path %s\n", cp, m_path.path);
@@ -167,6 +168,7 @@ static boolean validate_dir_for_commit()
// Bug #2509
if (def.multi) {
char *old_value = NULL;
+ value_size = strlen(cp);
switch_path(APATH); // temporarily switching to the active config path
status = get_value(&old_value, &m_path);
if (status == VTWERR_OK) {
@@ -176,8 +178,10 @@ static boolean validate_dir_for_commit()
if (old_value)
my_free(old_value);
}
-
- status = validate_value(&def, cp);
+ if (strlen(cp) > 0 || value_size == 0)
+ status = validate_value(&def, cp);
+ else
+ status = TRUE;
ret = ret && status;
}
if (cp)
@@ -238,7 +242,7 @@ static boolean validate_dir_for_commit()
if (!def_present || !def.tag)
pop_path(&t_path); /* for PUSH 2b */
- }
+ } // while
status = closedir(dp);
if (status)
bye("Cannot close dir %s\n", m_path.path);
@@ -1334,8 +1338,8 @@ static int fin_commit(boolean ok)
static char format4[]="rm -rf %s/{.*,*} >&/dev/null ; /bin/true"; /*cdirp*/
static char format5[]="rm -rf %s/{.*,*} >&/dev/null ; /bin/true"; /*adirp*/
static char format6[]="mv -f %s/* -t %s";/*tmpp, adirp*/
- static char format7[]="sudo mount -t unionfs -o dirs=%s=rw:%s=ro"
- " unionfs %s"; /*cdirp, adirp, mdirp*/
+ static char format7[]="sudo mount -t $UNIONFS -o dirs=%s=rw:%s=ro"
+ " $UNIONFS %s"; /*cdirp, adirp, mdirp*/
int m_len = strlen(get_mdirp());
int t_len = strlen(get_tmpp());
int c_len = strlen(get_cdirp());
diff --git a/src/delete.c b/src/delete.c
index 1b7b62e..b62a697 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -28,8 +28,8 @@ static void remove_rf(boolean do_umount)
command = my_malloc(strlen(get_mdirp()) + strlen(get_cdirp()) +
strlen(get_mdirp()) + 100,
"delete");
- sprintf(command, "sudo mount -t unionfs -o dirs=%s=rw:%s=ro:"
- " unionfs %s", get_cdirp(), get_adirp(), get_mdirp());
+ sprintf(command, "sudo mount -t $UNIONFS -o dirs=%s=rw:%s=ro:"
+ " $UNIONFS %s", get_cdirp(), get_adirp(), get_mdirp());
system(command);
free(command);
}