summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rwxr-xr-xetc/bash_completion.d/20vyatta-cfg20
-rwxr-xr-xlib/Vyatta/Config.pm42
-rwxr-xr-xlib/Vyatta/ConfigLoad.pm48
-rwxr-xr-xlib/Vyatta/ConfigOutput.pm133
-rw-r--r--scripts/vyatta-activate-config.pl107
-rwxr-xr-xscripts/vyatta-load-config.pl9
-rw-r--r--src/commit2.c78
-rw-r--r--src/common/defs.h7
-rw-r--r--src/common/unionfs.c49
-rw-r--r--src/common/unionfs.h1
11 files changed, 418 insertions, 77 deletions
diff --git a/Makefile.am b/Makefile.am
index f483abe..69c10c7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -50,6 +50,7 @@ sbin_SCRIPTS += scripts/vyatta-cli-expand-var.pl
sbin_SCRIPTS += scripts/vyatta-output-config.pl
sbin_SCRIPTS += scripts/vyatta-save-config.pl
sbin_SCRIPTS += scripts/vyatta-load-config.pl
+sbin_SCRIPTS += scripts/vyatta-activate-config.pl
sbin_SCRIPTS += scripts/vyatta-cfg-notify
sbin_SCRIPTS += scripts/vyatta-irqaffin
sbin_SCRIPTS += scripts/vyatta-auto-irqaffin.pl
diff --git a/etc/bash_completion.d/20vyatta-cfg b/etc/bash_completion.d/20vyatta-cfg
index 4463ee3..e17fd36 100755
--- a/etc/bash_completion.d/20vyatta-cfg
+++ b/etc/bash_completion.d/20vyatta-cfg
@@ -431,6 +431,18 @@ loadkey()
eval "${vyatta_sbindir}/vyatta-load-user-key.pl $@"
}
+activate()
+{
+ #create or remove activate file
+ eval "${vyatta_sbindir}/vyatta-activate-config.pl activate $@"
+}
+
+deactivate()
+{
+ #create or remove activate file
+ eval "${vyatta_sbindir}/vyatta-activate-config.pl deactivate $@"
+}
+
vyatta_loadkey_complete()
{
case "$COMP_CWORD" in
@@ -929,8 +941,10 @@ vyatta_config_complete ()
fi
if (( ${#COMP_WORDS[@]} < 2 )); then
- declare -a hitems=( "commit" \
+ declare -a hitems=( "activate" \
+ "commit" \
"copy" \
+ "deactivate" \
"delete" \
"discard" \
"edit" \
@@ -944,8 +958,10 @@ vyatta_config_complete ()
"set" \
"show" )
declare -a hstrs=( \
+ "Enable this portion of the configuration" \
"Commit the current set of changes" \
"Copy a configuration element" \
+ "Inactivate this portion of the configuration" \
"Delete a configuration element" \
"Discard uncommitted changes" \
"Edit a sub-element" \
@@ -1294,6 +1310,8 @@ complete -F vyatta_loadsave_complete save
complete -F vyatta_loadsave_complete load
complete -F vyatta_loadsave_complete merge
complete -F vyatta_loadkey_complete loadkey
+complete -F vyatta_config_complete activate
+complete -F vyatta_config_complete deactivate
complete -F vyatta_config_complete copy
complete -F vyatta_config_complete rename
diff --git a/lib/Vyatta/Config.pm b/lib/Vyatta/Config.pm
index 4ede95e..8de3aba 100755
--- a/lib/Vyatta/Config.pm
+++ b/lib/Vyatta/Config.pm
@@ -525,6 +525,48 @@ sub listDeleted {
return @deleted;
}
+## isDeactivated("node")
+# returns back whether this node is in an active (false) or
+# deactivated (true) state.
+sub getDeactivated {
+ my ($self, $node) = @_;
+
+ if (!defined $node) {
+ }
+
+ # let's setup the filepath for the change_dir
+ $node =~ s/\//%2F/g;
+ $node =~ s/\s+/\//g;
+ #now walk up parent in local and in active looking for '.disable' file
+
+ my @a = split(" ",$node);
+ $node = join("/",@a);
+
+ while (1) {
+ my $filepath = "$self->{_changes_only_dir_base}/$node";
+ my $filepathActive = "$self->{_active_dir_base}/$node";
+
+ my $local = $filepath . "/.disable";
+ my $active = $filepathActive . "/.disable";
+
+ if (-e $local && -e $active) {
+ return ("both",$node);
+ }
+ elsif (-e $local && !(-e $active)) {
+ return ("local",$node);
+ }
+ elsif (!(-e $local) && -e $active) {
+ return ("active",$node);
+ }
+ my $pos = rindex($node, "/");
+ if ($pos == -1) {
+ last;
+ }
+ $node = substr($node,0,$pos);
+ }
+ return (undef,undef);
+}
+
## isChanged("node")
# will check the change_dir to see if the "node" has been changed from a previous
# value. returns true or false.
diff --git a/lib/Vyatta/ConfigLoad.pm b/lib/Vyatta/ConfigLoad.pm
index 627b361..54befc6 100755
--- a/lib/Vyatta/ConfigLoad.pm
+++ b/lib/Vyatta/ConfigLoad.pm
@@ -86,7 +86,12 @@ sub enumerate_branch {
if (defined($val)) {
push @cur_path, $val;
}
- push @all_naked_nodes, [ @cur_path ];
+ if (defined $cur_node->{'disable'}) {
+ push @all_naked_nodes, [ '!', @cur_path ];
+ }
+ else {
+ push @all_naked_nodes, [ @cur_path ];
+ }
my @qpath = applySingleQuote(@cur_path);
push @all_nodes, [\@qpath, 0];
}
@@ -270,6 +275,7 @@ sub findDeletedNodes {
}
my @set_list = ();
+my @disable_list = ();
# find specified node's values in active config that are set
# (added or changed).
@@ -322,21 +328,33 @@ sub findSetNodes {
return;
}
foreach (sort keys %{$new_ref}) {
- if (scalar(keys %{$new_ref->{$_}}) == 0) {
- # we are at a non-value leaf node.
- # check if we need to add this node.
- if (!defined($active_hash{$_})) {
- my @plist = applySingleQuote(@active_path, $_);
- push @set_list, [\@plist, 0];
- } else {
- # node already present. do nothing.
+ if (scalar(keys %{$new_ref->{$_}}) == 0) {
+ # we are at a non-value leaf node.
+ # check if we need to add this node.
+ if (!defined($active_hash{$_})) {
+ my @plist = applySingleQuote(@active_path, $_);
+ if ($active_path[0] eq '!') {
+ my @tmp = @plist[1..$#plist];
+ push @disable_list, [\@tmp, 0];
+ push @set_list, [\@tmp, 0];
+ }
+ else {
+ push @set_list, [\@plist, 0];
+ }
+ } else {
+ # node already present. do nothing.
+ }
+ next;
}
- next;
- }
- # we recur regardless of whether it's in active. all changes will be
- # handled when we reach leaf nodes (above).
- findSetNodes($new_ref->{$_}, [ @active_path, $_ ]);
+ if ($active_path[0] eq '!') {
+ my @plist = applySingleQuote(@active_path, $_);
+ my @tmp = @plist[1..$#plist];
+ push @disable_list, [\@tmp, 0];
+ }
+ findSetNodes($new_ref->{$_}, [ @active_path, $_ ]);
}
+ # we recur regardless of whether it's in active. all changes will be
+ # handled when we reach leaf nodes (above).
}
# compare the current active config with the specified hierarchy and return
@@ -347,6 +365,7 @@ sub getConfigDiff {
$active_cfg = new Vyatta::Config;
$new_cfg_ref = shift;
@set_list = ();
+ @disable_list = ();
@delete_list = ();
findDeletedNodes($new_cfg_ref, [ ]);
findSetNodes($new_cfg_ref, [ ]);
@@ -369,6 +388,7 @@ sub getConfigDiff {
my %diff = (
'delete' => \@new_delete_list,
'set' => \@set_list,
+ 'deactivate' => \@disable_list,
);
return %diff;
}
diff --git a/lib/Vyatta/ConfigOutput.pm b/lib/Vyatta/ConfigOutput.pm
index fd30049..fd377d7 100755
--- a/lib/Vyatta/ConfigOutput.pm
+++ b/lib/Vyatta/ConfigOutput.pm
@@ -66,9 +66,10 @@ my $config = undef;
# deleted" from displayDeletedOrigChildren.)
sub displayValues {
my @cur_path = @{$_[0]};
- my $prefix = $_[1];
- my $name = $_[2];
- my $simple_show = $_[3];
+ my $dis = $_[1];
+ my $prefix = $_[2];
+ my $name = $_[3];
+ my $simple_show = $_[4];
my ($is_multi, $is_text, $default) = $config->parseTmpl(\@cur_path);
if ($is_text) {
$default =~ /^"(.*)"$/;
@@ -99,7 +100,7 @@ sub displayValues {
if ($is_password && $hide_password) {
$oval = $HIDE_PASSWORD;
}
- print "$prefix$name $oval\n";
+ print "$dis$prefix$name $oval\n";
}
return;
}
@@ -108,7 +109,7 @@ sub displayValues {
if ($is_password && $hide_password) {
$del = $HIDE_PASSWORD;
}
- print "-$prefix$name $del\n";
+ print "$dis-$prefix$name $del\n";
}
}
foreach my $nval (@nvals) {
@@ -123,7 +124,7 @@ sub displayValues {
if ($is_password && $hide_password) {
$nval = $HIDE_PASSWORD;
}
- print "$diff$prefix$name $nval\n";
+ print "$dis$diff$prefix$name $nval\n";
}
} else {
my $oval = $config->returnOrigValue('');
@@ -145,7 +146,7 @@ sub displayValues {
if ($is_password && $hide_password) {
$oval = $HIDE_PASSWORD;
}
- print "$prefix$name $oval\n";
+ print "$dis$prefix$name $oval\n";
}
return;
}
@@ -166,10 +167,10 @@ sub displayValues {
if ($is_password && $hide_password) {
$value = $HIDE_PASSWORD;
}
- print "$diff$prefix$name $value\n";
+ print "$dis$diff$prefix$name $value\n";
}
elsif ($cnodes{'def'} && ($diff eq '>' || $diff eq '-')) {
- print "$diff$prefix$name $value\n";
+ print "$dis$diff$prefix$name $value\n";
}
}
}
@@ -180,25 +181,40 @@ sub displayValues {
# deleted.)
sub displayDeletedOrigChildren {
my @cur_path = @{$_[0]};
- my $prefix = $_[1];
- my $dont_show_as_deleted = $_[2];
+ my $dis = $_[1];
+ my $prefix = $_[2];
+ my $dont_show_as_deleted = $_[3];
my $dprefix = '-';
if (defined($dont_show_as_deleted)) {
$dprefix = '';
}
$config->setLevel('');
+
my @children = $config->listOrigNodes(join ' ', @cur_path);
for my $child (sort @children) {
if ($child eq 'node.val') {
# should not happen!
next;
}
+
my $is_tag = $config->isTagNode([ @cur_path, $child ]);
+
+ if (!defined $is_tag) {
+ my $path = join(' ',( @cur_path, $child ));
+ my ($state, $n) = $config->getDeactivated($path);
+ if (defined $state) {
+ $dis = '! ';
+ }
+ else {
+ $dis = '';
+ }
+ }
+
$config->setLevel(join ' ', (@cur_path, $child));
my @cnames = sort $config->listOrigNodesNoDef();
if ($cnames[0] eq 'node.val') {
- displayValues([ @cur_path, $child ], $prefix, $child,
+ displayValues([ @cur_path, $child ], $dis, $prefix, $child,
$dont_show_as_deleted);
} elsif ($cnames[0] eq 'def') {
#ignore
@@ -210,21 +226,32 @@ sub displayDeletedOrigChildren {
# should not happen
next;
}
- print "$dprefix$prefix$child $cname {\n";
+
+ #need separate check here
+ my $path = join(' ',( @cur_path, $child, $cname ));
+ my ($state, $n) = $config->getDeactivated($path);
+ if (defined $state) {
+ $dis = '! ';
+ }
+ else {
+ $dis = '';
+ }
+
+ print "$dis$dprefix$prefix$child $cname {\n";
displayDeletedOrigChildren([ @cur_path, $child, $cname ],
- "$prefix ", $dont_show_as_deleted);
- print "$dprefix$prefix}\n";
+ $dis,"$prefix ", $dont_show_as_deleted);
+ print "$dis$dprefix$prefix}\n";
}
} else {
- print "$dprefix$prefix$child {\n";
- displayDeletedOrigChildren([ @cur_path, $child ], "$prefix ",
+ print "$dis$dprefix$prefix$child {\n";
+ displayDeletedOrigChildren([ @cur_path, $child ],$dis, "$prefix ",
$dont_show_as_deleted);
- print "$dprefix$prefix}\n";
+ print "$dis$dprefix$prefix}\n";
}
} else {
my $has_tmpl_children = $config->hasTmplChildren([ @cur_path, $child ]);
- print "$dprefix$prefix$child"
- . ($has_tmpl_children ? " {\n$dprefix$prefix}\n" : "\n");
+ print "$dis$dprefix$prefix$child"
+ . ($has_tmpl_children ? " {\n$dis$dprefix$prefix}\n" : "\n");
}
}
}
@@ -235,12 +262,18 @@ sub displayDeletedOrigChildren {
sub displayChildren {
my %child_hash = %{$_[0]};
my @cur_path = @{$_[1]};
- my $prefix = $_[2];
+ my $dis = $_[2];
+ my $prefix = $_[3];
for my $child (sort (keys %child_hash)) {
+ my $dis = "";
+ my @tmp = @cur_path;
+ push (@tmp,$child);
+
if ($child eq 'node.val') {
# should not happen!
next;
}
+
my ($diff, $vdiff) = (' ', ' ');
if ($child_hash{$child} eq 'added') {
$diff = '+';
@@ -252,6 +285,18 @@ sub displayChildren {
$vdiff = '>';
}
my $is_tag = $config->isTagNode([ @cur_path, $child ]);
+
+ if (!defined($is_tag)) {
+ my $path = join(' ',( @cur_path, $child ));
+ my ($state, $n) = $config->getDeactivated($path);
+ if (defined $state) {
+ $dis = '! ';
+ }
+ else {
+ $dis = '';
+ }
+ }
+
$config->setLevel(join ' ', (@cur_path, $child));
my %cnodes = $config->listNodeStatus();
my @cnames = sort keys %cnodes;
@@ -269,7 +314,7 @@ sub displayChildren {
}
if ($leaf == 1) {
- displayValues([ @cur_path, $child ], $prefix, $child);
+ displayValues([ @cur_path, $child ], $dis, $prefix, $child);
} elsif (scalar($#cnames) >= 0) {
if ($is_tag) {
@cnames = sort versioncmp @cnames;
@@ -278,50 +323,60 @@ sub displayChildren {
# should not happen
next;
}
+
+ my $path = join(' ',( @cur_path, $child, $cname ));
+ my ($state, $n) = $config->getDeactivated($path);
+ if (defined $state) {
+ $dis = '! ';
+ }
+ else {
+ $dis = '';
+ }
+
my $tdiff = ' ';
if ($cnodes{$cname} eq 'deleted') {
$tdiff = '-';
} elsif ($cnodes{$cname} eq 'added') {
$tdiff = '+';
}
- print "$tdiff$prefix$child $cname {\n";
+ print "$dis$tdiff$prefix$child $cname {\n";
if ($cnodes{$cname} eq 'deleted') {
displayDeletedOrigChildren([ @cur_path, $child, $cname ],
- "$prefix ");
+ $dis, "$prefix ");
} else {
$config->setLevel(join ' ', (@cur_path, $child, $cname));
my %ccnodes = $config->listNodeStatus();
displayChildren(\%ccnodes, [ @cur_path, $child, $cname ],
- "$prefix ");
+ $dis, "$prefix ");
}
- print "$tdiff$prefix}\n";
+ print "$dis$tdiff$prefix}\n";
}
} else {
- print "$diff$prefix$child {\n";
+ print "$dis$diff$prefix$child {\n";
if ($child_hash{$child} eq 'deleted') {
# this should not happen
- displayDeletedOrigChildren([ @cur_path, $child ], "$prefix ");
+ displayDeletedOrigChildren([ @cur_path, $child ], $dis, "$prefix ");
} else {
- displayChildren(\%cnodes, [ @cur_path, $child ], "$prefix ");
+ displayChildren(\%cnodes, [ @cur_path, $child ], $dis, "$prefix ");
}
- print "$diff$prefix}\n";
+ print "$dis$diff$prefix}\n";
}
} else {
if ($child_hash{$child} eq 'deleted') {
$config->setLevel('');
my @onodes = $config->listOrigNodes(join ' ', (@cur_path, $child));
if ($#onodes == 0 && $onodes[0] eq 'node.val') {
- displayValues([ @cur_path, $child ], $prefix, $child);
+ displayValues([ @cur_path, $child ], $dis, $prefix, $child);
} else {
- print "$diff$prefix$child {\n";
- displayDeletedOrigChildren([ @cur_path, $child ], "$prefix ");
- print "$diff$prefix}\n";
+ print "$dis$diff$prefix$child {\n";
+ displayDeletedOrigChildren([ @cur_path, $child ], $dis, "$prefix ");
+ print "$dis$diff$prefix}\n";
}
} else {
my $has_tmpl_children
= $config->hasTmplChildren([ @cur_path, $child ]);
- print "$diff$prefix$child"
- . ($has_tmpl_children ? " {\n$diff$prefix}\n" : "\n");
+ print "$dis$diff$prefix$child"
+ . ($has_tmpl_children ? " {\n$dis$diff$prefix}\n" : "\n");
}
}
}
@@ -350,9 +405,9 @@ sub outputNewConfig {
if ($leaf == 1) {
# this is a leaf value-node
- displayValues([ @_ ], '', $_[$#_]);
+ displayValues([ @_ ], '', '', $_[$#_]);
} else {
- displayChildren(\%rnodes, [ @_ ], '');
+ displayChildren(\%rnodes, [ @_ ], '', '');
}
} else {
if ($config->existsOrig() && ! $config->exists()) {
@@ -371,7 +426,7 @@ sub outputNewConfig {
sub outputActiveConfig {
$config = new Vyatta::Config;
$config->setLevel(join ' ', @_);
- displayDeletedOrigChildren([ @_ ], '', 1);
+ displayDeletedOrigChildren([ @_ ], '','', 1);
}
1;
diff --git a/scripts/vyatta-activate-config.pl b/scripts/vyatta-activate-config.pl
new file mode 100644
index 0000000..20f704d
--- /dev/null
+++ b/scripts/vyatta-activate-config.pl
@@ -0,0 +1,107 @@
+#!/usr/bin/perl
+
+# Author: Michael Larson <mike@vyatta.com>
+# Date: 2010
+# Description: Perl script for activating/deactivating portions of the configuration
+
+# **** 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.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008, 2009, 2010 Vyatta, Inc.
+# All Rights Reserved.
+# **** End License ****
+
+use strict;
+use warnings;
+use File::Find;
+use lib "/opt/vyatta/share/perl5";
+
+
+sub wanted {
+ return unless ( $_ eq '.disable' );
+ print("Cannot set nested deactivated nodes\n");
+ exit 1;
+}
+
+sub usage() {
+ print "Usage: $0 <path>\n";
+ exit 0;
+}
+
+#adjust for leaf node
+my $i = 0;
+my @path = @ARGV[1..$#ARGV];
+foreach my $elem (@path) {
+ $elem =~ s/\//%2F/g;
+ $elem =~ s/\s+/\//g;
+ $path[$i++] = $elem;
+}
+my $path = join '/', @path;
+
+my $full_path = "$ENV{VYATTA_TEMP_CONFIG_DIR}/$path";
+
+if (! -e $full_path) {
+ $path = join '/', @path[0..$#path-1];
+ my $leaf = "$ENV{VYATTA_TEMP_CONFIG_DIR}/$path/node.val";
+ if (-e $leaf) {
+ #prevent setting on leaf or multi, check for node.val
+# $full_path = "$ENV{VYATTA_TEMP_CONFIG_DIR}/$path";
+ printf("Cannot activate/deactivate end node\n");
+ exit 1;
+ }
+ else {
+ printf("This command is not valid: $path\n");
+ exit 1;
+ }
+}
+
+
+if ($ARGV[0] eq 'activate') {
+ $full_path .= "/.disable";
+ if (-e $full_path) {
+ `rm -f $full_path`;
+ }
+ else {
+ printf("This element is not deactivated.\n");
+ exit 1;
+ }
+}
+elsif ($ARGV[0] eq 'deactivate') {
+ #first let's check and ensure that there is not another child .disable node...
+ #also needs to be enforced when committing
+ my $active_dir = "$ENV{VYATTA_ACTIVE_CONFIGURATION_DIR}/$path";
+ my $local_dir = $full_path;
+ if (-e $active_dir) {
+ find( \&wanted, $active_dir );
+ }
+ if (-e $local_dir) {
+ find( \&wanted, $local_dir );
+ }
+ `touch $full_path/.disable`;
+}
+elsif ($ARGV[0] eq 'complete') {
+ #provide match...
+ printf("complete\n");
+}
+else {
+ printf("incoming arg: " . $ARGV[0] . "\n");
+ usage();
+}
+
+#if this is activate
+# make sure no activate subnodes
+# create .disable file in node
+#else
+# ensure .disable file exists
+# remove node
+
+print "Done\n";
+exit 0;
diff --git a/scripts/vyatta-load-config.pl b/scripts/vyatta-load-config.pl
index f0dbaf1..ab5a47e 100755
--- a/scripts/vyatta-load-config.pl
+++ b/scripts/vyatta-load-config.pl
@@ -190,6 +190,7 @@ if ( scalar( keys %cfg_hier ) == 0 ) {
my %cfg_diff = Vyatta::ConfigLoad::getConfigDiff( \%cfg_hier );
my @set_list = @{ $cfg_diff{'set'} };
+my @deactivate_list = @{ $cfg_diff{'deactivate'} };
if ($merge_mode eq 'false') {
my @delete_list = @{ $cfg_diff{'delete'} };
@@ -217,6 +218,14 @@ foreach (@set_list) {
}
}
+foreach (@deactivate_list) {
+ my ( $cmd_ref, $rank ) = @{$_};
+ my @cmd = ( "$sbindir/vyatta-activate-config.pl deactivate", @{$cmd_ref} );
+ my $cmd_str = join ' ', @cmd;
+ system("$cmd_str 1>/dev/null");
+ #ignore error on complaint re: nested nodes
+}
+
system("$sbindir/my_commit");
if ( $? >> 8 ) {
print "Load failed (commit failed)\n";
diff --git a/src/commit2.c b/src/commit2.c
index 3db695f..af01598 100644
--- a/src/commit2.c
+++ b/src/commit2.c
@@ -363,6 +363,7 @@ process_func(GNode *node, gpointer data)
gpointer gp = ((GNode*)node)->data;
struct Config *c = &((struct VyattaNode*)gp)->_config;
struct Data *d = &((struct VyattaNode*)gp)->_data;
+ NODE_OPERATION op = d->_operation;
int status = 0;
if (c->_def.actions &&
@@ -370,15 +371,32 @@ process_func(GNode *node, gpointer data)
if (g_debug) {
if (d->_name != NULL) {
- printf("commit2::process_func(), calling process on : %s for action %d, type: %d, operation: %d, path: %s\n",d->_name,result->_action,c->_def.def_type, d->_operation, d->_path);
- syslog(LOG_DEBUG,"commit2::process_func(), calling process on : %s for action %d, type: %d, operation: %d, path: %s",d->_name,result->_action,c->_def.def_type, d->_operation, d->_path);
+ printf("commit2::process_func(), calling process on : %s for action %d, type: %d, operation: %d, path: %s\n",d->_name,result->_action,c->_def.def_type, op, d->_path);
+ syslog(LOG_DEBUG,"commit2::process_func(), calling process on : %s for action %d, type: %d, operation: %d, path: %s",d->_name,result->_action,c->_def.def_type, op, d->_path);
}
else {
- printf("commit2::process_func(), calling process on : [n/a] for action %d, operation: %d, path: %s\n",result->_action, d->_operation, d->_path);
- syslog(LOG_DEBUG,"commit2::process_func(), calling process on : [n/a] for action %d, operation: %d, path: %s",result->_action, d->_operation, d->_path);
+ printf("commit2::process_func(), calling process on : [n/a] for action %d, operation: %d, path: %s\n",result->_action, op, d->_path);
+ syslog(LOG_DEBUG,"commit2::process_func(), calling process on : [n/a] for action %d, operation: %d, path: %s",result->_action, op, d->_path);
}
}
+ //FIRST LET'S COMPUTE THE DEACTIVATE->ACTIVATE OVERRIDE
+ if (d->_disable_op != K_NO_DISABLE_OP) {
+ if ((d->_disable_op & K_LOCAL_DISABLE_OP) && (d->_disable_op & K_ACTIVE_DISABLE_OP)) {
+ //no state change: deactivated
+ return FALSE; //skip operation on node
+ }
+ else if (!(d->_disable_op & K_LOCAL_DISABLE_OP) && (d->_disable_op & K_ACTIVE_DISABLE_OP)) {
+ //node will be activated on commit
+ //LET'S SPOOF the operation... convert it to CREATE
+ op = K_CREATE_OP;
+ }
+ else if ((d->_disable_op & K_LOCAL_DISABLE_OP) && !(d->_disable_op & K_ACTIVE_DISABLE_OP)) {
+ //node will be deactivated on commit
+ //LET'S SPOOF the operation... convert it to DELETE
+ op = K_DEL_OP;
+ }
+ }
/*
Needs to be cleaned up a bit such that this convoluted if clause is easier to read. Basically
is says:
@@ -388,15 +406,15 @@ process_func(GNode *node, gpointer data)
or
if a node is DELETE, is a DELETE ACTION or a END ACTION, or a BEGIN ACTION
*/
- if ((IS_SET(d->_operation) && !IS_ACTIVE(d->_operation) && (result->_action != delete_act && result->_action != create_act)) ||
- (IS_CREATE(d->_operation) && !IS_ACTIVE(d->_operation) && (result->_action == begin_act || result->_action == end_act || result->_action == create_act || (result->_action == update_act && !c->_def.actions[create_act].vtw_list_head))) ||
- (IS_ACTIVE(d->_operation) && ((result->_action == begin_act) || (result->_action == end_act))) ||
- (IS_DELETE(d->_operation) && ((result->_action == delete_act) || (result->_action == begin_act) || (result->_action == end_act)) )) {
+ if ((IS_SET(op) && !IS_ACTIVE(op) && (result->_action != delete_act && result->_action != create_act)) ||
+ (IS_CREATE(op) && !IS_ACTIVE(op) && (result->_action == begin_act || result->_action == end_act || result->_action == create_act || (result->_action == update_act && !c->_def.actions[create_act].vtw_list_head))) ||
+ (IS_ACTIVE(op) && ((result->_action == begin_act) || (result->_action == end_act))) ||
+ (IS_DELETE(op) && ((result->_action == delete_act) || (result->_action == begin_act) || (result->_action == end_act)) )) {
//NEED TO ADD IF CREATE, THEN CREATE OR UPDATE
//IF SET THEN UPDATE
//let's skip the case where this is active and it's a delete--shouldn't be done, but needs to be include in the rule set above
- if (IS_DELETE(d->_operation) && IS_ACTIVE(d->_operation) && result->_action == delete_act) {
+ if (IS_DELETE(op) && IS_ACTIVE(op) && result->_action == delete_act && d->_disable_op == K_NO_DISABLE_OP) { //only apply this when no disable operation is set
return FALSE;
}
@@ -475,8 +493,8 @@ process_func(GNode *node, gpointer data)
}
//do not set for promoted actions
- if (!IS_ACTIVE(d->_operation)) {
- if (IS_DELETE(d->_operation)) {
+ if (!IS_ACTIVE(op)) {
+ if (IS_DELETE(op)) {
setenv(ENV_ACTION_NAME,ENV_ACTION_DELETE,1);
}
else {
@@ -688,6 +706,7 @@ sort_func(GNode *node, gpointer data, boolean priority_mode)
//change action state of node according to enclosing behavior
if ((G_NODE_IS_ROOT(node) == FALSE) &&
+ (((struct VyattaNode*)gp)->_data._disable_op != K_NO_DISABLE_OP) || //added to support enclosing behavior of activated/deactivated nodes
((IS_SET_OR_CREATE(((struct VyattaNode*)gp)->_data._operation)) ||
(IS_DELETE(((struct VyattaNode*)gp)->_data._operation))) &&
(IS_NOOP(((struct VyattaNode*)(node->parent->data))->_data._operation))) {
@@ -713,7 +732,11 @@ sort_func(GNode *node, gpointer data, boolean priority_mode)
while (TRUE) {
n = n->parent;
vtw_def def = ((struct VyattaNode*)(n->data))->_config._def;
- ((struct VyattaNode*)(n->data))->_data._operation = ((struct VyattaNode*)gp)->_data._operation | K_ACTIVE_OP;
+ ((struct VyattaNode*)(n->data))->_data._operation = ((struct VyattaNode*)gp)->_data._operation;
+ //DON'T set active when only in disable state...
+ if (((struct VyattaNode*)gp)->_data._disable_op == K_NO_DISABLE_OP) {
+ ((struct VyattaNode*)(n->data))->_data._operation |= K_ACTIVE_OP;
+ }
if (def.actions[end_act].vtw_list_head || def.actions[begin_act].vtw_list_head) {
break;
}
@@ -890,21 +913,37 @@ dump_func(GNode *node, gpointer data)
if (((struct VyattaNode*)gp)->_data._name != NULL) {
int i;
+ char disable_op[2];
+ if (((struct VyattaNode*)gp)->_data._disable_op == (K_ACTIVE_DISABLE_OP | K_LOCAL_DISABLE_OP)) {
+ disable_op[0] = 'c';
+ }
+ else if (((struct VyattaNode*)gp)->_data._disable_op == K_ACTIVE_DISABLE_OP) {
+ disable_op[0] = 'u';
+ }
+ else if (((struct VyattaNode*)gp)->_data._disable_op == K_LOCAL_DISABLE_OP) {
+ disable_op[0] = 's';
+ }
+ else {
+ disable_op[0] = ' ';
+ }
+ disable_op[1] = '\0';
+
if (IS_ACTIVE(((struct VyattaNode*)gp)->_data._operation)) {
- fprintf(out,"*");
+ fprintf(out,"%s*",disable_op);
}
else if (IS_DELETE(((struct VyattaNode*)gp)->_data._operation)) {
- fprintf(out,"-");
+ fprintf(out,"%s-",disable_op);
}
else if (IS_CREATE(((struct VyattaNode*)gp)->_data._operation)) {
- fprintf(out,"+");
+ fprintf(out,"%s+",disable_op);
}
else if (IS_SET(((struct VyattaNode*)gp)->_data._operation)) {
- fprintf(out,">");
+ fprintf(out,"%s>",disable_op);
}
else {
- fprintf(out," ");
+ fprintf(out,"%s ",disable_op);
}
+
for (i = 0; i < depth; ++i) {
fprintf(out," ");
}
@@ -1171,6 +1210,11 @@ validate_func(GNode *node, gpointer data)
}
}
+ //don't perform validation checks on disabled nodes
+ if (d->_disable_op == K_LOCAL_DISABLE_OP) {
+ return FALSE; //SHOULD only hit the case where the node is locally disabled or globally disabled and not in a transition to active state
+ }
+
if (IS_DELETE(d->_operation) && !IS_ACTIVE(d->_operation)) {
return FALSE; //will not perform validation checks on deleted nodes
}
diff --git a/src/common/defs.h b/src/common/defs.h
index 6f97e9b..88b8441 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -35,6 +35,12 @@ typedef enum {
K_DEL_OP = 0x10
} NODE_OPERATION;
+typedef enum {
+ K_NO_DISABLE_OP = 0X00,
+ K_LOCAL_DISABLE_OP = 0x02, //MEANS DISABLE FLAG IS SET IN LOCAL CONFIGURATION
+ K_ACTIVE_DISABLE_OP = 0x04 //MEANS DISABLE FLAG IS SET IN ACTIVE CONFIGURATION
+} NODE_ACTIVATE;
+
#define IS_SET(op) (op & K_SET_OP)
#define IS_ACTIVE(op) (op & K_ACTIVE_OP)
#define IS_CREATE(op) (op & K_CREATE_OP)
@@ -72,6 +78,7 @@ struct Data
boolean _value; //is this a value?
char* _path;
NODE_OPERATION _operation; //no-op, set, or delete
+ NODE_ACTIVATE _disable_op; //is this node currently deactivated?
};
struct VyattaNode
diff --git a/src/common/unionfs.c b/src/common/unionfs.c
index 2be210e..151c6ce 100644
--- a/src/common/unionfs.c
+++ b/src/common/unionfs.c
@@ -189,6 +189,7 @@ retrieve_data(char* rel_data_path, GNode *node, char* root, NODE_OPERATION op)
vn->_data._name = cp;
vn->_data._value = FALSE;//TRUE; //data value
vn->_data._operation = op;
+ vn->_data._disable_op = K_NO_DISABLE_OP;
vn->_config._priority = LOWEST_PRIORITY;
vn->_data._path = malloc(MAX_LENGTH_DIR_PATH*sizeof(char));
sprintf(vn->_data._path,"%s",rel_data_path);
@@ -280,9 +281,7 @@ retrieve_data(char* rel_data_path, GNode *node, char* root, NODE_OPERATION op)
}
if (G_NODE_IS_ROOT(node) == FALSE) {
- struct VyattaNode* vn_parent = (struct VyattaNode*)node->parent->data;
struct VyattaNode* vn = (struct VyattaNode*)node->data;
- // vn->_config._priority = vn_parent->_config._def.def_priority;
if (vn->_config._def.tag && vn->_config._multi) {
vn->_config._priority = LOWEST_PRIORITY;
@@ -343,19 +342,49 @@ retrieve_data(char* rel_data_path, GNode *node, char* root, NODE_OPERATION op)
strcmp(dirp->d_name, "..") != 0 &&
strcmp(dirp->d_name, MODIFIED_FILE) != 0 &&
strcmp(dirp->d_name, DEF_FILE) != 0 &&
+ strcmp(dirp->d_name, DISABLE_FILE) != 0 &&
strcmp(dirp->d_name, WHITEOUT_FILE) != 0 &&
strcmp(dirp->d_name, VALUE_FILE) != 0) {
processed = TRUE;
+
+ NODE_ACTIVATE deactivated = K_NO_DISABLE_OP;
+ if (G_NODE_IS_ROOT(node) == FALSE && ((struct VyattaNode*)node->data)->_data._disable_op != K_NO_DISABLE_OP) {
+ deactivated = ((struct VyattaNode*)node->data)->_data._disable_op;
+ }
+ else { //do a lstat check in the local dir
+ struct stat s;
+ char buf[MAX_LENGTH_HELP_STR];
+ sprintf(buf,"%s/%s/%s/%s",get_mdirp(),rel_data_path,dirp->d_name,DISABLE_FILE);
+ if (lstat(buf,&s) == 0) {
+ //need to check existence of file in active configuration here as well!
+ deactivated |= K_LOCAL_DISABLE_OP;
+ }
+ sprintf(buf,"%s/%s/%s/%s",get_adirp(),rel_data_path,dirp->d_name,DISABLE_FILE);
+ if (lstat(buf,&s) == 0) {
+ deactivated |= K_ACTIVE_DISABLE_OP;
+ }
+ }
+
char *data_buf = malloc(MAX_LENGTH_DIR_PATH*sizeof(char));
- if (strncmp(dirp->d_name,DELETED_NODE,4) == 0) {
- strcpy(data_buf,dirp->d_name+4); //SKIP THE .WH.
+ if (strncmp(dirp->d_name,DELETED_NODE,4) == 0 ||
+ deactivated != K_NO_DISABLE_OP) {
+
+ struct VyattaNode *vn = calloc(1,sizeof(struct VyattaNode));
+
+ if (strncmp(dirp->d_name,DELETED_NODE,4) == 0) {
+ strcpy(data_buf,dirp->d_name+4); //SKIP THE .WH.
+ vn->_data._operation = K_DEL_OP;
+ }
+ else {
+ strcpy(data_buf,dirp->d_name);
+ vn->_data._operation = K_NO_OP;
+ }
//create new node and insert...
- struct VyattaNode *vn = calloc(1,sizeof(struct VyattaNode));
vn->_data._name = data_buf;
vn->_data._value = FALSE;
- vn->_data._operation = K_DEL_OP;
vn->_config._priority = LOWEST_PRIORITY;
+ vn->_data._disable_op = deactivated;
char new_data_path[MAX_LENGTH_DIR_PATH];
sprintf(new_data_path,"%s/%s",rel_data_path,data_buf);
@@ -374,6 +403,7 @@ retrieve_data(char* rel_data_path, GNode *node, char* root, NODE_OPERATION op)
vn->_data._name = data_buf;
vn->_data._value = FALSE;
vn->_config._priority = LOWEST_PRIORITY;
+ vn->_data._disable_op = deactivated;
char new_data_path[MAX_LENGTH_DIR_PATH];
sprintf(new_data_path,"%s/%s",rel_data_path,data_buf);
@@ -444,6 +474,7 @@ retrieve_data(char* rel_data_path, GNode *node, char* root, NODE_OPERATION op)
vn->_data._value = FALSE;
vn->_data._operation = K_DEL_OP;
vn->_config._priority = LOWEST_PRIORITY;
+ vn->_data._disable_op = K_NO_DISABLE_OP;
GNode *new_node = g_node_new(vn);
new_node = insert_sibling_in_order(node,new_node);
@@ -473,6 +504,7 @@ common_get_local_session_data()
struct VyattaNode *vn = calloc(1,sizeof(struct VyattaNode));
vn->_data._name = NULL; //root node has null
vn->_data._operation = K_NO_OP;
+ vn->_data._disable_op = K_NO_DISABLE_OP;
vn->_config._priority = LOWEST_PRIORITY;
//create first node
@@ -902,6 +934,7 @@ copy_vyatta_node(struct VyattaNode* vn)
strcpy(new_vn->_data._path,vn->_data._path);
}
new_vn->_data._operation = vn->_data._operation;
+ new_vn->_data._disable_op = vn->_data._disable_op;
new_vn->_config._multi = vn->_config._multi;
new_vn->_config._priority = vn->_config._priority;
new_vn->_config._priority_extended = vn->_config._priority_extended;
@@ -1070,6 +1103,10 @@ dlist_test_func(GQuark key_id,gpointer data,gpointer user_data)
strcpy(new_vn->_data._name,(char*)g_quark_to_string(key_id));
new_vn->_config._path = malloc(MAX_LENGTH_DIR_PATH*sizeof(char));
sprintf(new_vn->_config._path,"%s/node.tag",vn_parent->_config._path);
+
+ //let's set this nodes disable_op to its parent's value.
+ new_vn->_data._disable_op = vn_parent->_data._disable_op;
+
new_vn->_data._operation = ((struct ValueData*)data)->_state;
new_vn->_config._def = vn_parent->_config._def;
}
diff --git a/src/common/unionfs.h b/src/common/unionfs.h
index 098ac41..2933deb 100644
--- a/src/common/unionfs.h
+++ b/src/common/unionfs.h
@@ -23,6 +23,7 @@
#define NODE_TAG_FILE "node.tag"
#define VALUE_FILE "node.val"
#define MODIFIED_FILE ".modified"
+#define DISABLE_FILE ".disable"
#define DEF_FILE "def"
#define WHITEOUT_FILE ".wh.__dir_opaque"
#define DELETED_NODE ".wh."