summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2008-04-03 15:09:34 -0700
committerAn-Cheng Huang <ancheng@vyatta.com>2008-04-03 15:09:34 -0700
commit9158b59fd7cdd018a5c9b1e36c097b0436fd02a4 (patch)
treebc6a8afbe6e51d9f98825d2d02b677ad733c5c16 /src
parentbcdf7826a9e29cd48627ffb57b665fcad9a714fa (diff)
downloadvyatta-cfg-9158b59fd7cdd018a5c9b1e36c097b0436fd02a4.tar.gz
vyatta-cfg-9158b59fd7cdd018a5c9b1e36c097b0436fd02a4.zip
fix for bug 3097: correctly detect deleted tag
Diffstat (limited to 'src')
-rw-r--r--src/commit.c96
1 files changed, 88 insertions, 8 deletions
diff --git a/src/commit.c b/src/commit.c
index 6ed8632..534757c 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -972,6 +972,65 @@ get_filtered_directory_listing(DIR *dp, valstruct *mvals, vtw_type_e 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)
{
@@ -1013,32 +1072,53 @@ static boolean commit_delete_children(vtw_def *defp, boolean deleting,
memset(&valsM, 0, sizeof (valstruct));
memset(&cur_sorted, 0, sizeof(vtw_sorted));
+ /* changes directory */
get_filtered_directory_listing(dp, &mvals, type, 0);
if (closedir(dp) != 0) {
INTERNAL;
}
- if (adp) {
+
+ if (adp && mdp) {
+ /* active directory */
get_filtered_directory_listing(adp, &valsA, type, 0);
if (closedir(adp) != 0) {
INTERNAL;
}
- }
- if (mdp) {
+ /* 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);
+ }
+ }
+ }
+ free_val(&valsA);
+ }
+ if (valsM.free_me) {
+ free_val(&valsM);
+ }
}
if (!(mvals.free_me)) {
/* empty struct. nothing to do. */
return TRUE;
}
- /* XXX TODO */
- /* for each "node" in A but not in M
- * if ".wh.node" is not in mvals
- * add ".wh.node" to mvals
- */
vtw_sort(&mvals, &cur_sorted);
for (curi = 0; curi < cur_sorted.num && ok; ++curi){
if (type == TEXT_TYPE ||