Factor out check_same_dev_ino() from check_same_stat() so it can be called separately.
[Samba.git] / lib / nss_wrapper / nss_wrapper.pl
blob48fa2c52b8f6e739a788a9ce13b58c5835f2fc01
1 #!/usr/bin/perl
4 use strict;
6 use Getopt::Long;
7 use Cwd qw(abs_path);
9 my $opt_help = 0;
10 my $opt_passwd_path = undef;
11 my $opt_group_path = undef;
12 my $opt_action = undef;
13 my $opt_type = undef;
14 my $opt_name = undef;
15 my $opt_member = undef;
16 my $opt_gid = 65534;# nogroup gid
18 my $passwdfn = undef;
19 my $groupfn = undef;
20 my $memberfn = undef;
21 my $actionfn = undef;
23 sub passwd_add($$$$$);
24 sub passwd_delete($$$$$);
25 sub group_add($$$$$);
26 sub group_delete($$$$$);
27 sub member_add($$$$$);
28 sub member_delete($$$$$);
30 sub check_path($$);
32 my $result = GetOptions(
33 'help|h|?' => \$opt_help,
34 'passwd_path=s' => \$opt_passwd_path,
35 'group_path=s' => \$opt_group_path,
36 'action=s' => \$opt_action,
37 'type=s' => \$opt_type,
38 'name=s' => \$opt_name,
39 'member=s' => \$opt_member,
40 'gid=i' => \$opt_gid
43 sub usage($;$)
45 my ($ret, $msg) = @_;
47 print $msg."\n\n" if defined($msg);
49 print "usage:
51 --help|-h|-? Show this help.
53 --passwd_path <path> Path of the 'passwd' file.
54 --group_path <path> Path of the 'group' file.
56 --type <type> 'passwd', 'group' and 'member' are supported.
58 --action <action> 'add' or 'delete'.
60 --name <name> The name of the object.
62 --member <member> The name of the member.
64 --gid <gid> Primary Group ID for new users.
66 exit($ret);
69 usage(1) if (not $result);
71 usage(0) if ($opt_help);
73 if (not defined($opt_action)) {
74 usage(1, "missing: --action [add|delete]");
76 if ($opt_action eq "add") {
77 $passwdfn = \&passwd_add;
78 $groupfn = \&group_add;
79 $memberfn = \&member_add;
80 } elsif ($opt_action eq "delete") {
81 $passwdfn = \&passwd_delete;
82 $groupfn = \&group_delete;
83 $memberfn = \&member_delete;
84 } else {
85 usage(1, "invalid: --action [add|delete]: '$opt_action'");
88 if (not defined($opt_type)) {
89 usage(1, "missing: --type [passwd|group|member]");
91 if ($opt_type eq "member" and not defined($opt_member)) {
92 usage(1, "missing: --member <member>");
94 my $opt_fullpath_passwd;
95 my $opt_fullpath_group;
96 if ($opt_type eq "passwd") {
97 $actionfn = $passwdfn;
98 $opt_fullpath_passwd = check_path($opt_passwd_path, $opt_type);
99 } elsif ($opt_type eq "group") {
100 $actionfn = $groupfn;
101 $opt_fullpath_group = check_path($opt_group_path, $opt_type);
102 } elsif ($opt_type eq "member") {
103 $actionfn = $memberfn;
104 $opt_fullpath_passwd = check_path($opt_passwd_path, "passwd");
105 $opt_fullpath_group = check_path($opt_group_path, "group");
106 } else {
107 usage(1, "invalid: --type [passwd|group]: '$opt_type'")
110 if (not defined($opt_name)) {
111 usage(1, "missing: --name <name>");
113 if ($opt_name eq "") {
114 usage(1, "invalid: --name <name>");
117 exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name, $opt_gid);
119 sub check_path($$)
121 my ($path,$type) = @_;
123 if (not defined($path)) {
124 usage(1, "missing: --$type\_path <path>");
126 if ($path eq "" or $path eq "/") {
127 usage(1, "invalid: --$type\_path <path>: '$path'");
129 my $fullpath = abs_path($path);
130 if (not defined($fullpath)) {
131 usage(1, "invalid: --$type\_path <path>: '$path'");
133 return $fullpath;
136 sub passwd_add_entry($$);
138 sub passwd_load($)
140 my ($path) = @_;
141 my @lines;
142 my $passwd = undef;
144 open(PWD, "<$path") or die("Unable to open '$path' for read");
145 @lines = <PWD>;
146 close(PWD);
148 $passwd->{array} = ();
149 $passwd->{name} = {};
150 $passwd->{uid} = {};
151 $passwd->{path} = $path;
153 foreach my $line (@lines) {
154 passwd_add_entry($passwd, $line);
157 return $passwd;
160 sub group_add_entry($$);
162 sub group_load($)
164 my ($path) = @_;
165 my @lines;
166 my $group = undef;
168 open(GROUP, "<$path") or die("Unable to open '$path' for read");
169 @lines = <GROUP>;
170 close(GROUP);
172 $group->{array} = ();
173 $group->{name} = {};
174 $group->{gid} = {};
175 $group->{path} = $path;
177 foreach my $line (@lines) {
178 group_add_entry($group, $line);
181 return $group;
184 sub passwd_lookup_name($$)
186 my ($passwd, $name) = @_;
188 return undef unless defined($passwd->{name}{$name});
190 return $passwd->{name}{$name};
193 sub group_lookup_name($$)
195 my ($group, $name) = @_;
197 return undef unless defined($group->{name}{$name});
199 return $group->{name}{$name};
202 sub passwd_lookup_uid($$)
204 my ($passwd, $uid) = @_;
206 return undef unless defined($passwd->{uid}{$uid});
208 return $passwd->{uid}{$uid};
211 sub group_lookup_gid($$)
213 my ($group, $gid) = @_;
215 return undef unless defined($group->{gid}{$gid});
217 return $group->{gid}{$gid};
220 sub passwd_get_free_uid($)
222 my ($passwd) = @_;
223 my $uid = 1000;
225 while (passwd_lookup_uid($passwd, $uid)) {
226 $uid++;
229 return $uid;
232 sub group_get_free_gid($)
234 my ($group) = @_;
235 my $gid = 1000;
237 while (group_lookup_gid($group, $gid)) {
238 $gid++;
241 return $gid;
244 sub passwd_add_entry($$)
246 my ($passwd, $str) = @_;
248 chomp $str;
249 my @e = split(':', $str);
251 push(@{$passwd->{array}}, \@e);
252 $passwd->{name}{$e[0]} = \@e;
253 $passwd->{uid}{$e[2]} = \@e;
256 sub group_add_entry($$)
258 my ($group, $str) = @_;
260 chomp $str;
261 my @e = split(':', $str);
263 push(@{$group->{array}}, \@e);
264 $group->{name}{$e[0]} = \@e;
265 $group->{gid}{$e[2]} = \@e;
268 sub passwd_remove_entry($$)
270 my ($passwd, $eref) = @_;
272 for (my $i = 0; defined($passwd->{array}[$i]); $i++) {
273 if ($eref == $passwd->{array}[$i]) {
274 $passwd->{array}[$i] = undef;
278 delete $passwd->{name}{${$eref}[0]};
279 delete $passwd->{uid}{${$eref}[2]};
282 sub group_remove_entry($$)
284 my ($group, $eref) = @_;
286 for (my $i = 0; defined($group->{array}[$i]); $i++) {
287 if ($eref == $group->{array}[$i]) {
288 $group->{array}[$i] = undef;
292 delete $group->{name}{${$eref}[0]};
293 delete $group->{gid}{${$eref}[2]};
296 sub group_add_member($$$)
298 my ($group, $eref, $username) = @_;
300 my @members;
301 my $str = @$eref[3] || undef;
302 if ($str) {
303 @members = split(",", $str);
306 foreach my $member (@members) {
307 if ($member and $member eq $username) {
308 die("account[$username] is already member of '@$eref[0]'");
312 push(@members, $username);
314 my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @members);
316 group_remove_entry($group, $eref);
318 group_add_entry($group, $gwent);
321 sub group_delete_member($$$)
323 my ($group, $eref, $username) = @_;
325 my @members = undef;
326 my $str = @$eref[3] || undef;
327 if ($str) {
328 @members = split(",", $str);
330 my @new_members;
331 my $removed = 0;
333 foreach my $member (@members) {
334 if ($member and $member ne $username) {
335 push(@new_members, $member);
336 } else {
337 $removed = 1;
341 if ($removed != 1) {
342 die("account[$username] is not member of '@$eref[0]'");
345 my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @new_members);
347 group_remove_entry($group, $eref);
349 group_add_entry($group, $gwent);
352 sub passwd_save($)
354 my ($passwd) = @_;
355 my @lines = ();
356 my $path = $passwd->{path};
357 my $tmppath = $path.$$;
359 foreach my $eref (@{$passwd->{array}}) {
360 next unless defined($eref);
362 my $line = join(':', @{$eref});
363 push(@lines, $line);
366 open(PWD, ">$tmppath") or die("Unable to open '$tmppath' for write");
367 print PWD join("\n", @lines)."\n";
368 close(PWD);
369 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
372 sub group_save($)
374 my ($group) = @_;
375 my @lines = ();
376 my $path = $group->{path};
377 my $tmppath = $path.$$;
379 foreach my $eref (@{$group->{array}}) {
380 next unless defined($eref);
382 my $line = join(':', @{$eref});
383 if (scalar(@{$eref}) == 3) {
384 $line .= ":";
386 push(@lines, $line);
389 open(GROUP, ">$tmppath") or die("Unable to open '$tmppath' for write");
390 print GROUP join("\n", @lines)."\n";
391 close(GROUP);
392 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
395 sub passwd_add($$$$$)
397 my ($path, $dummy, $dummy2, $name, $gid) = @_;
399 #print "passwd_add: '$name' in '$path'\n";
401 my $passwd = passwd_load($path);
403 my $e = passwd_lookup_name($passwd, $name);
404 die("account[$name] already exists in '$path'") if defined($e);
406 my $uid = passwd_get_free_uid($passwd);
408 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
410 passwd_add_entry($passwd, $pwent);
412 passwd_save($passwd);
414 return 0;
417 sub passwd_delete($$$$$)
419 my ($path, $dummy, $dummy2, $name, $dummy3) = @_;
421 #print "passwd_delete: '$name' in '$path'\n";
423 my $passwd = passwd_load($path);
425 my $e = passwd_lookup_name($passwd, $name);
426 die("account[$name] does not exists in '$path'") unless defined($e);
428 passwd_remove_entry($passwd, $e);
430 passwd_save($passwd);
432 return 0;
435 sub group_add($$$$$)
437 my ($dummy, $dummy2, $path, $name, $dummy3) = @_;
439 #print "group_add: '$name' in '$path'\n";
441 my $group = group_load($path);
443 my $e = group_lookup_name($group, $name);
444 die("group[$name] already exists in '$path'") if defined($e);
446 my $gid = group_get_free_gid($group);
448 my $gwent = $name.":x:".$gid.":"."";
450 group_add_entry($group, $gwent);
452 group_save($group);
454 #printf("%d\n", $gid);
456 return 0;
459 sub group_delete($$$$$)
461 my ($dummy, $dummy2, $path, $name, $dummy3) = @_;
463 #print "group_delete: '$name' in '$path'\n";
465 my $group = group_load($path);
467 my $e = group_lookup_name($group, $name);
468 die("group[$name] does not exists in '$path'") unless defined($e);
470 group_remove_entry($group, $e);
472 group_save($group);
474 return 0;
477 sub member_add($$$$$)
479 my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_;
481 #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n";
483 my $group = group_load($group_path);
485 my $g = group_lookup_name($group, $groupname);
486 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
488 my $passwd = passwd_load($passwd_path);
490 my $u = passwd_lookup_name($passwd, $username);
491 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
493 group_add_member($group, $g, $username);
495 group_save($group);
497 return 0;
500 sub member_delete($$$$$)
502 my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_;
504 #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n";
506 my $group = group_load($group_path);
508 my $g = group_lookup_name($group, $groupname);
509 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
511 my $passwd = passwd_load($passwd_path);
513 my $u = passwd_lookup_name($passwd, $username);
514 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
516 group_delete_member($group, $g, $username);
518 group_save($group);
520 return 0;