home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

Perl CookbookPerl CookbookSearch this book

8.13. Updating a Random-Access File

8.13.3. Discussion

You don't have to use anything fancier than print in Perl to output a record. Remember that the opposite of read is not write but print, although oddly enough, the opposite of sysread is syswrite.

The example program shown in Example 8-4, weekearly, takes one argument: the user whose record you want to backdate by a week. (Of course, in practice, you wouldn't really want to (nor be able to!) mess with the system accounting files.) This program requires write access to the file to be updated, since it opens the file in update mode. After fetching and altering the record, it packs it up again, skips backward in the file one record, and writes it out.

Example 8-4. weekearly

  #!/usr/bin/perl -w
  # weekearly -- set someone's login date back a week
  use User::pwent;
  use IO::Seekable;
  $typedef = "L A12 A16";         # linux fmt; sunos is "L A8 A16"
  $sizeof  = length(pack($typedef, ( )));
  $user    = shift(@ARGV) || $ENV{USER} || $ENV{LOGNAME};
  $address = getpwnam($user)->uid * $sizeof;
  open (LASTLOG, "+<:raw", "/var/log/lastlog")
      or die "can't update /var/log/lastlog: $!";
  seek(LASTLOG, $address, SEEK_SET)
      or die "seek failed: $!";
  read(LASTLOG, $buffer, $sizeof) =  = $sizeof
      or die "read failed: $!";
  ($time, $line, $host) = unpack($typedef, $buffer);
  $time  -= 24 * 7 * 60 * 60;         # back-date a week
  $buffer = pack($typedef, $time, $line, $time);
  seek(LASTLOG, -$sizeof, SEEK_CUR)   # backup one record
      or die "seek failed: $!";
  print LASTLOG $record;
      or die "close failed: $!";

Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.