#!/usr/bin/perl -w use Getopt::Long; use lib "/opt/vyatta/share/perl5/"; use strict; use IO::Prompt; my ($show, $delete, $updateone); my @copy; my @update; GetOptions( "show=s" => \$show, "delete=s" => \$delete, "update=s{2}" => \@update, "updateone=s" => \$updateone, "copy=s{2}" => \@copy ); if (defined $show){ show($show); } if (defined $delete){ delete_file($delete); } if (@update){ update(@update); } if (defined($updateone)){ update($updateone, "running"); } if (@copy){ copy(@copy); } sub conv_file { my $file = " "; my $filein = pop(@_); $file = $filein; my $topdir; if ($file =~ /(.+?):\/\/(.*)/){ $topdir = $1; $file = $2; } elsif ($file =~ /^\//) { $topdir = "running"; } else { print "File: $filein not found \n"; exit 1; } if ($topdir eq "running") { $file = "/$file"; } elsif (lc($topdir) eq 'disk-install') { $file = "/lib/live/mount/persistence/$file"; } elsif (grep { lc($topdir) eq $_ } ("ftp", "tftp", "http", "https", "scp", "sftp")) { $file = $filein; $topdir = 'url'; } else { if (!-d "/lib/live/mount/persistence/boot/$topdir/rw"){ print "Image $topdir not found!\n"; exit 1; } $file = "/lib/live/mount/persistence/boot/$topdir/rw/$file"; } return ($topdir, $file); } sub conv_file_to_rel { my ($topdir, $filename) = @_; if ($topdir eq "running"){ $filename =~ s?/?$topdir://?; } elsif ($topdir eq "disk-install") { $filename =~ s?/lib/live/mount/persistence/?$topdir://?; } else { $filename =~ s?/lib/live/mount/persistence/boot/$topdir/rw/?$topdir://?; } return $filename; } sub delete_file { my ($file) = @_; (my $topdir, $file) = conv_file($file); if ($topdir eq 'url'){ print "Cannot delete files from a url\n"; exit 1; } if (-d $file){ my $print_dir = conv_file_to_rel($topdir,$file); if (y_or_n("Do you want to erase the entire $print_dir directory?")){ system("rm -rf $file"); print("Directory erased\n"); } } elsif (-f $file) { my $print_file = conv_file_to_rel($topdir,$file); if (y_or_n("Do you want to erase the $print_file file?")){ system("rm -rf $file"); print("File erased\n"); } } } sub url_copy { my ($from, $to) = @_; my ($f_topdir, $t_topdir); ($f_topdir, $from) = conv_file($from); ($t_topdir, $to) = conv_file($to); if ($t_topdir eq 'url' && $f_topdir eq 'url'){ print "Cannot copy a url to a url\n"; exit 1; } elsif($t_topdir eq 'url') { if (-d $from){ print "Cannot upload an entire directory to url\n"; exit 1; } elsif ($to =~ /http/){ print "Cannot upload to http url\n"; exit 1; } upload($from, $to); } elsif ($f_topdir eq 'url') { if (-d $to){ $from =~ /.*\/(.*)/; my $from_file = $1; $to = "$to/$from_file"; if (-f "$to") { if (!y_or_n("This file exists; overwrite if needed?")){ exit 0; } } } print "Downloading...\n"; download($from, $to); print "Download complete.\n"; } exit 0; } sub copy { my ($from, $to) = @_; my ($f_topdir, $t_topdir); ($f_topdir, $from) = conv_file($from); if ($f_topdir eq 'url'){ url_copy($from, $to); } ($t_topdir, $to) = conv_file($to); if ($t_topdir eq 'url'){ url_copy($from, $to); } $from =~ /.*\/(.*)/; my $from_file = $1; if (-d $from && -e $to && !(-d $to)){ print "Cannot copy a directory to a file.\n"; return 1; } elsif (-f $to || (-d $to && -f "$to/$from_file")) { if (y_or_n("This file exists; overwrite if needed?")){ rsync($from, $to); } } elsif (-d $to && -d $from){ if (y_or_n("This directory exists; would you like to merge?")){ rsync($from, $to); } } else { rsync($from, $to); } } sub update { my ($to, $from) = @_; my ($t_topdir, $f_topdir); ($f_topdir, $from) = conv_file("$from://"); if ($f_topdir eq 'url'){ print "Cannot clone from a url\n"; exit 1; } ($t_topdir, $to) = conv_file("$to://"); if ($t_topdir eq 'running'){ print "Cannot clone to running\n"; exit 1; } if ($t_topdir eq 'disk-install'){ print "Cannot clone to disk-install\n"; exit 1; } if ($t_topdir eq 'url'){ print "Cannot clone to a url\n"; exit 1; } my $print_from = conv_file_to_rel($f_topdir, $from); my $print_to = conv_file_to_rel($t_topdir, $to); my $msg = "WARNING: This is a destructive copy of the /config directories\n". "This will erase all data in the ".$print_to."config directory\n". "This data will be replaced with the data from ".$print_from."config\n". "The current config data will be backed up in ".$print_to."config.preclone\n". "Do you wish to continue?"; if (y_or_n("$msg")){ system("rm -rf $to/config.preclone"); system("mv $to/config $to/config.preclone") if (-d "$to/config"); my $confdir="config"; $confdir="opt/vyatta/etc/config" if ($f_topdir eq "disk-install"); if (rsync("$from/$confdir", $to) > 0){ print "Clone Failed!\nRestoring old config\n"; system("mv $to/config.preclone $to/config"); } } } sub rsync { my ($from,$to) = @_; system("rsync -a --progress --exclude '.wh.*' $from $to"); return $?; } sub upload { my ($from, $to) = @_; system("python3 -c 'from vyos.remote import upload; upload(\"$from\", \"$to\")'") } sub download { my ($from, $to) = @_; system("python3 -c 'from vyos.remote import download; download(\"$to\", \"$from\", progressbar=True, check_space=True)'"); } sub y_or_n { my ($msg) = @_; my $process_client = $ENV{'VYATTA_PROCESS_CLIENT'}; if (defined $process_client){ return 1 if ($process_client =~ /gui2_rest/); } print "$msg (Y/N): "; my $input = <>; return 1 if ($input =~ /Y|y/); return 0; } sub show { my ($topdir, $file) = conv_file(pop(@_)); my $output = ""; if ($topdir eq 'url'){ print "Cannot show files from a url\n"; exit 1; } if (-d $file) { print "########### DIRECTORY LISTING ###########\n"; system("ls -lGph --group-directories-first $file"); } elsif (-T $file) { print "########### FILE INFO ###########\n"; my $filename = conv_file_to_rel($topdir, $file); print "File Name: $filename\n"; print "Text File: \n"; my $lsstr = `ls -lGh $file`; parsels($lsstr); print " Description:\t"; system("file -sb $file"); print "\n########### FILE DATA ###########\n"; system("cat $file"); } elsif ($file =~ /.*\.pcap/){ print "########### FILE INFO ###########\n"; my $filename = conv_file_to_rel($topdir, $file); print "File Name: $filename\n"; print "Binary File: \n"; my $lsstr = `ls -lGh $file`; parsels($lsstr); print " Description:\t"; system("file -sb $file"); print "\n########### FILE DATA ###########\n"; system("sudo tshark -r $file | less"); } elsif (-B $file) { print "########### FILE INFO ###########\n"; my $filename = conv_file_to_rel($topdir, $file); print "File Name: $filename\n"; print "Binary File: \n"; my $lsstr = `ls -lGh $file`; parsels($lsstr); print " Description:\t"; system("file -sb $file"); print "\n########### FILE DATA ###########\n"; system("hexdump -C $file| less"); } else { my $filename = conv_file_to_rel($topdir, $file); print "File: $filename not found\n"; } } sub parsels { my $lsout = pop(@_); my @ls = split(' ', $lsout); print " Permissions: $ls[0]\n"; print " Owner:\t$ls[2]\n"; print " Size:\t\t$ls[3]\n"; print " Modified:\t$ls[4] $ls[5] $ls[6]\n"; }