#!/usr/bin/perl

use strict;
use warnings;

use Fcntl qw(S_IFREG);
use File::Basename;
use File::Path;

use PVE::LXC::Tools;
use PVE::Tools qw(MS_BIND);

PVE::LXC::Tools::lxc_hook('autodev', 'lxc', sub {
    my ($vmid, $vars, undef, undef) = @_;

    my $root = $vars->{ROOTFS_MOUNT};

    PVE::LXC::Tools::for_current_passthrough_devices($vmid, sub {
	my ($type, $major, $minor, $dev) = @_;

	my $rel_devpath = "/dev/$dev";
	my $rel_dir = dirname($rel_devpath);
	File::Path::mkpath("$root/$rel_dir");
	PVE::Tools::mknod("$root/dev/$dev", S_IFREG, 0)
	    or die("Could not mknod $root/dev/$dev: $!\n");

	PVE::Tools::mount("/var/lib/lxc/$vmid/passthrough/dev/$dev", "$root/dev/$dev", 0, MS_BIND, 0)
	    or die("Bind mount of device $dev into container failed: $!\n");
    });

    PVE::LXC::Tools::for_current_passthrough_mounts($vmid, sub {
	my ($type, $major, $minor, $dev) = @_;

	my $rel_devpath = "/dev/$dev";
	my $rel_dir = dirname($rel_devpath);
	File::Path::mkpath("$root/$rel_dir");

	PVE::Tools::run_command(['mknod', '-m', '666', "$root/dev/$dev",
				 $type, $major, $minor]);

	if ($dev =~ /^dm-\d+$/) {
	    File::Path::mkpath("$root/dev/mapper");
	    my $mapped_name = PVE::Tools::file_get_contents("/sys/block/$dev/dm/name");
	    chomp $mapped_name;
	    symlink("/dev/$dev", "$root/dev/mapper/$mapped_name");
	}

	my $cgbase = "/sys/fs/cgroup/devices/lxc/$vmid";
	my $limitpath = "$cgbase/devices.allow";
	my $nspath = "$cgbase/ns/devices.allow";
	if (!PVE::LXC::Tools::cgroup_do_write($limitpath, "$type $major:$minor rwm")) {
	    warn "failed to allow access to device $dev ($major:$minor)\n";
	}
	if (!PVE::LXC::Tools::cgroup_do_write($nspath, "$type $major:$minor rwm")) {
	    warn "failed to allow access to device $dev ($major:$minor) inside the namespace\n";
	}
    });
});
