# Copyright (C) all contributors # License: AGPL-3.0+ # base class to ensures Xapian||SQLite files respect core.sharedRepository # of git repos package PublicInbox::Umask; use v5.12; use PublicInbox::OnDestroy; use constant { PERM_UMASK => 0, OLD_PERM_GROUP => 1, OLD_PERM_EVERYBODY => 2, PERM_GROUP => 0660, PERM_EVERYBODY => 0664, }; sub _read_git_config_perm { my ($self) = @_; chomp(my $perm = $self->git->qx('config', 'core.sharedRepository')); $perm; } sub _git_config_perm { my $self = shift; my $perm = scalar @_ ? $_[0] : _read_git_config_perm($self); $perm //= ''; return PERM_UMASK if $perm eq '' || $perm eq 'umask'; return PERM_GROUP if $perm eq 'group'; return PERM_EVERYBODY if $perm =~ /\A(?:all|world|everybody)\z/; return PERM_GROUP if ($perm =~ /\A(?:true|yes|on|1)\z/); return PERM_UMASK if ($perm =~ /\A(?:false|no|off|0)\z/); my $i = oct($perm); return PERM_UMASK if $i == PERM_UMASK; return PERM_GROUP if $i == OLD_PERM_GROUP; return PERM_EVERYBODY if $i == OLD_PERM_EVERYBODY; if (($i & 0600) != 0600) { die "core.sharedRepository mode invalid: ". sprintf('%.3o', $i) . "\nOwner must have permissions\n"; } ($i & 0666); } sub _umask_for { my ($perm) = @_; # _git_config_perm return value my $rv = $perm; return umask if $rv == 0; # set +x bit if +r or +w were set $rv |= 0100 if ($rv & 0600); $rv |= 0010 if ($rv & 0060); $rv |= 0001 if ($rv & 0006); (~$rv & 0777); } sub with_umask { my ($self, $cb, @arg) = @_; my $old = umask($self->{umask} //= umask_prepare($self)); my $restore = on_destroy \&CORE::umask, $old; $cb ? $cb->(@arg) : $restore; } sub umask_prepare { my ($self) = @_; _umask_for(_git_config_perm($self)); } 1;