Someone asked "Is there a shell script you can share that will set the permissions?" in an email without a subject today ;-)
Here's an example script, fixperms.tool, that sets permissions of source files before you build the installer. I pulled this from my daily installer build script, but I did test it as a stand-alone before posting. It's a bit of a mess, evolving as I get better at regular expressions, but has been working great for a long time.
The example sets the permissions for two relative paths -- One that would be installed to /Applications (only root:admin can write) and the other is a folder you want all users to be able to write to. NOTE: You can use relative paths like "../../../ApplcationBuilds/MyAppFolder".
Remember to chmod 755 fixperms.tool (so it runs) and run it with sudo or as root (or it cannot change some files perms).
It assumes that all executables start with one of the hex strings in the @EXECUTABLE_INDICATOR array (as you would see in a hex editor like 0xED).
If anyone else knows more executable hex strings or a better approach, please post a reply.
-Gary
---------------------------------------------------------------------------------------------------------- --------- SAVE THE FOLLOWING AS fixperms.tool ------------------------------------------------------------ #!/usr/bin/perl
$THIS_PROCESS_NAME = "FixPermissionsForInstallerBuild";
# Hex strings that start executables @EXECUTABLE_INDICATORS = ("23212F","4A6F7921","FEEDFACE","CAFEBABE"); # Convert to character strings foreach ( @EXECUTABLE_INDICATORS ) { s/([a-fA-F0-9]{2})/chr(hex $1)/eg; }
# determine dir script is in use FindBin qw($Bin);
chmodRecursivelyForPath_toAppMode_toFileMode_( "MyAppFolder", "0775", "0664" ); chmodRecursivelyForPath_toAppMode_toFileMode_( "MySharedDocFolder", "0777", "0666" );
exit 0;
############################################################ # # SUBROUTINES # ############################################################
sub isExecutableFile { local ( $filepath ) = @_; open CHECKFILE, $filepath; read CHECKFILE, $firstEightBytes, 8; close CHECKFILE; foreach ( @EXECUTABLE_INDICATOR_BYTES ) { if ( substr($firstEightBytes,0,length($_)) eq $_ ) { return 1; } } return 0; } sub chmodRecursivelyForPath_toAppMode_toFileMode_ { local ( $path, $exeMode, $fileMode ) = @_; local $isExecutable = 0; $path = cleanFilePath( $path ); if ( ! -e $path ) { if ( $path =~ m/Icon$/ ) { # apple puts \015 on pkg icon names that readdir drops $path .= chr(13); changePath_toMode( $path, $fileMode ); } else { output("WARNING: Cannot find file to chmod (".$path.")"); } } else { if ( -l $path ) { # LINK - Make executable $isExecutable = 1; #} elsif ( -p $path ) { # PIPE - Treat like file #} elsif ( -b $path ) { # BLOCK SPECIAL FILE - Treat like file #} elsif ( -c $path ) { # CHARACTER SPECIAL FILE - Treat like file #} elsif ( -S $path ) { # SOCKET - Treat like file } elsif ( -d $path ) { # DIRECTORY - Make executable and recurse $isExecutable = 1; opendir THISDIR, "$path" || output("ERROR: Could not read dir to chmod : ".$path); local @fileNames = readdir THISDIR; close THISDIR; local @sortedFileNames = sort { uc($a) cmp uc($b) } @fileNames; foreach ( @sortedFileNames ) { if ( $_ !~ /^\.{1,2}$/ ) { # Not a navigation file (. or ..) chmodRecursivelyForPath_toAppMode_toFileMode_( $path."/$_", $exeMode, $fileMode ); } } } else { $isExecutable = isExecutableFile($path); } if ( $isExecutable ) { changePath_toMode( $path, $exeMode ); } else { changePath_toMode( $path, $fileMode ); } } return 1; } sub changePath_toMode { local ( $path,$modeString ) = @_; local $mode = undef; if ( -e $path ) { $mode = oct($modeString); chmod $mode, $path; } else { output("ERROR: Path does not exist: ".$poth); } } sub cleanFilePath { local ( $path ) = @_; # convert to unix path $path =~ s|\\|/|g; # convert to absolute path if ( substr($path,0,2) eq "./" ) { # prefix with working dir $path = $Bin . substr($path,1); } elsif ( substr($path,0,3) eq "../" ) { # move up one dir for each "../" local @pathPrefix = split '/', $BaseDir; while ( substr($path,0,3) eq "../" ) { $path = substr($path,3); pop @pathPrefix; } $path = join('/',@pathPrefix) . "/" . $path; } elsif ( substr($path,0,1) ne "/" ) { # absolute paths should start with "/" $path = $Bin . "/" . $path; } # remove unwanted trailing chars local $lastChar = substr($path,length($path)-1); while ( ( $lastChar eq " " ) || ( $lastChar eq "\\" ) || ( $lastChar eq "/" ) || ( $lastChar eq "\r" ) || ( $lastChar eq "\n" ) ) { chop $path; $lastChar = substr($path,length($path)-1); } # return the cleansed return $path; } sub output { local $stop = 0; foreach ( @_ ) { print $THIS_PROCESS_NAME." - ".makeFileDate()." - ".$_."\n"; # Set stop if output line started with "FATAL ERROR" if ( m/^FATAL ERROR/ ) { $stop = 1; } } if ( $stop ) { print $THIS_PROCESS_NAME." - ".makeFileDate()." - Stopped for FATAL ERROR\n"; exit 1; } } sub makeFileDate { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year = $year + 1900; $mon = $mon + 1; return sprintf("u.u.u_uu", $year, $mon, $mday, $hour, $min); }
|