if (my $fd2 = IO::File->new("/proc/net/dev", "r")) {
while (defined ($line = <$fd2>)) {
- if ($line =~ m/^\s*(eth[0-9]):.*/) {
+ if ($line =~ m/^\s*(eth\d+):.*/) {
$ifaces->{$1}->{exists} = 1;
}
}
close($fd2);
}
+ # we try to keep order inside the file
+ my $priority = 2; # 1 is reserved for lo
+
# always add the vmbr0 bridge device
$ifaces->{vmbr0}->{exists} = 1;
} elsif ($line =~ m/^iface\s+(\S+)\s+inet\s+(\S+)\s*$/) {
my $i = $1;
$ifaces->{$i}->{method} = $2;
+ $ifaces->{$i}->{priority} = $priority++;
my $d = $ifaces->{$i};
while (defined ($line = <$fh>)) {
- if ($line =~ m/^#(.*)\s*$/) {
- $d->{comment} = '' if !$d->{comment};
- $d->{comment} .= PVE::Tools::decode_text($1) . "\n";
+ if ($line =~ m/^\s*#(.*)\s*$/) {
+ # NOTE: we use 'comments' instead of 'comment' to
+ # avoid automatic utf8 conversion
+ $d->{comments} = '' if !$d->{comments};
+ $d->{comments} .= "$1\n";
} elsif ($line =~ m/^\s+((\S+)\s+(.+))$/) {
my $option = $1;
my ($id, $value) = ($2, $3);
}
if (!$ifaces->{lo}) {
+ $ifaces->{lo}->{priority} = 1;
$ifaces->{lo}->{method} = 'loopback';
$ifaces->{lo}->{type} = 'loopback';
$ifaces->{lo}->{autostart} = 1;
$ifaces->{$1}->{exists} = 0;
$d->{exists} = 0;
}
- } elsif ($iface =~ m/^eth[0-9]$/) {
+ } elsif ($iface =~ m/^eth\d+$/) {
$d->{type} = 'eth';
} elsif ($iface =~ m/^lo$/) {
$d->{type} = 'loopback';
$raw .= "\t$option\n";
}
- # add comments
- my $comment = $d->{comment} || '';
- foreach my $cl (split(/\n/, $comment)) {
- $raw .= '#' . PVE::Tools::encode_text($cl) . "\n";
+ # add comments
+ my $comments = $d->{comments} || '';
+ foreach my $cl (split(/\n/, $comments)) {
+ $raw .= "#$cl\n";
}
$raw .= "\n";
my $printed = {};
- foreach my $t (('lo', 'eth', '')) {
- foreach my $iface (sort keys %$ifaces) {
- my $d = $ifaces->{$iface};
+ my $if_type_hash = {
+ loopback => 10,
+ eth => 20,
+ bond => 30,
+ bridge => 40,
+ };
+
+ my $lookup_type_prio = sub {
+ my $iface = shift;
- next if $printed->{$iface};
- next if $iface !~ m/^$t/;
+ my $alias = 0;
+ if ($iface =~ m/^(\S+):\d+$/) {
+ $iface = $1;
+ $alias = 1;
+ }
- $printed->{$iface} = 1;
- $raw .= __interface_to_string($iface, $d);
+ my $pri;
+ if ($iface eq 'lo') {
+ $pri = $if_type_hash->{loopback};
+ } elsif ($iface =~ m/^eth\d+$/) {
+ $pri = $if_type_hash->{eth} + $alias;
+ } elsif ($iface =~ m/^bond\d+$/) {
+ $pri = $if_type_hash->{bond} + $alias;
+ } elsif ($iface =~ m/^vmbr\d+$/) {
+ $pri = $if_type_hash->{bridge} + $alias;
}
+
+ return $pri || ($if_type_hash->{unknown} + $alias);
+ };
+
+ foreach my $iface (sort {
+ my $ref1 = $ifaces->{$a};
+ my $ref2 = $ifaces->{$b};
+ my $p1 = &$lookup_type_prio($a);
+ my $p2 = &$lookup_type_prio($b);
+
+ return $p1 <=> $p2 if $p1 != $p2;
+
+ $p1 = $ref1->{priority} || 100000;
+ $p2 = $ref2->{priority} || 100000;
+
+ return $p1 <=> $p2 if $p1 != $p2;
+
+ return $a cmp $b;
+ } keys %$ifaces) {
+
+ my $d = $ifaces->{$iface};
+
+ next if $printed->{$iface};
+
+ $printed->{$iface} = 1;
+ $raw .= __interface_to_string($iface, $d);
}
PVE::Tools::safe_print($filename, $fh, $raw);
\&read_etc_network_interfaces,
\&write_etc_network_interfaces);
+
+sub read_iscsi_initiatorname {
+ my ($filename, $fd) = @_;
+
+ while (defined(my $line = <$fd>)) {
+ if ($line =~ m/^InitiatorName=(\S+)$/) {
+ return $1;
+ }
+ }
+
+ return 'undefined';
+}
+
+register_file('initiatorname', "/etc/iscsi/initiatorname.iscsi",
+ \&read_iscsi_initiatorname);
+
+sub read_apt_auth {
+ my ($filename, $fd) = @_;
+
+ local $/;
+
+ my $raw = defined($fd) ? <$fd> : '';
+
+ $raw =~ s/^\s+//;
+
+
+ my @tokens = split(/\s+/, $raw);
+
+ my $data = {};
+
+ my $machine;
+ while (defined(my $tok = shift @tokens)) {
+
+ $machine = shift @tokens if $tok eq 'machine';
+ next if !$machine;
+ $data->{$machine} = {} if !$data->{$machine};
+
+ $data->{$machine}->{login} = shift @tokens if $tok eq 'login';
+ $data->{$machine}->{password} = shift @tokens if $tok eq 'password';
+ };
+
+ return $data;
+}
+
+my $format_apt_auth_data = sub {
+ my $data = shift;
+
+ my $raw = '';
+
+ foreach my $machine (sort keys %$data) {
+ my $d = $data->{$machine};
+ $raw .= "machine $machine\n";
+ $raw .= " login $d->{login}\n" if $d->{login};
+ $raw .= " password $d->{password}\n" if $d->{password};
+ $raw .= "\n";
+ }
+
+ return $raw;
+};
+
+sub write_apt_auth {
+ my ($filename, $fh, $data) = @_;
+
+ my $raw = &$format_apt_auth_data($data);
+
+ die "write failed: $!" unless print $fh "$raw\n";
+
+ return $data;
+}
+
+sub update_apt_auth {
+ my ($filename, $fh, $data) = @_;
+
+ my $orig = read_apt_auth($filename, $fh);
+
+ foreach my $machine (keys %$data) {
+ $orig->{$machine} = $data->{$machine};
+ }
+
+ return &$format_apt_auth_data($orig);
+}
+
+register_file('apt-auth', "/etc/apt/auth.conf",
+ \&read_apt_auth, \&write_apt_auth,
+ \&update_apt_auth, perm => 0640);
+
1;