home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2177 < prev    next >
Internet Message Format  |  1990-12-28  |  6KB

  1. From: tchrist@convex.COM (Tom Christiansen)
  2. Newsgroups: comp.lang.perl,comp.unix.questions,alt.sources
  3. Subject: Re: Help with massive uid/gid change.
  4. Message-ID: <109616@convex.convex.com>
  5. Date: 30 Nov 90 21:36:05 GMT
  6.  
  7. In article <2365@taurus.BITNET> <ofer%math.tau.ac.il@CUNYVM.CUNY.EDU> writes:
  8. >Hello
  9. >I have to change the uid/gid numbers for all the users on a system
  10. >I'd like to do it doing one pass over the file system and not by
  11. >doing n times 'find ....' for n=the number of users.
  12. >I have an old /etc/passwd file and a new one and wish to use them
  13. >as the base for this number swapping process.
  14. >I have perl and all standard unix available.
  15.  
  16. I believe that UofCO has a compiled version of this kind of thing that's
  17. quite quick by going under the file system, which may or may not bother
  18. you.  I don't have a copy though, so wrote my own.
  19.  
  20. This is how it works.  You make a file, called "howtomv" by default.
  21. In it you put new mappings, for example:
  22.  
  23.     #comment
  24.     user jimbob 10002      # more comment
  25.     user stevebob 854
  26.     group bobbros 200
  27.     user daemon 1854
  28.     user notes 1
  29.  
  30. Then you run the script.  It will give you a passwd.new and a group.new
  31. file that you can inspect, and it won't really do the work if you use -n.
  32. I've checked for a lot of blunders, but not all.  One thing I don't check
  33. for is if userid A wants to move to userid B and B is occupied, it won't
  34. let you.  It should really check to see whether B is moving and leaving a
  35. vacancy, but it doesn't.  By all means inspect the code closely first, run
  36. with -n to see what it wants to do, and keep a backup of your disk.  No
  37. warranties, etc etc.  Still, it worked well enough for me when I needed it.
  38.  
  39. --tom
  40.  
  41. #!/usr/bin/perl
  42. #
  43. # mvids - "moves" uids and gids
  44. # Tom Christiansen <tchrist@convex.com>
  45. #
  46. # usage: mvids [-n] [-f howtomvfile] [starting-dir]
  47. #    
  48. # Takes list of new user and group ids.
  49. # Fixes passwd and group files.
  50. # Traverses local file system starting with starting-dir
  51. #      updating all changed ids
  52. #
  53. # -n means don't really change anything 
  54. # -f is if you don't like the default description file name of howtomv
  55.  
  56.  
  57. # read descriptions from howtomv file with format: 
  58. #    type name number
  59. # e.g.:
  60. #    user tom 1023
  61. #    group staff 200
  62.  
  63.  
  64. $| = 1;
  65. $oops = 0;
  66.  
  67. require 'getopts.pl';
  68.  
  69. do Getopts('dnf:');
  70.  
  71. $FILE = $opt_f || "howtomv"; 
  72.  
  73. $DIR = $opt_d ? "." : "/etc";
  74.  
  75. $topdir = shift || '/';
  76.  
  77. die "usage: $0 [-n] [-f howtomv] [starting-dir]\n"     if $#ARGV > -1;
  78.  
  79. die "$topdir: Not a directory"    unless -d $topdir;
  80.  
  81. open FILE || die "Can't open directions file \"$FILE\": $!\n";
  82. while (<FILE>) {
  83.     s/\s*#.*//;
  84.     next if /^$/;
  85.     unless (/^(user|group)\s+(\w+)\s+(\d+)/) {
  86.     print STDERR "malformed line at line $. of $FILE: $_";
  87.     $oops++; next;
  88.     } 
  89.     if ($3 > 32000) {
  90.     print STDERR "$1 $2 has id that's too big ($3)\n";
  91.     $oops++; next;
  92.     } 
  93.     if ($3 == 0) {
  94.     print STDERR "Too dangerous to move $1 $2 to 0\n";
  95.     $oops++; next;
  96.     } 
  97.     if ($2 eq 'root') {
  98.     print STDERR "You don't really want to move root\n";
  99.     $oops++; $next;
  100.     } 
  101.     if ($1 eq 'user') {
  102.     if (defined $n_pwn2i{$2}) {
  103.         print STDERR "Saw user $2 again at line $. of $FILE\n";
  104.         $oops++; next;
  105.     }
  106.     if (defined $n_pwi2n{$3}) {
  107.         print STDERR "Saw uid $3 again at line $. of $FILE\n";
  108.         $oops++; next;
  109.     }
  110.     $uids++;
  111.     $n_pwn2i{$2} = $3;
  112.     $n_pwi2n{$3} = $2;
  113.     } else {
  114.     if (defined $n_grn2i{$2}) {
  115.         print STDERR "Saw group $2 again at line $. of $FILE\n";
  116.         $oops++; next;
  117.     } 
  118.     if (defined $n_gri2n{$3}) {
  119.         print STDERR "Saw gid $3 again at line $. of $FILE\n";
  120.         $oops++; next;
  121.     }
  122.     $gids++;
  123.     $n_grn2i{$2} = $3;
  124.     $n_gri2n{$3} = $2;
  125.     } 
  126.  
  127. $PWD  = "$DIR/passwd";
  128. $NPWD = "$PWD.new";
  129.  
  130. if ($uids) {
  131.     open PWD             || die "Can't open $PWD: $!\n";
  132.     open (NPWD, ">$NPWD")     || die "Can't create $NPWD: $!\n";
  133.  
  134.     while (<PWD>) {
  135.     ((($name,$uid) = /^(\w+):[^:]*:(\d+):/)) 
  136.         || die "Bad passwd entry at line $.\n";
  137.     if (defined $n_pwi2n{$uid} && !defined $n_pwn2i{$name}) {
  138.         printf STDERR "Can't move user %s to uid %d -- %s already has it\n",
  139.             $n_pwi2n{$uid}, $uid, $name;
  140.         $oops++;
  141.         next;
  142.     } 
  143.     $pwn2i{$name} = $uid;
  144.     s/:$uid:/:$n_pwn2i{$name}:/    if defined $n_pwn2i{$name};
  145.     print NPWD;
  146.     }
  147.     close PWD;
  148.     close NPWD;
  149.  
  150.     foreach $user (keys %pwnam) {
  151.     unless (defined $pwn2i{$user}) {
  152.         print STDERR "Can't move non-existent user $user\n";
  153.         $oops++;
  154.     } 
  155.     } 
  156.  
  157. }
  158.  
  159. if ($gids) {
  160.     $GRP = "$DIR/group";
  161.     $NGRP = "$GRP.new";
  162.     open GRP             || die "Can't open $GRP: $!\n";
  163.     open (NGRP , ">$NGRP")     || die "Can't create $NGRP: $!\n";
  164.  
  165.     while (<GRP>) {
  166.     ((($name,$gid) = /^(\w+):[^:]*:(\d+):/)) 
  167.         || die "Bad group entry at line $.\n";
  168.     if (defined $n_gri2n{$gid} && !defined $n_grn2i{$name}) {
  169.         printf STDERR "Can't move gid %s to %d -- %s already has it\n",
  170.             $n_gri2n{$gid}, $gid, $name;
  171.         $oops++;
  172.         next;
  173.     } 
  174.     $grn2i{$name} = $gid;
  175.     s/:$gid:/:$n_grn2i{$name}:/    if defined $n_grn2i{$name};
  176.     print NGRP;
  177.     } 
  178.     close GRP;
  179.     close NGRP;
  180.  
  181.     foreach $group (keys %grnam) {
  182.     unless (defined $grn2i{$group}) {
  183.         print STDERR "Can't move non-existent group $group\n";
  184.         $oops++;
  185.     } 
  186.     } 
  187.  
  188. }
  189.  
  190. die "$0: $oops error" . ($oops > 1 ? "s" : "").
  191.     " in remapping directions.\n"        if $oops;
  192.  
  193.  
  194. die "$0: no ids to move\n" unless $uids || $gids;
  195.  
  196. # ok, now do it
  197.  
  198. open(FIND, "find $topdir \\( -fstype nfs -prune \\) -o -ls |")
  199.     || die "Can't open find pipe";
  200.  
  201. while (<FIND>) {
  202.     split;
  203.     $uid = $gid = -1;
  204.     ($file, $user, $group) = ($_[11], $_[5], $_[6]);
  205.  
  206.     if (defined $n_pwn2i{$user}) {
  207.     $uid = $n_pwn2i{$user};
  208.     print "changing owner $user of $file from ",
  209.         "$pwn2i{$user} to $n_pwn2i{$user}\n";
  210.     }
  211.     if (defined $n_grn2i{$group}) {
  212.     $gid = $n_grn2i{$group};
  213.     print "changing group $group of $file from ",
  214.         "$grn2i{$group} to $n_grn2i{$group}\n";
  215.     }
  216.  
  217.     if (!$opt_n && ($uid != -1 || $gid != -1)) {
  218.     if (!chown $uid, $gid, $file) {
  219.         printf STDERR "couldn't chown $file to $uid.$gid: $!\n";
  220.         $oops++;
  221.     } 
  222.     } 
  223.  
  224. unless ($opt_n) {
  225.     if ($uids) {
  226.     rename($PWD, "$PWD.bak")     
  227.         || die "Can't mv $PWD to $PWD.bak: $!\n";
  228.     rename($NPWD, $PWD)        
  229.         || die "Can't mv $NPWD to $PWD: $!\n";
  230.     }
  231.     if ($gids) {
  232.     rename($GRP, "$GRP.bak")
  233.         || die "Can't mv $GRP to $GRP.bak: $!\n";
  234.     rename($NGRP, $GRP)
  235.         || die "Can't mv $NGRP to $GRP: $!\n";
  236.     }
  237.  
  238. exit ($oops != 0);
  239.