home *** CD-ROM | disk | FTP | other *** search
- From: tchrist@convex.COM (Tom Christiansen)
- Newsgroups: comp.lang.perl,comp.unix.questions,alt.sources
- Subject: Re: Help with massive uid/gid change.
- Message-ID: <109616@convex.convex.com>
- Date: 30 Nov 90 21:36:05 GMT
-
- In article <2365@taurus.BITNET> <ofer%math.tau.ac.il@CUNYVM.CUNY.EDU> writes:
- >Hello
- >I have to change the uid/gid numbers for all the users on a system
- >I'd like to do it doing one pass over the file system and not by
- >doing n times 'find ....' for n=the number of users.
- >I have an old /etc/passwd file and a new one and wish to use them
- >as the base for this number swapping process.
- >I have perl and all standard unix available.
-
- I believe that UofCO has a compiled version of this kind of thing that's
- quite quick by going under the file system, which may or may not bother
- you. I don't have a copy though, so wrote my own.
-
- This is how it works. You make a file, called "howtomv" by default.
- In it you put new mappings, for example:
-
- #comment
- user jimbob 10002 # more comment
- user stevebob 854
- group bobbros 200
- user daemon 1854
- user notes 1
-
- Then you run the script. It will give you a passwd.new and a group.new
- file that you can inspect, and it won't really do the work if you use -n.
- I've checked for a lot of blunders, but not all. One thing I don't check
- for is if userid A wants to move to userid B and B is occupied, it won't
- let you. It should really check to see whether B is moving and leaving a
- vacancy, but it doesn't. By all means inspect the code closely first, run
- with -n to see what it wants to do, and keep a backup of your disk. No
- warranties, etc etc. Still, it worked well enough for me when I needed it.
-
- --tom
-
- #!/usr/bin/perl
- #
- # mvids - "moves" uids and gids
- # Tom Christiansen <tchrist@convex.com>
- #
- # usage: mvids [-n] [-f howtomvfile] [starting-dir]
- #
- # Takes list of new user and group ids.
- # Fixes passwd and group files.
- # Traverses local file system starting with starting-dir
- # updating all changed ids
- #
- # -n means don't really change anything
- # -f is if you don't like the default description file name of howtomv
-
-
- # read descriptions from howtomv file with format:
- # type name number
- # e.g.:
- # user tom 1023
- # group staff 200
-
-
- $| = 1;
- $oops = 0;
-
- require 'getopts.pl';
-
- do Getopts('dnf:');
-
- $FILE = $opt_f || "howtomv";
-
- $DIR = $opt_d ? "." : "/etc";
-
- $topdir = shift || '/';
-
- die "usage: $0 [-n] [-f howtomv] [starting-dir]\n" if $#ARGV > -1;
-
- die "$topdir: Not a directory" unless -d $topdir;
-
- open FILE || die "Can't open directions file \"$FILE\": $!\n";
- while (<FILE>) {
- s/\s*#.*//;
- next if /^$/;
- unless (/^(user|group)\s+(\w+)\s+(\d+)/) {
- print STDERR "malformed line at line $. of $FILE: $_";
- $oops++; next;
- }
- if ($3 > 32000) {
- print STDERR "$1 $2 has id that's too big ($3)\n";
- $oops++; next;
- }
- if ($3 == 0) {
- print STDERR "Too dangerous to move $1 $2 to 0\n";
- $oops++; next;
- }
- if ($2 eq 'root') {
- print STDERR "You don't really want to move root\n";
- $oops++; $next;
- }
- if ($1 eq 'user') {
- if (defined $n_pwn2i{$2}) {
- print STDERR "Saw user $2 again at line $. of $FILE\n";
- $oops++; next;
- }
- if (defined $n_pwi2n{$3}) {
- print STDERR "Saw uid $3 again at line $. of $FILE\n";
- $oops++; next;
- }
- $uids++;
- $n_pwn2i{$2} = $3;
- $n_pwi2n{$3} = $2;
- } else {
- if (defined $n_grn2i{$2}) {
- print STDERR "Saw group $2 again at line $. of $FILE\n";
- $oops++; next;
- }
- if (defined $n_gri2n{$3}) {
- print STDERR "Saw gid $3 again at line $. of $FILE\n";
- $oops++; next;
- }
- $gids++;
- $n_grn2i{$2} = $3;
- $n_gri2n{$3} = $2;
- }
- }
-
- $PWD = "$DIR/passwd";
- $NPWD = "$PWD.new";
-
- if ($uids) {
- open PWD || die "Can't open $PWD: $!\n";
- open (NPWD, ">$NPWD") || die "Can't create $NPWD: $!\n";
-
- while (<PWD>) {
- ((($name,$uid) = /^(\w+):[^:]*:(\d+):/))
- || die "Bad passwd entry at line $.\n";
- if (defined $n_pwi2n{$uid} && !defined $n_pwn2i{$name}) {
- printf STDERR "Can't move user %s to uid %d -- %s already has it\n",
- $n_pwi2n{$uid}, $uid, $name;
- $oops++;
- next;
- }
- $pwn2i{$name} = $uid;
- s/:$uid:/:$n_pwn2i{$name}:/ if defined $n_pwn2i{$name};
- print NPWD;
- }
- close PWD;
- close NPWD;
-
- foreach $user (keys %pwnam) {
- unless (defined $pwn2i{$user}) {
- print STDERR "Can't move non-existent user $user\n";
- $oops++;
- }
- }
-
- }
-
- if ($gids) {
- $GRP = "$DIR/group";
- $NGRP = "$GRP.new";
- open GRP || die "Can't open $GRP: $!\n";
- open (NGRP , ">$NGRP") || die "Can't create $NGRP: $!\n";
-
- while (<GRP>) {
- ((($name,$gid) = /^(\w+):[^:]*:(\d+):/))
- || die "Bad group entry at line $.\n";
- if (defined $n_gri2n{$gid} && !defined $n_grn2i{$name}) {
- printf STDERR "Can't move gid %s to %d -- %s already has it\n",
- $n_gri2n{$gid}, $gid, $name;
- $oops++;
- next;
- }
- $grn2i{$name} = $gid;
- s/:$gid:/:$n_grn2i{$name}:/ if defined $n_grn2i{$name};
- print NGRP;
- }
- close GRP;
- close NGRP;
-
- foreach $group (keys %grnam) {
- unless (defined $grn2i{$group}) {
- print STDERR "Can't move non-existent group $group\n";
- $oops++;
- }
- }
-
- }
-
- die "$0: $oops error" . ($oops > 1 ? "s" : "").
- " in remapping directions.\n" if $oops;
-
-
- die "$0: no ids to move\n" unless $uids || $gids;
-
- # ok, now do it
-
- open(FIND, "find $topdir \\( -fstype nfs -prune \\) -o -ls |")
- || die "Can't open find pipe";
-
- while (<FIND>) {
- split;
- $uid = $gid = -1;
- ($file, $user, $group) = ($_[11], $_[5], $_[6]);
-
- if (defined $n_pwn2i{$user}) {
- $uid = $n_pwn2i{$user};
- print "changing owner $user of $file from ",
- "$pwn2i{$user} to $n_pwn2i{$user}\n";
- }
- if (defined $n_grn2i{$group}) {
- $gid = $n_grn2i{$group};
- print "changing group $group of $file from ",
- "$grn2i{$group} to $n_grn2i{$group}\n";
- }
-
- if (!$opt_n && ($uid != -1 || $gid != -1)) {
- if (!chown $uid, $gid, $file) {
- printf STDERR "couldn't chown $file to $uid.$gid: $!\n";
- $oops++;
- }
- }
- }
-
- unless ($opt_n) {
- if ($uids) {
- rename($PWD, "$PWD.bak")
- || die "Can't mv $PWD to $PWD.bak: $!\n";
- rename($NPWD, $PWD)
- || die "Can't mv $NPWD to $PWD: $!\n";
- }
- if ($gids) {
- rename($GRP, "$GRP.bak")
- || die "Can't mv $GRP to $GRP.bak: $!\n";
- rename($NGRP, $GRP)
- || die "Can't mv $NGRP to $GRP: $!\n";
- }
- }
-
- exit ($oops != 0);
-