X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FTools.pm;h=550da09a609ddcf39f7999cc384bb312515192ed;hp=06da78be0d38a8ecc465d9a1363628b46e5cfb53;hb=6cf6b40469e5cbd63c04f075ce1399f3a1ad3574;hpb=2e353dfb5f734b14e4cda874ac796722d4bf0032 diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm index 06da78b..550da09 100644 --- a/src/PVE/Tools.pm +++ b/src/PVE/Tools.pm @@ -85,6 +85,8 @@ use constant {CLONE_NEWNS => 0x00020000, use constant {O_PATH => 0x00200000, O_TMPFILE => 0x00410000}; # This includes O_DIRECTORY +use constant {AT_EMPTY_PATH => 0x1000}; + sub run_with_timeout { my ($timeout, $code, @param) = @_; @@ -640,7 +642,7 @@ sub pipe_socket_to_command { } sub split_list { - my $listtxt = shift || ''; + my $listtxt = shift // ''; return split (/\0/, $listtxt) if $listtxt =~ m/\0/; @@ -670,7 +672,7 @@ sub template_replace { return $tmpl if !$tmpl; my $res = ''; - while ($tmpl =~ m/([^{]+)?({([^}]+)})?/g) { + while ($tmpl =~ m/([^{]+)?(\{([^}]+)\})?/g) { $res .= $1 if $1; $res .= ($data->{$3} || '-') if $2; } @@ -760,7 +762,7 @@ my $keymaphash = { 'pl' => ['Polish', 'pl', 'qwerty/pl.kmap.gz', 'pl', undef], 'pt' => ['Portuguese', 'pt', 'qwerty/pt-latin1.kmap.gz', 'pt', 'nodeadkeys'], 'pt-br' => ['Brazil-Portuguese', 'pt-br', 'qwerty/br-latin1.kmap.gz', 'br', 'nodeadkeys'], - #'ru' => ['Russian', 'ru', 'qwerty/ru.kmap.gz', 'ru', undef], # dont know? + #'ru' => ['Russian', 'ru', 'qwerty/ru.kmap.gz', 'ru', undef], # don't know? 'si' => ['Slovenian', 'sl', 'qwertz/slovene.kmap.gz', 'si', undef], 'se' => ['Swedish', 'sv', 'qwerty/se-latin1.kmap.gz', 'se', 'nodeadkeys'], #'th' => [], @@ -1384,6 +1386,11 @@ sub parse_host_and_port { return; # nothing } +sub setresuid($$$) { + my ($ruid, $euid, $suid) = @_; + return 0 == syscall(PVE::Syscall::setresuid, $ruid, $euid, $suid); +} + sub unshare($) { my ($flags) = @_; return 0 == syscall(PVE::Syscall::unshare, $flags); @@ -1399,6 +1406,11 @@ sub syncfs($) { return 0 == syscall(PVE::Syscall::syncfs, $fileno); } +sub fsync($) { + my ($fileno) = @_; + return 0 == syscall(PVE::Syscall::fsync, $fileno); +} + sub sync_mountpoint { my ($path) = @_; sysopen my $fd, $path, O_PATH or die "failed to open $path: $!\n"; @@ -1546,6 +1558,11 @@ sub mkdirat($$$) { return syscall(PVE::Syscall::mkdirat, $dirfd, $name, $mode) == 0; } +sub fchownat($$$$$) { + my ($dirfd, $pathname, $owner, $group, $flags) = @_; + return syscall(PVE::Syscall::fchownat, $dirfd, $pathname, $owner, $group, $flags) == 0; +} + my $salt_starter = time(); sub encrypt_pw { @@ -1613,4 +1630,69 @@ sub readline_nointr { return $line; } +sub get_host_arch { + + my @uname = POSIX::uname(); + my $machine = $uname[4]; + + if ($machine eq 'x86_64') { + return 'amd64'; + } elsif ($machine eq 'aarch64') { + return 'arm64'; + } else { + die "unsupported host architecture '$machine'\n"; + } +} + +# Devices are: [ (12 bits minor) (12 bits major) (8 bits minor) ] +sub dev_t_major($) { + my ($dev_t) = @_; + return (int($dev_t) & 0xfff00) >> 8; +} + +sub dev_t_minor($) { + my ($dev_t) = @_; + $dev_t = int($dev_t); + return (($dev_t >> 12) & 0xfff00) | ($dev_t & 0xff); +} + +# Given an array of array refs [ \[a b c], \[a b b], \[e b a] ] +# Returns the intersection of elements as a single array [a b] +sub array_intersect { + my ($arrays) = @_; + + if (!ref($arrays->[0])) { + $arrays = [ grep { ref($_) eq 'ARRAY' } @_ ]; + } + + return [] if scalar(@$arrays) == 0; + return $arrays->[0] if scalar(@$arrays) == 1; + + my $array_unique = sub { + my %seen = (); + return grep { ! $seen{ $_ }++ } @_; + }; + + # base idea is to get all unique members from the first array, then + # check the common elements with the next (uniquely made) one, only keep + # those. Repeat for every array and at the end we only have those left + # which exist in all arrays + my $return_arr = [ $array_unique->(@{$arrays->[0]}) ]; + for my $i (1 .. $#$arrays) { + my %count = (); + # $return_arr is already unique, explicit at before the loop, implicit below. + foreach my $element (@$return_arr, $array_unique->(@{$arrays->[$i]})) { + $count{$element}++; + } + $return_arr = []; + foreach my $element (keys %count) { + push @$return_arr, $element if $count{$element} > 1; + } + last if scalar(@$return_arr) == 0; # empty intersection, early exit + } + + return $return_arr; +} + + 1;