summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli_new.c134
-rw-r--r--src/commit.c4
-rw-r--r--src/delete.c4
3 files changed, 128 insertions, 14 deletions
diff --git a/src/cli_new.c b/src/cli_new.c
index d4380d5..b668e5b 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"
@@ -229,6 +231,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 +240,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()
{
- int fd = open(LOCK_FILE, O_WRONLY | O_CREAT | O_EXCL, 0660);
+ 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 = -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)
diff --git a/src/commit.c b/src/commit.c
index 24aff34..c3219e5 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -1338,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);
}