1#!/usr/bin/perl 2 3# migrate old samba2 smb.conf settings to new samba3 setup 4# as well as merge local configuration settings 5# Dec 3 2003 Stew Benedict <sbenedict@mandrakesoft.com> 6# revised Jan 6 2004 - dropping some parameters 7# revised Feb 11 2004 - don't try to process a config a second time 8 9# check command line arguments 10my $numargs = @ARGV; 11if ($numargs lt 1) { 12 print "useage: smb-migrate test|test-commit|commit\n"; 13 exit(1); 14} 15 16# define some variables 17my $user_parms = 0; 18my $new_conf_file = "/etc/samba/smb.conf"; 19my @new_conf; 20my $merged_conf_file = "/etc/samba/smb.conf"; 21my $merge_comment = "# *** merged from original smb.conf: ***\n"; 22my $uncomment_comment = "# *** uncommented from original smb.conf: ***\n"; 23my $unique_comment = "# *** unique added from original smb.conf: ***\n"; 24my @merge_log; 25my $log_file = "/var/log/samba/smb-migrate.log"; 26my $to_merge = "/etc/samba/smb.conf.tomerge"; 27 28if ($ARGV[0] eq "test" || $ARGV[0] eq "test-commit") { 29 $to_merge = "smb.conf"; 30 $log_file = "smb-migrate.log"; 31 $merged_conf_file = "smb.conf.merged"; 32} 33 34# if the file has already been processed, don't do it again 35my $processed = `grep -c 'original smb.conf: ***' $to_merge`; 36if ($processed > 0) { 37 `cp $to_merge $new_conf_file`; 38 print "Already processed, aborting.\n"; 39 exit 0; 40} 41 42# get the stripped, uncommented data from old smb.conf 43my @old_conf = `grep -v "^#" $to_merge | grep -v "^;" | grep -v "^\$"` or die; 44 45# use a clean config file as a starting point 46`cp /usr/share/samba/smb.conf.clean $new_conf_file` if $ARGV[0] !~ /test/; 47 48# and the whole new conf file we're going to merge with 49my @new_conf_org = `cat $new_conf_file` or die; 50 51mlog("Data to change/add in standard sections of smb.conf:\n\n"); 52 53sub mlog { 54 my (@dstring) = @_; 55 if ($ARGV[0] eq "test") { 56 print "@dstring"; 57 } else { 58 push @merge_log, @dstring; 59 } 60} 61 62sub merge_conf { 63 my ($header, $new_value) = @_; 64 my @parmlist = split " = ", $new_value; 65 my $match = 0; 66 my $comment = ''; 67 $comment = $unique_comment if $continuation = 0; 68 $continuation = 1; 69 70 # find the header in question 71 $index = 0; 72 foreach (@new_conf_org) { 73 if (/^\[$header\]|;\[$header\]|^; \[$header\]|^\[$header\$\]|;\[$header\$\]|^; \[$header\$\]/) { 74 # restore print$ 75 $header = "print" . '$' if $header eq "print"; 76 # if the header is commented, remove the comment 77 if (/^;\[|^#\[|^; \[/) { 78 my $entry = $_; 79 @new_conf_org[$index] =~ s/^;|^; |^#//g; 80 mlog("uncomment: $header line $index: $entry -> @new_conf_org[$index]"); 81 splice(@new_conf_org, $index, 0, $uncomment_comment); 82 $index++ 83 } 84 $start_loc = $index; 85# print "[$header]: $start_loc\n"; 86 last; 87 } 88 $index++ 89 } 90 91 my $elements = @new_conf_org; 92 93 # walk through this header's entries, update as needed 94 for ($i = $start_loc + 1; $i < $elements; $i++) { 95 # if we hit a new header, may be commented - bail out 96 my $is_header = @new_conf_org[$i]; 97 $is_header =~ s/^ |\t|\n//; 98 if ($is_header =~ /^\[|;\[|#\[/) { 99# print "new header: $is_header at $i\n"; 100 if ($match == 0) { 101 # it's possible the parameter is continued across multiple lines 102 $continuation = 0 if $new_value !~ /\\$/; 103 # completely new entry, try to place it under the correct header 104# print "new entry for [$header]: $new_value\n"; 105 mlog("unique: $header line $last_index: $new_value"); 106 splice(@new_conf_org, $last_index + 1, 0, $comment, $new_value); 107 $last_index++;$last_index++; 108 } 109 return; 110 } 111 112 # some syntax changes 113 if ($new_value =~ /winbind/) { 114 $old_value = $new_value; 115 $new_value =~ s/winbind/idmap/; 116 mlog("syntax: $header: $old_value -> $new_value"); 117 } 118 119 # partial match, decide whether to add or replace 120 if (@new_conf_org[$i] =~ /@parmlist[0]/) { 121 if (@new_conf_org[$i] !~ /^;|^#/) { 122 if (@new_conf_org[$i] ne $_) { 123 mlog("update: $header line $i: @new_conf_org[$i] -> $new_value"); 124 @new_conf_org[$i] = ";" . $new_conf_org[$i]; 125 splice(@new_conf_org, $i + 1, 0, $merge_comment, $new_value); 126# $match = 1; 127 } 128 $match = 1; 129 } else { 130 # is it really a definition or just a comment? 131 if (@new_conf_org[$i] =~ / = /) { 132 # commented in new config, add the old entry 133 mlog("add: $header line $i: @new_conf_org[$i] -> $new_value"); 134 splice(@new_conf_org, $i + 1, 0, $merge_comment, $new_value); 135 $i++;$i++; 136 $match = 1; 137 } 138 } 139# $match = 1 if $new_value eq @new_conf_org[$i]; 140 $last_index = $i; 141 return if ($match eq 1); 142 $match = 0; 143 } 144 } 145 return; 146} 147 148foreach (@old_conf) { 149 # check for section headers 150 if (/^\[/) { 151 # standard headers? 152 if (!/^\[global\]|^\[homes\]|^\[netlogon\]|^\[Profiles\]|^\[printers\]|^\[print\$\]|^\[pdf-generator\]/) { 153 # non-standard - add to new config 154 $user_parms = 1; 155 push (@new_conf, $_); 156 } else { 157 $user_parms = 0; 158 chop; 159 $header = $_; 160 s/\[|\]|\$//g; 161 $bare_header = $_; 162 } 163 } else { 164 # non-standard - add to new config 165 if ($user_parms == 1) { 166 push (@new_conf, $_); 167 } else { 168 # now we're working with standard settings 169 # update new config with values if they differ or are commented out 170 # translate any old nomenclature to the new style 171 # may still be some commented lines buried 172 # throw those out and try to merge into new config 173 if (!/^[ ]+#|^[ ]+;|^#|^;/) { 174# print "$header: $_\n"; 175 merge_conf($bare_header, $_); 176 } 177 } 178 } 179} 180 181# write the user config data to new smb.conf 182 183mlog("\nNew data for smb.conf:\n\n"); 184mlog("@new_conf"); 185 186if ($ARGV[0] eq "commit" || $ARGV[0] eq "test-commit") { 187 local *NEWCONF; 188 open(NEWCONF, "> $merged_conf_file"); 189 print NEWCONF @new_conf_org; 190 print NEWCONF @new_conf; 191 close NEWCONF; 192 local *LOGFILE; 193 open(LOGFILE, "> $log_file"); 194 print LOGFILE @merge_log; 195 close LOGFILE 196} 197 198