summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli_path_utils.c26
-rw-r--r--src/cli_path_utils.h26
-rw-r--r--src/cli_val_engine.c26
-rw-r--r--src/cli_val_engine.h26
-rw-r--r--src/commit.c301
-rw-r--r--src/delete.c2
6 files changed, 261 insertions, 146 deletions
diff --git a/src/cli_path_utils.c b/src/cli_path_utils.c
index 84a2bc0..642b5ae 100644
--- a/src/cli_path_utils.c
+++ b/src/cli_path_utils.c
@@ -4,17 +4,21 @@
Module: cli
**** License ****
- Version: VPL 1.0
-
- The contents of this file are subject to the Vyatta Public License
- Version 1.0 ("License"); you may not use this file except in
- compliance with the License. You may obtain a copy of the License at
- http://www.vyatta.com/vpl
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 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.
+
+ A copy of the GNU General Public License is available as
+ `/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution
+ or on the World Wide Web at `http://www.gnu.org/copyleft/gpl.html'.
+ You can also obtain it by writing to the Free Software Foundation,
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ MA 02110-1301, USA.
This code was originally developed by Vyatta, Inc.
Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
diff --git a/src/cli_path_utils.h b/src/cli_path_utils.h
index 6cc3be8..6716b22 100644
--- a/src/cli_path_utils.h
+++ b/src/cli_path_utils.h
@@ -4,17 +4,21 @@
Module: cli
**** License ****
- Version: VPL 1.0
-
- The contents of this file are subject to the Vyatta Public License
- Version 1.0 ("License"); you may not use this file except in
- compliance with the License. You may obtain a copy of the License at
- http://www.vyatta.com/vpl
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 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.
+
+ A copy of the GNU General Public License is available as
+ `/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution
+ or on the World Wide Web at `http://www.gnu.org/copyleft/gpl.html'.
+ You can also obtain it by writing to the Free Software Foundation,
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ MA 02110-1301, USA.
This code was originally developed by Vyatta, Inc.
Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
diff --git a/src/cli_val_engine.c b/src/cli_val_engine.c
index 50a02df..adf40a4 100644
--- a/src/cli_val_engine.c
+++ b/src/cli_val_engine.c
@@ -4,17 +4,21 @@
Module: cli
**** License ****
- Version: VPL 1.0
-
- The contents of this file are subject to the Vyatta Public License
- Version 1.0 ("License"); you may not use this file except in
- compliance with the License. You may obtain a copy of the License at
- http://www.vyatta.com/vpl
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 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.
+
+ A copy of the GNU General Public License is available as
+ `/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution
+ or on the World Wide Web at `http://www.gnu.org/copyleft/gpl.html'.
+ You can also obtain it by writing to the Free Software Foundation,
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ MA 02110-1301, USA.
This code was originally developed by Vyatta, Inc.
Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
diff --git a/src/cli_val_engine.h b/src/cli_val_engine.h
index 0f32276..6315dac 100644
--- a/src/cli_val_engine.h
+++ b/src/cli_val_engine.h
@@ -4,17 +4,21 @@
Module: cli
**** License ****
- Version: VPL 1.0
-
- The contents of this file are subject to the Vyatta Public License
- Version 1.0 ("License"); you may not use this file except in
- compliance with the License. You may obtain a copy of the License at
- http://www.vyatta.com/vpl
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 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.
+
+ A copy of the GNU General Public License is available as
+ `/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution
+ or on the World Wide Web at `http://www.gnu.org/copyleft/gpl.html'.
+ You can also obtain it by writing to the Free Software Foundation,
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ MA 02110-1301, USA.
This code was originally developed by Vyatta, Inc.
Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
diff --git a/src/commit.c b/src/commit.c
index c3219e5..534757c 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -53,6 +53,23 @@ static void make_dir()
}
#endif
+static struct dirent *
+get_next_filtered_dirent(DIR *dp, int exclude_wh)
+{
+ struct dirent *dirp = NULL;
+ while ((dirp = readdir(dp)) != NULL) {
+ if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0
+ || strcmp(dirp->d_name, MOD_NAME) == 0
+ || strcmp(dirp->d_name, opaque_name) == 0
+ || (exclude_wh && strncmp(dirp->d_name, ".wh.", 4) == 0)) {
+ continue;
+ } else {
+ return dirp;
+ }
+ }
+ return dirp;
+}
+
/*************************************************
validate_dir_for_commit:
validate value.value if there is one, validate
@@ -114,16 +131,7 @@ static boolean validate_dir_for_commit()
push_path(&t_path, tag_name); /* PUSH 2a */
}
- while ((dirp = readdir(dp)) != NULL) {
-
- if (strcmp(dirp->d_name, ".") == 0 ||
- strcmp(dirp->d_name, "..") == 0 ||
- strcmp(dirp->d_name, MOD_NAME) == 0 ||
- strcmp(dirp->d_name, opaque_name) == 0 ||
- strncmp(dirp->d_name, ".wh.", 4) == 0) {
- continue; /*ignore dot and dot-dot*/
- }
-
+ while ((dirp = get_next_filtered_dirent(dp, 1)) != NULL) {
subdirs_number++;
if(uename)
@@ -747,17 +755,16 @@ static boolean commit_delete_child(vtw_def *pdefp, char *child,
mark_paths(&mark);
if (!deleting) {
int status;
- /* are we marked with opaque */
push_path(&m_path, child);
- push_path(&m_path, opaque_name);
+ switch_path(APATH); /* switch to active */
status = lstat(m_path.path, &statbuf);
+ switch_path(CPATH); /* back to changes */
pop_path(&m_path);
- pop_path(&m_path);
- if (status >= 0) {
- /* brand new directory, nothing is
- deleted there;
- update will handle txn (both begin and end)
- */
+ if (status < 0) {
+ /* node doesn't exist in active config. it's newly created
+ * so we don't need to handle delete. update will handle the
+ * transaction (if any).
+ */
return TRUE;
}
}
@@ -917,25 +924,141 @@ static boolean commit_delete_child(vtw_def *pdefp, char *child,
return ok;
}
+/* add a value to the valstruct. struct must be initialized (memset 0).
+ * cp: pointer to value
+ * type: type of value
+ */
+static void
+valstruct_append(valstruct *mvals, char *cp, vtw_type_e type)
+{
+ if (!(mvals->free_me)) {
+ /* empty struct. add 1st value */
+ mvals->free_me = TRUE;
+ mvals->val = cp;
+ mvals->val_type = type;
+ } else {
+ if ((mvals->cnt % MULTI_ALLOC) == 0) {
+ /* convert into multivalue */
+ mvals->vals = my_realloc(mvals->vals, (mvals->cnt + MULTI_ALLOC)
+ * sizeof(char *), "add_value");
+ if (mvals->cnt == 0) { /* single value - convert */
+ mvals->vals[0] = mvals->val;
+ mvals->cnt= 1;
+ mvals->val = NULL;
+ }
+ }
+ mvals->vals[mvals->cnt] = cp;
+ ++mvals->cnt;
+ }
+}
+
+/* get the filtered directory listing and put the names in valstruct.
+ * dp: target directory
+ * mvals: structure for storing the names
+ * type: type of the names
+ * exclude_wh: exclude whiteouts
+ */
+static void
+get_filtered_directory_listing(DIR *dp, valstruct *mvals, vtw_type_e type,
+ int exclude_wh)
+{
+ struct dirent *dirp = NULL;
+ char *cp = NULL;
+
+ memset(mvals, 0, sizeof (valstruct));
+ while ((dirp = get_next_filtered_dirent(dp, exclude_wh)) != NULL) {
+ cp = clind_unescape(dirp->d_name);
+ valstruct_append(mvals, cp, type);
+ }
+}
+
+/* check if a value is one of those in a valstruct.
+ * cp: pointer to value
+ * vals: pointer to valstruct
+ *
+ * return 1 if yes, 0 otherwise.
+ * TODO: optimization
+ */
+static int
+is_val_in_valstruct(char *cp, valstruct *vals)
+{
+ int i = 0;
+ if (!(vals->free_me)) {
+ /* empty struct. */
+ return 0;
+ }
+ if (vals->cnt == 0) {
+ /* single-value struct */
+ if (strcmp(cp, vals->val) == 0) {
+ return 1;
+ }
+ return 0;
+ }
+ /* multi-value */
+ for (i = 0; i < vals->cnt; i++) {
+ if (strcmp(cp, vals->vals[i]) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* returns the value at a particular index in a valstruct.
+ * vals: pointer to the valstruct
+ * idx: index of the value
+ *
+ * return pointer to the value, NULL if idx is not valid.
+ */
+static char *
+idx_val_in_valstruct(valstruct *vals, int idx)
+{
+ if (!(vals->free_me)) {
+ /* empty struct. */
+ return NULL;
+ }
+ if (vals->cnt == 0) {
+ /* single-value struct */
+ if (idx == 0) {
+ return vals->val;
+ }
+ return NULL;
+ }
+ /* multi-value */
+ if ((idx < 0) || (idx >= vals->cnt)) {
+ return NULL;
+ }
+ return vals->vals[idx];
+}
+
+
static boolean commit_delete_children(vtw_def *defp, boolean deleting,
boolean in_txn)
{
- DIR *dp;
- int status;
- struct dirent *dirp;
+ DIR *dp, *adp = NULL, *mdp = NULL;
boolean ok = TRUE;
char *child;
vtw_type_e type;
- valstruct mvals;
- boolean first;
- char *cp;
+ valstruct mvals, valsA, valsM;
int elem, curi;
vtw_sorted cur_sorted;
- char *uename = NULL;
+
+ if (!deleting) {
+ switch_path(APATH); /* switch to active */
+ if ((adp = opendir(m_path.path)) == NULL) {
+ INTERNAL;
+ }
+ switch_path(MPATH); /* switch to modified */
+ if ((mdp = opendir(m_path.path)) == NULL) {
+ INTERNAL;
+ }
+ switch_path(CPATH); /* back to changes */
+ }
if ((dp = opendir(m_path.path)) == NULL){
- if (deleting)
+ if (deleting) {
+ /* deleting. adp & mdp are not opened so no need to close. */
return TRUE;
+ }
INTERNAL;
}
if (defp)
@@ -944,44 +1067,56 @@ static boolean commit_delete_children(vtw_def *defp, boolean deleting,
type = TEXT_TYPE;
if (type == ERROR_TYPE)
type = TEXT_TYPE;
- first = TRUE;
memset(&mvals, 0, sizeof (valstruct));
+ memset(&valsA, 0, sizeof (valstruct));
+ memset(&valsM, 0, sizeof (valstruct));
memset(&cur_sorted, 0, sizeof(vtw_sorted));
- while ((dirp = readdir(dp)) != NULL) {
- child = dirp->d_name;
- if (strcmp(child, ".") == 0 ||
- strcmp(child, "..") == 0 ||
- strcmp(child, MOD_NAME) == 0 ||
- strcmp(child, OPQ_NAME) == 0)
- continue;
- uename = clind_unescape(child);
- cp = uename;
- if (first) {
- mvals.free_me = TRUE;
- mvals.val = cp;
- mvals.val_type = type;
- first = FALSE;
- } else {
- if (mvals.cnt%MULTI_ALLOC == 0) {
- /* convert into multivalue */
- mvals.vals = my_realloc(mvals.vals,
- (mvals.cnt + MULTI_ALLOC) *
- sizeof(char *), "add_value");
- if (mvals.cnt == 0) { /* single value - convert */
- mvals.vals[0] = mvals.val;
- mvals.cnt= 1;
- mvals.val = NULL;
- }
+ /* changes directory */
+ get_filtered_directory_listing(dp, &mvals, type, 0);
+ if (closedir(dp) != 0) {
+ INTERNAL;
+ }
+
+ if (adp && mdp) {
+ /* active directory */
+ get_filtered_directory_listing(adp, &valsA, type, 0);
+ if (closedir(adp) != 0) {
+ INTERNAL;
+ }
+ /* modified directory */
+ get_filtered_directory_listing(mdp, &valsM, type, 0);
+ if (closedir(mdp) != 0) {
+ INTERNAL;
+ }
+
+ if (valsA.free_me) {
+ /* A is not empty */
+ int idx = 0;
+ char *cp = NULL;
+ for (idx = 0; (cp = idx_val_in_valstruct(&valsA, idx)); idx++) {
+ if (!is_val_in_valstruct(cp, &valsM)) {
+ /* cp is in A but not in M */
+ /* construct whiteout name */
+ char *wh_name = my_malloc(strlen(cp) + 4 + 1, "del_children");
+ strcpy(wh_name, ".wh.");
+ strcpy(wh_name + 4, cp);
+ if (!is_val_in_valstruct(wh_name, &mvals)) {
+ /* whiteout not in C */
+ /* add whiteout to mvals */
+ valstruct_append(&mvals, wh_name, type);
+ }
+ }
}
- mvals.vals[mvals.cnt] = cp;
- ++mvals.cnt;
+ free_val(&valsA);
+ }
+ if (valsM.free_me) {
+ free_val(&valsM);
}
}
- status = closedir(dp);
- if (status)
- INTERNAL;
- if (first) {
+
+ if (!(mvals.free_me)) {
+ /* empty struct. nothing to do. */
return TRUE;
}
vtw_sort(&mvals, &cur_sorted);
@@ -1007,18 +1142,12 @@ static boolean commit_update_children(vtw_def *defp, boolean creating,
boolean in_txn, boolean *parent_update)
{
DIR *dp;
- int status;
- struct dirent *dirp;
boolean ok = TRUE;
char *child;
vtw_type_e type;
valstruct mvals;
- boolean first;
- char *cp;
int elem, curi;
vtw_sorted cur_sorted;
- char *uename = NULL;
-
if ((dp = opendir(m_path.path)) == NULL){
printf("%s:%d: opendir error: path=%s\n",
@@ -1034,43 +1163,14 @@ static boolean commit_update_children(vtw_def *defp, boolean creating,
type = TEXT_TYPE;
if (type == ERROR_TYPE)
type = TEXT_TYPE;
- first = TRUE;
- while ((dirp = readdir(dp)) != NULL) {
- child = dirp->d_name;
- if (strcmp(child, ".") == 0 ||
- strcmp(child, "..") == 0 ||
- strcmp(child, MOD_NAME) == 0 ||
- strcmp(child, OPQ_NAME) == 0)
- continue;
- cp = uename = clind_unescape(child);
- if (first) {
- mvals.free_me = TRUE;
- mvals.val = cp;
- mvals.val_type = type;
- first = FALSE;
- } else {
- if (mvals.cnt%MULTI_ALLOC == 0) {
- /* convert into multivalue */
- mvals.vals = my_realloc(mvals.vals,
- (mvals.cnt + MULTI_ALLOC) *
- sizeof(char *), "add_value");
- if (mvals.cnt == 0) { /* single value - convert */
- mvals.vals[0] = mvals.val;
- mvals.cnt= 1;
- mvals.val = NULL;
- }
- }
- mvals.vals[mvals.cnt] = cp;
- ++mvals.cnt;
- }
- }
- status = closedir(dp);
- if (status)
+ get_filtered_directory_listing(dp, &mvals, type, 0);
+ if (closedir(dp) != 0) {
INTERNAL;
- if (first) {
- if (uename)
- my_free(uename);
+ }
+
+ if (!(mvals.free_me)) {
+ /* empty struct. nothing to do. */
return TRUE;
}
vtw_sort(&mvals, &cur_sorted);
@@ -1165,7 +1265,6 @@ static boolean commit_value(vtw_def *defp, char *cp,
/* act_value will be freed by freeing cur_value
do not zero out it here */
}
-
acti = 0;
curi = 0;
total = act_sorted.num + cur_sorted.num;
@@ -1359,7 +1458,7 @@ static int fin_commit(boolean ok)
system(command);
my_free(command);
- command = my_malloc(strlen(format3) + c_len, "");
+ command = my_malloc(strlen(format3) + t_len, "");
sprintf(command, format3, get_tmpp());
system(command);
my_free(command);
diff --git a/src/delete.c b/src/delete.c
index b62a697..bb36fd1 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -28,7 +28,7 @@ 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:"
+ sprintf(command, "sudo mount -t $UNIONFS -o dirs=%s=rw:%s=ro"
" $UNIONFS %s", get_cdirp(), get_adirp(), get_mdirp());
system(command);
free(command);