trim
extract_param
file_copy
+get_host_arch
O_PATH
O_TMPFILE
+AT_EMPTY_PATH
+AT_FDCWD
+CLONE_NEWNS
+CLONE_NEWUTS
+CLONE_NEWIPC
+CLONE_NEWUSER
+CLONE_NEWPID
+CLONE_NEWNET
);
my $pvelogdir = "/var/log/pve";
use constant {O_PATH => 0x00200000,
O_TMPFILE => 0x00410000}; # This includes O_DIRECTORY
+use constant {AT_EMPTY_PATH => 0x1000,
+ AT_FDCWD => -100};
+
sub run_with_timeout {
my ($timeout, $code, @param) = @_;
return next_unused_port(5900, 6000, $family, $address);
}
+sub spice_port_range {
+ return (61000, 61999);
+}
+
sub next_spice_port {
my ($family, $address) = @_;
- return next_unused_port(61000, 61099, $family, $address);
+ return next_unused_port(spice_port_range(), $family, $address);
}
sub must_stringify {
my $res = eval { run_fork_with_timeout($timeout, $df) } // {};
warn $@ if $@;
- # untaint the values
- my ($blocks, $used, $bavail) = map { defined($_) ? (/^(\d+)$/) : 0 }
+ # untaint, but be flexible: PB usage can result in scientific notation
+ my ($blocks, $used, $bavail) = map { defined($_) ? (/^([\d\.e\-+]+)$/) : 0 }
$res->@{qw(blocks used bavail)};
return {
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 {
return $line;
}
+my $host_arch;
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";
- }
+ $host_arch = (POSIX::uname())[4] if !$host_arch;
+ return $host_arch;
}
# Devices are: [ (12 bits minor) (12 bits major) (8 bits minor) ]
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;
+}
+
+sub open_tree($$$) {
+ my ($dfd, $pathname, $flags) = @_;
+ return PVE::Syscall::file_handle_result(syscall(
+ &PVE::Syscall::open_tree,
+ $dfd,
+ $pathname,
+ $flags,
+ ));
+}
+
+sub move_mount($$$$$) {
+ my ($from_dirfd, $from_pathname, $to_dirfd, $to_pathname, $flags) = @_;
+ return 0 == syscall(
+ &PVE::Syscall::move_mount,
+ $from_dirfd,
+ $from_pathname,
+ $to_dirfd,
+ $to_pathname,
+ $flags,
+ );
+}
+
+sub fsopen($$) {
+ my ($fsname, $flags) = @_;
+ return PVE::Syscall::file_handle_result(syscall(&PVE::Syscall::fsopen, $fsname, $flags));
+}
+
+sub fsmount($$$) {
+ my ($fd, $flags, $mount_attrs) = @_;
+ return PVE::Syscall::file_handle_result(syscall(
+ &PVE::Syscall::fsmount,
+ $fd,
+ $flags,
+ $mount_attrs,
+ ));
+}
+
+sub fspick($$$) {
+ my ($dirfd, $pathname, $flags) = @_;
+ return PVE::Syscall::file_handle_result(syscall(
+ &PVE::Syscall::fspick,
+ $dirfd,
+ $pathname,
+ $flags,
+ ));
+}
+
+sub fsconfig($$$$$) {
+ my ($fd, $command, $key, $value, $aux) = @_;
+ return 0 == syscall(&PVE::Syscall::fsconfig, $fd, $command, $key, $value, $aux);
+}
+
+# "raw" mount, old api, not for generic use (as it does not invoke any helpers).
+# use for lower level stuff such as bind/remount/... or simple tmpfs mounts
+sub mount($$$$$) {
+ my ($source, $target, $filesystemtype, $mountflags, $data) = @_;
+ return 0 == syscall(
+ &PVE::Syscall::mount,
+ $source,
+ $target,
+ $filesystemtype,
+ $mountflags,
+ $data,
+ );
+}
+
+sub safe_compare {
+ my ($left, $right, $cmp) = @_;
+
+ return 0 if !defined($left) && !defined($right);
+ return -1 if !defined($left);
+ return 1 if !defined($right);
+ return $cmp->($left, $right);
+}
+
1;