From: Yousong Zhou Date: Tue, 13 Jun 2017 09:03:38 +0000 (+0800) Subject: scripts/package-metadata.pl: parse and validate field Require-User X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=80d9ec5d3dbc1e393f377ede51e16d5c267475bd;p=openwrt%2Fstaging%2Fflorian.git scripts/package-metadata.pl: parse and validate field Require-User The script will now detect uid/gid collision and can generate a table of current allocation ./scripts/package-metadata.pl usergroup tmp/.packageinfo \ | sort -k 1,1r -k 3,3n \ | column -t This should ensure that no collision will happen for each single build Signed-off-by: Yousong Zhou --- diff --git a/scripts/metadata.pm b/scripts/metadata.pm index 8334f26d31..d446892e2b 100644 --- a/scripts/metadata.pm +++ b/scripts/metadata.pm @@ -2,7 +2,7 @@ package metadata; use base 'Exporter'; use strict; use warnings; -our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore); +our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore %usernames %groupnames); our %package; our %preconfig; @@ -13,6 +13,11 @@ our %features; our %overrides; our @ignore; +our %usernames; +our %groupnames; +our %userids; +our %groupids; + sub get_multiline { my $fh = shift; my $prefix = shift; @@ -31,6 +36,58 @@ sub confstr($) { return $conf; } +sub parse_package_metadata_usergroup($$$$$) { + my $makefile = shift; + my $typename = shift; + my $names = shift; + my $ids = shift; + my $spec = shift; + my $name; + my $id; + + # the regex for name is taken from is_valid_name() of package shadow + if ($spec =~ /^([a-z_][a-z0-9_-]*\$?)$/) { + $name = $spec; + $id = -1; + } elsif ($spec =~ /^([a-z_][a-z0-9_-]*\$?)=(\d+)$/) { + $name = $1; + $id = $2; + } else { + warn "$makefile: invalid $typename spec $spec\n"; + return 0; + } + + if ($id =~ /^[1-9]\d*$/) { + if ($id >= 65536) { + warn "$makefile: $typename $name id $id >= 65536"; + return 0; + } + if (not exists $ids->{$id}) { + $ids->{$id} = { + name => $name, + makefile => $makefile, + }; + } elsif ($ids->{$id}{name} ne $name) { + warn "$makefile: $typename $name id $id is already taken by $ids->{$id}{makefile}\n"; + return 0; + } + } elsif ($id != -1) { + warn "$makefile: $typename $name has invalid id $id\n"; + return 0; + } + + if (not exists $names->{$name}) { + $names->{$name} = { + id => $id, + makefile => $makefile, + }; + } elsif ($names->{$name}{id} != $id) { + warn "$makefile: id of $typename $name collides with that defined defined in $names->{$name}{makefile}\n"; + return 0; + } + return 1; +} + sub parse_target_metadata($) { my $file = shift; my ($target, @target, $profile); @@ -128,6 +185,8 @@ sub clear_packages() { %category = (); %features = (); %overrides = (); + %usernames = (); + %groupnames = (); } sub parse_package_metadata($) { @@ -262,6 +321,17 @@ sub parse_package_metadata($) { /^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1; /^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1; /^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1; + /^Require-User:\s*(.*?)\s*$/ and do { + my @ugspecs = split /\s+/, $1; + + for my $ugspec (@ugspecs) { + my @ugspec = split /:/, $ugspec, 2; + parse_package_metadata_usergroup($makefile, "user", \%usernames, \%userids, $ugspec[0]) or return 0; + if (@ugspec > 1) { + parse_package_metadata_usergroup($makefile, "group", \%groupnames, \%groupids, $ugspec[1]) or return 0; + } + } + }; } close FILE; return 1; diff --git a/scripts/package-metadata.pl b/scripts/package-metadata.pl index 2da32c770e..d4100c1726 100755 --- a/scripts/package-metadata.pl +++ b/scripts/package-metadata.pl @@ -632,6 +632,16 @@ sub gen_version_filtered_list() { } } +sub gen_usergroup_list() { + parse_package_metadata($ARGV[0]) or exit 1; + for my $name (keys %usernames) { + print "user $name $usernames{$name}{id} $usernames{$name}{makefile}\n"; + } + for my $name (keys %groupnames) { + print "group $name $groupnames{$name}{id} $groupnames{$name}{makefile}\n"; + } +} + sub parse_command() { GetOptions("ignore=s", \@ignore); my $cmd = shift @ARGV; @@ -643,6 +653,7 @@ sub parse_command() { /^subdirs$/ and return gen_package_subdirs(); /^license$/ and return gen_package_license(0); /^licensefull$/ and return gen_package_license(1); + /^usergroup$/ and return gen_usergroup_list(); /^version_filter$/ and return gen_version_filtered_list(); } die <