#!/usr/bin/perl
# check_ogp.pl
# Checks the ownership, group, and permissions for all files and directories in
# a target directory against what you want them to be. You can use the default
# settings (useful for the collective) or enter your own. You can also have the
# changes made automatically or via prompting. Or, you can have no changes made
# but just get a report of what files and directories do not match what you want.
# Since the script can change ownership of files; you probably must be the root
# (superuser) to run it successfully.
# TODO: Add option allowing output to be echoed to a log file; this can help
# when generating a report on a directory with lots of files and directories
# in it.
use strict;
use File::Find;
if ( $^O eq "MSWin32" )
{
print "ERROR: Wrong operating system! \n"
. "This script must be run on a Linux box, but your OS says it is $^O. \n"
. "Bye!";
exit;
}
my $defDir = "/inetpub/www"; # Default target dir.
my $targetDir = ""; # Target dir (may differ from default).
my $defOwner = "collective"; # Default target owner.
my $targetOwner = ""; # Target owner (may differ from default).
my $targetUid; # UID of target owner.
my $defGroup = "inetadmin"; # Default target group.
my $targetGroup = ""; # Target group (may differ from default).
my $targetGid; # UID of target owner.
my $defPerm = sprintf "%04o", 0775; # Default permissions (775 saved as octal-looking string).
my $targetPerm = ""; # Target permissions (may differ from default).
my $useDefaults = 1; # 0 = get user input; 1 = use defaults.
my $appMode = 1; # 0 = make changes without prompting;
# 1 = prompt before making changes;
# 2 = make no changes; just report findings.
my @fileStat; # Holds list data returned by stat().
my $fileMode; # Mode (file type & permissions) of file/dir; $temp[2].
my $fileUid; # User ID (owner) of file/dir; $temp[4].
my $fileGid; # Group ID of file/dir; $temp[5].
my $fileOwner; # Owner (user name), looked up from $fileUid.
my $fileGroup; # Group, looked up from $fileGid.
my $filePerm; # File permissions, extracted from $fileMode; stored as string
# that looks like an octal number (easy for user to read).
my $prompt; # Hold user input from prompts.
my $curDir; # Current directory of finddepth().
my $errorCount;
# Find out what user wants to do.
print "*** Check/Change Ownership and Permissions of Files and Directories *** \n"
. "Default Settings: \n"
. " Starting Directory: $defDir \n"
. " Files/Dirs owner should be: $defOwner \n"
. " Files/Dirs group should be: $defGroup \n"
. " Files/Dirs permissions should be: $defPerm \n"
. " Prompt before making changes \n";
$errorCount = 0; # Count input errors; bail out if user can't get it right.
CheckUser();
print "\n";
# Now do it.
finddepth sub
{
return unless ( -f $_ or -d $_ ); # Skip everything except files and directories.
if ( $curDir ne $File::Find::dir )
{
$curDir = $File::Find::dir;
print "\nChecking $curDir... \n";
}
@fileStat = stat( "$_" );
$fileMode = $fileStat[2];
$fileUid = $fileStat[4];
$fileGid = $fileStat[5];
$fileOwner = getpwuid( "$fileUid" ); # Look up the owner's name.
$fileGroup = getgrgid( "$fileGid" ); # Look up the group's name.
$filePerm = sprintf "%04o", $fileMode & 07777; # Extract the permissions from the mode and save them
# in octal format. (Otherwise, they'll look odd.)
$prompt = ""; # Clear the prompt.
if ( "$fileOwner" ne "$targetOwner" or "$fileGroup" ne "$targetGroup" )
{
if ( $appMode == 2 )
{
print " $_ owner/group is $fileOwner/$fileGroup \n";
} elsif ( $appMode == 1 )
{
print " $_ owner/group is $fileOwner/$fileGroup. Change to $targetOwner/$targetGroup (y/any)? ";
$prompt = ;
chomp $prompt;
}
if ( $appMode == 0 or $prompt eq "y" )
{
chown( "$targetUid", "$targetGid", $_ );
print "$_ changed to $targetOwner/$targetGroup \n";
}
}
$prompt = ""; # Clear the prompt.
if ( "$filePerm" ne "$targetPerm" )
{
if ( $appMode == 2 )
{
print " $_ permissions are $filePerm \n";
} elsif ( $appMode == 1 )
{
print " $_ permissions are $filePerm. Change to $targetPerm (y/any)? ";
$prompt = ;
chomp $prompt;
}
if ( $appMode == 0 or $prompt eq "y" )
{
chmod( "$targetPerm", $_ );
print "$_ changed to $targetPerm \n";
}
}
}, $targetDir;
print "\n";
sub CheckUser
{
print "Use the default settings (y = yes; n = no; q = quit)? ";
$prompt = ;
chomp $prompt; # Lose line ending.
print "\n";
if ( $prompt eq "y" )
{
$targetDir = $defDir;
$targetOwner = $defOwner;
$targetGroup = $defGroup;
$targetPerm = $defPerm;
return;
} elsif ( $prompt eq "n" )
{
print "Enter information as requested; you can also enter d "
. "to use the default setting or q to quit \n";
GetDir();
GetOwner();
GetGroup();
GetPerm();
GetAppMode();
print "\n";
return;
} elsif ( $prompt eq "q" )
{
exit;
} else
{
$errorCount += 1;
if ( $errorCount > 3 )
{
print "Sorry, too many input errors. Bye! \n";
exit;
} else
{
CheckUser();
}
}
}
sub GetDir
{
print "Starting directory (default $defDir): ";
$prompt = ;
chomp $prompt; # Lose line ending.
if ( $prompt eq "d" )
{
$targetDir = $defDir;
return;
} elsif ( $prompt eq "q" )
{
exit;
} else
{
if ( -d $prompt )
{
$targetDir = $prompt;
return;
} else
{
$errorCount += 1;
print "ERROR: Could not find a directory named $prompt \n";
if ( $errorCount > 3 )
{
print "Sorry, too many input errors. Bye! \n";
exit;
} else
{
GetDir();
}
}
}
}
sub GetOwner
{
print "Owner (default $defOwner): ";
$prompt = ;
chomp $prompt; # Lose line ending.
if ( $prompt eq "d" )
{
$targetOwner = $defOwner;
return;
} elsif ( $prompt eq "q" )
{
exit;
} else
{
$targetUid = getgrnam( $prompt ); # Get UID for input name.
if ( $targetUid >= 0 )
{
$targetOwner = $prompt;
return;
} else
{
$errorCount += 1;
print "ERROR: Could not find a user ID for $prompt \n";
if ( $errorCount > 3 )
{
print "Sorry, too many input errors. Bye! \n";
exit;
} else
{
GetOwner();
}
}
}
}
sub GetGroup
{
print "Group (default $defGroup): ";
$prompt = ;
chomp $prompt; # Lose line ending.
if ( $prompt eq "d" )
{
$targetGroup = $defGroup;
return;
} elsif ( $prompt eq "q" )
{
exit;
} else
{
$targetGid = getgrnam( $prompt ); # Get GID for input name.
if ( $targetGid >= 0 )
{
$targetGroup = $prompt;
return;
} else
{
$errorCount += 1;
print "ERROR: Could not find a group ID for $prompt \n";
if ( $errorCount > 3 )
{
print "Sorry, too many input errors. Bye! \n";
exit;
} else
{
GetGroup();
}
}
}
}
sub GetPerm
{
my $errPerm = 0;
print "Permissions (enter with or without leading 0; default $defPerm): ";
$prompt = ;
chomp $prompt; # Lose line ending.
if ( $prompt eq "d" )
{
$targetPerm = $defPerm;
return;
} elsif ( $prompt eq "q" )
{
exit;
} elsif ( not $prompt =~ /^0/ )
{
$prompt = "0" . $prompt;
}
if ( length( $prompt ) == 4 )
{
my $temp = $prompt; # Store $prompt in a var that will be modified in error checking.
my $char = chop $temp; # This is $prompt's 4th character, which is the "Other" permissions.
$errPerm = 1 unless ( $char =~ /[0-7]/ );
$char = chop $temp; # This is $prompt's 3rd character, which is the "Group" permissions.
$errPerm = 1 unless ( $char =~ /[0-7]/ );
$char = chop $temp; # This is $prompt's 2nd character, which is the "Owner" permissions.
$errPerm = 1 unless ( $char =~ /[0-7]/ );
if ( $char == 0 )
{
print " WARNING: You want to set the owner's file permission to 0? This is very strange \n"
. " Are you sure you want to do this (y/any)? ";
my $reply = ;
chomp $reply;
unless ( $reply eq "y" )
{
print "Try again: \n";
GetPerm();
}
}
} else
{
$errPerm = 1; # $prompt incorrect length.
}
unless ( $errPerm == 1 )
{
$targetPerm = $prompt;
return;
} else
{
$errorCount += 1;
print "ERROR: Permissions as entered are incorrect in some way \n";
if ( $errorCount > 3 )
{
print "Sorry, too many input errors. Bye! \n";
exit;
} else
{
GetPerm();
}
}
}
sub GetAppMode
{
print "Application can: \n"
. " 0 Make changes automatically without prompting you \n"
. " 1 Prompt you whether or not make each change (default) \n"
. " 2 Just report which files do not match the settings (no changes made) \n"
. "Enter your choice (0, 1, 2, d, q )? ";
$prompt = ;
chomp $prompt; # Lose line ending.
if ( $prompt eq "d" or $prompt == 1 )
{
return;
} elsif ( $prompt == 0 )
{
$appMode = 0;
return;
} elsif ( $prompt == 2 )
{
$appMode = 2;
return;
} elsif ( $prompt eq "q" )
{
exit;
} else
{
$errorCount += 1;
print "ERROR: Incorrect input \n";
if ( $errorCount > 3 )
{
print "Sorry, too many input errors. Bye! \n";
exit;
} else
{
GetAppMode();
}
}
}