Rename setexec to chexec.
[utils/utils.git] / chexec
diff --git a/chexec b/chexec
new file mode 100755 (executable)
index 0000000..67ed861
--- /dev/null
+++ b/chexec
@@ -0,0 +1,43 @@
+#!/usr/bin/perl
+# chexec: turns a file's executability on or off, same semantics as rsync's --executability
+# usage: chexec { + | - | --reference=<file> } <file> [...]
+# Rename from setexec for consistency with chmod, etc. and cadaver's chexec - Matt 2009-07-02
+
+$cmd = $ARGV[0];
+shift @ARGV;
+
+if ($cmd =~ /^--reference=(.*)$/) {
+       $ref_file = $1;
+       @stbuf = stat($ref_file);
+       if (@stbuf == 0) {
+               die "chexec: stat($ref_file): $!\n";
+       }
+       $ref_perms = $stbuf[2] & 07777;
+       if (($ref_perms & 0111) == 0) {
+               $cmd = '-';
+       } else {
+               $cmd = '+';
+       }
+} elsif ($cmd ne '+' && $cmd ne '-') {
+       die "usage: chexec { + | - | --reference=<file> } <file> [...]\n";
+}
+
+sub docmd($$) {
+       my ($cmd, $perms) = @_;
+       if ($cmd eq '+') {
+               return $perms | ($perms & 0444) >> 2;
+       } elsif ($cmd eq '-') {
+               return $perms & ~0111;
+       }
+}
+
+file: foreach $file (@ARGV) {
+       @stbuf = stat($file);
+       if (@stbuf == 0) {
+               warn "chexec: stat($file): $!, skipping file\n";
+               next file;
+       }
+       $perms = $stbuf[2] & 07777;
+       $perms = docmd($cmd, $perms);
+       chmod($perms, $file) or warn "chexec: chmod($perms, $file): $!, skipping file\n";
+}