Code :

#!/usr/bin/perl # Allrights- A perl tool for making backups of file permissions # Copyright (C) 2005 Norbert Klein <norbert@acodedb.com> # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # 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. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Version 1.02 # Change log # From 1.01 to 1.02 # ----------------- # 2005-12-18 # Fixed: File names with only one character are ignored # From 1.0 to 1.01 # ---------------- # 2005-12-16 # Many thanks to Marc Mims who found and fixed 3 bugs: # Fixed: No support for file names with single quotes # Fixed: Misinterpretation of file names starting with dashes # Fixed: Restore crashes if executed on non-existing directories use strict; use warnings; use diagnostics; use Cwd; use File::Spec::Functions; my $error=""; my $startdir=""; if ($ARGV[0]){ #help text if argument is passed to script if ($ARGV[0] =~ /^(\?|help|-h|--help)$/) { print <<'END'; This script allows you to backup and restore file properties. It backups the permissions, owners and groups of all files and folders including all subfolders. IT DOES NOT BACKUP THE FILES AND FOLDERS THEMSELVES !!! Usage: ./allrights.pl [DIR | OPTION] Examples: ./allrights.pl ./allrights.pl --help ./allrights.pl /folder1/folder2 ./allrights.pl ./folder2 DIR: Directory were to start the backup (starting point of recursive descend) OPTIONS: ?, help, -help, --help will display this help text Without parameter the starting point for the backup will be the current working directory BACKUP ------ Run the script including the path to the directory you want to backup or run it inside this directory without paramters. Two executable files will be created within this folder: permissions_backup.sh ownergroup_backup.sh Both are simple shell scripts which do not need Perl and can be run independently. The program backups hidden files and hidden folders also. But note that symbolic links will be ignored. If a symbolic link points to a file outside of the saved directory tree, this file will remain unchanged too. If a user name or group name does not exist any more in /etc/passwd or /etc/group the uid or gid itself will be written into the backup files instead of the names. This happens if a group or user has been deleted, but files with these ids still exist. RESTORE ------- You can run the two backup scripts independently. If you want to restore permissions and owner/group just run both. In case you have removed some files since the last backup, the script output will show you which files couldn't be found. Author: norbert@acodedb.com Have fun ! END exit(); }else{ #if user passes relative path, change to absolute path if (substr($ARGV[0],0,1) eq "/"){ $startdir=$ARGV[0]; }else{ $startdir=cwd() . "/" . $ARGV[0]; $startdir =~ s|^//|/|; } } }else{ $startdir=cwd(); } #first line in every output shall be empty printf "

"; #check if folder passed by user exists if (!-e $startdir) { $error=" The folder $startdir does not exist"; &finish(); } #get content from /etc/passwd and /etc/group for uid/gid -> username/groupname translation my %unames=(); my %gnames=(); #the script will produce a correct backup, also if etc/passwd cannot be opened if (!open(FILE,"/etc/passwd")){ $error=" The file \"/etc/passwd\" could not be opened

"; $error.=" This means that your backup scripts (.sh) have been created with UIDs instead of names (just a matter of clearness)

"; $error.=" Your backup has been created successfully

"; $error.=" You can restore your permissions and owners/groups by running \"./permissions_backup.sh\" and/or \"./ownergroup_backup.sh\""; }else { my $uname=""; my $uid=""; while (<FILE>) { #skip comments if($_=~/^\s*#/){ next; } my @l=split(":",$_); $uname=$l[0]; $uid=$l[2]; $unames{$uid}=$uname; } } close(FILE); #the script will produce a correct backup, also if /etc/group cannot be opened if (!open(FILE,"/etc/group")){ $error=" The file \"/etc/group\" could not be opened

"; $error.=" This means that your backup scripts (.sh) have been created with GIDs instead of names (just a matter of clearness)

"; $error.=" Your backup has been created successfully

"; $error.=" You can restore your permissions and owners/groups by running \"./permissions_backup.sh\" and/or \"./ownergroup_backup.sh\""; }else { my $gname=""; my $gid=""; while (<FILE>) { #skip comments if($_=~/^\s*#/){ next; } my @l=split(":",$_); $gname=$l[0]; $gid=$l[2]; $gnames{$gid}=$gname; } } close(FILE); #check if backupfiles already exists if (-e "permissions_backup.sh"){ $error= " The backup file \"permissions_backup.sh\" already exists

"; $error.=" Please rename or remove it as previous backup files will not be overwritten"; &finish(); } if (-e "ownergroup_backup.sh"){ $error= " The backup file \"ownergroup_backup.sh\" already exists

"; $error.=" Please rename or remove it as previous backup files will not be overwritten"; &finish(); } printf " Preparing backup files \"permissions_backup.sh\" and \"ownergroup_backup.sh\"

"; system("touch permissions_backup.sh"); if (!open FILE, "+< permissions_backup.sh"){ $error= " The file \"permissions_backup.sh\" could not be opened"; &finish(); } seek FILE,0,0; #permission backup sub recdirs_p($); #prototype needed before print FILE "#!/bin/bash

"; print FILE "#THE RESTORATION OF PERMISSIONS STARTS HERE: $startdir

"; print FILE "#START > ---------------

"; print FILE "

echo

echo \" Restoring, this may take a while...\"

"; &recdirs_p($startdir,""); print FILE "

echo \" Completed\"

echo

"; print FILE "

#END < ---------------

"; #make executable bash script out of it system ("chmod 00711 permissions_backup.sh"); close (FILE); printf " Shell script \"permissions_backup.sh\" created

"; system("touch ownergroup_backup.sh"); if (!open FILE, "+< ownergroup_backup.sh"){ $error= " The file \"ownergroup_backup.sh\" could not be opened"; &finish(); } seek FILE,0,0; #owner, group backkup sub recdirs_og($); #prototype needed before print FILE "#!/bin/bash

"; print FILE "#THE RESTORATION OF OWNERS/GROUPS STARTS HERE: $startdir

"; print FILE "#START > ---------------

"; print FILE "

echo

echo \" Restoring, this may take a while...\"

"; &recdirs_og($startdir,""); print FILE "

echo \" Completed\"

echo

"; print FILE "

#END < ---------------

"; #make executable bash script out of it system ("chmod 00711 ownergroup_backup.sh"); close(FILE); printf " Shell script \"ownergroup_backup.sh\" created

"; &finish(); #functions ------------------------------------------------------------------------------------------------ sub finish(){ #error output if ($error ne "") { printf(" Error(s) occurred:

%s

",$error); }else{ printf " Backup completed



"; printf " You can restore your permissions and owners/groups by running \"./permissions_backup.sh\" and \"./ownergroup_backup.sh\"

"; } printf "

"; #cleanup exit(); } sub recdirs_p($){ my $path=$_[0]; if(opendir(DIR, $path)) { #get all objects besides . and .. my @obj=grep!/^\.$|^\.\.$/,readdir(DIR); #all my $mode=""; my $file=""; my $full_path=""; foreach(@obj){ $file=$path . "/" . $_; #ignore softlinks if (-l $file) { next; } $mode=(stat($file))[2]; $mode=sprintf("0%o ", $mode & 07777); #if necessary fill with leading zeros if (length($mode) < 5){ $mode = '0' x (5 - length($mode)) . $mode; } #support for file names with quotes $full_path = shell_escape(catfile($path, $_)); print FILE qq{chmod $mode -- "$full_path"

}; } #directories foreach(@obj) { #(-d "file") also recognizes symbolic links, if they point to a directory if((-d "$path/$_") && (!-l "$path/$_")) { &recdirs_p("$path/$_"); } } close DIR; } } sub recdirs_og($){ my $path=$_[0]; if(opendir(DIR, $path)) { my @obj=grep!/^\.$|^\.\.$/,readdir(DIR); my $uname=""; my $gname=""; my $file=""; my $full_path=""; foreach(@obj){ $file=$path . "/" . $_; if (-l $file) { next; } #get username/groupname for uid/gid. if username/groupname don't exist keep uid/gid if (!defined($uname=$unames{((stat($file))[4])})) { $uname=(stat($file))[4]; } if (!defined($gname=$gnames{((stat($file))[5])})) { $gname=(stat($file))[5]; } $full_path = shell_escape(catfile($path, $_)); print FILE qq{chown $uname:$gname -- "$full_path"

}; } foreach(@obj) { if((-d "$path/$_") && (!-l "$path/$_")) { &recdirs_og("$path/$_"); } } close DIR; } } sub shell_escape($){ my $string = $_[0]; $string =~ s/([\$"`\\])/\\$1/g; return $string; } # end of code ----------------------------------------------------------------------------------------------