NAME

FileInfo -- cached information about files and directories

USAGE

  use FileInfo;
  chdir($new_dir);		# Changes to new directory and keeps track
				# of the directory name in the variable
				# $CWD_INFO.
  $finfo = file_info("filename");

  $finfo->build_handle;		# Returns the handle for the process that is
				# building (or has built) the file.
  $finfo->set_build_handle($handle); # Sets the handle for the process
				# that's currently building the file.


  $build_rule = $finfo->build_rule; # Returns the rule for building the file,
				# if such a rule exists.
  $finfo->set_build_rule($rule); # Set the rule used to build this file.

  $finfo->build_info_string("key");
				# Returns a piece of information from the build
				# info file, if there is one.
  $finfo->set_build_info_string("key", "value");
  FileInfo::update_build_infos(); # Flushes build info cache to disk.

  if ($finfo->exists_or_can_be_built) {}
  my $dir_finfo = $finfo->parent; # The directory containing this file.
  $name = $finfo->absolute_filename;	# Returns absolute file name.
				# If more than one name can be used
				# (because of soft links), the shortest
				# possible one is used to avoid problems with
				# the automounter.
  $name = $finfo->relative_filename;
  $relative_fname = $finfo->relative_filename("dir");
  $relative_fname = $finfo->relative_filename($dirinfo);
				# Returns name relative to given directory.

  $finfo->may_have_changed;	# Indicate that the file may have changed on
				# disk, so invalidate (or check) cached info.

  if ($finfo->file_exists) { ... }
  $date = $finfo->file_mtime;

  @file_infos = find_file("filename"); # Find a file with a given name
				# somewhere in the directory hierarchy.
				# (See also Glob::zglob for a more powerful
				# wildcarded find procedure.)

  if ($finfo->is_dir) { ... }
  if ($finfo->is_writable) { ... }
  if ($finfo->is_executable) { ... }
  if ($finfo->is_symbolic_link) { ... }

  $finfo->unlink;		# Deletes the file.

  my $link_finfo = $finfo->dereference;
				# Dereference a symbolic link.

  @file_infos = $finfo->dir_contents;
				# If the file is a directory, this is the list
				# of FileInfo structures in that directory.
  $finfo->read_directory;	# Try to (re)read the contents of a directory.

  my $stat_array = $finfo->stat_array; # Return the array returned by stat().
  my $lstat_array = $finfo->lstat_array; # Return the array returned by lstat().
  $signature = $finfo->signature;
  $finfo->set_signature_function(\&function);
				# Set the function that is used to compute
				# the signature for this file.

  FileInfo::relative_filename("file", "dir"); # Returns relative name of file
				# with respect to the directory.
  FileInfo::absolute_filename("file"); # Returns absolute name of file.

DESCRIPTION

FileInfo is an efficient way to avoid re-statting files and rereading directories. For each known file, there is a FileInfo structure that describes what is known about the file. You may add arbitrary additional information to the structure.

FileInfo is designed so it won't be confused by soft-linked directories. However, it will have problems if a soft link initially points to one directory and then is changed to point to a different directory, or if files are referred to thruogh a symbolic link to a directory before the symbolic link is actually created. Generally speaking, it's not a good idea to create or modify soft links.

FileInfo can be used alone. Some supplemental routines useful only in the context of makepp are found in FileInfo_makepp.pm, and in fact that file overrides some of the routines here.

absolute_filename

$str = $fileinfo->absolute_filename;
$str = absolute_filename("relative file name");

$str = $fileinfo->absolute_filename($dir);
$str = absolute_filename("relative file name", $dir);

Returns the absolute file name. The optional $dir argument specifies where to start looking for the file (i.e., what the "." directory is). If you don't specify this, uses the current directory.

chdir("new dir")

chdir("new dir")
chdir($dirinfo)

Changes to the indicated directory, and keeps track of the change in the variable $FileInfo::CWD_INFO. Dies with a message if the chdir failed.

You can pass a FileInfo structure describing the directory instead of the directory name itself if that is more convenient.

This subroutine is automatically exported into any packages that use FileInfo, so your chdirs will work automatically.

dereference

$finfo = $fileinfo->dereference;

If the file is a symbolic link, this returns a FileInfo structure for the file it points to. If the symbolic link points to another symbolic link, returns what that link points to. If the file is not a symbolic link, returns the original FileInfo structure.

exists_or_can_be_built

if ($file_info->exists_or_can_be_built) { ... }

Returns true if the file exists. This is overridden by a method of the same name in FileInfo_makepp.pm, which returns true if the file already exists or if we know of a way to build it.

file_exists

if ($file_info->file_exists) { ... }

Returns true (actually, returns the FileInfo structure) if the file exists, and undef if it doesn't.

file_info

$finfo = file_info("filename");
$finfo = file_info("filename", $dirinfo);

Returns the FileInfo structure for the given file. If no FileInfo structure exists, creates a new one for it.

If you pass a FileInfo structure to file_info, it just returns its argument.

The optional second argument specifies a directory the file name should be relative to. By default, this is the current directory.

  foreach (@{$finfo->dir_contents}) {
    $_->exists_or_can_be_built or next;	# Skip if file doesn't exist.
				# (Files which don't exist can have FileInfo
				# entries, if you happened to call
				# file_info on them explicitly.)
    # do your thing here.
  }

If you want to iterate through all the files which are in a directory, not just the ones encountered previously, then call $dirinfo->read_directory before using the above code snippet.

file_mtime

$date = $file_info->file_mtime;
$date = file_mtime("filename");

Returns the last modification time for the given file. If the file is a symbolic link, this returns the modification for the file the link refers to.

find_file

@file_infos = find_file("filename");

Finds all files in the directory tree that have the given file name. The files must either exist or have a build command specified for them (this is used by PBuilder). The file name must match exactly. The name should not contain any directory specification.

Returns a null array if nothing is found.

See also Glob::zglob for a find procedure that will work with wildcards. Note especially its "**" wildcard. find_file("filename") is equivalent to (but faster than) zglob_fileinfo("**/filename"), except that it will not read any directories--it only looks at files that are currently known.

This function will not return any files located in directories that don't exist, even if there are FileInfo structures for them.

is_dir

if ($fileinfo->is_dir) { ... }

Returns true (actually, returns the fileinfo structure) if the given file is actually a directory. Does not return true for soft links that point to directories. (If you want to do that, you can call is_symbolic_link and then follow the symbolic link using dereference.) See under file_info for how to examine the contents of the directory.

is_dir() only returns true for directories that currently exist. You can create FileInfo structures for directories that don't exist yet; to check for this kind of directory, use is_or_will_be_dir().

is_or_will_be_dir

if ($fileinfo->is_dir) { ... }

Returns true (actually, returns the fileinfo structure) if the given file is actually a directory, or if it will be a directory (because file_info() was called using it as a directory). Also returns true for soft links that point to directories.

is_executable

if ($finfo->is_executable) { ... }

Returns true (actually, returns the FileInfo structure) if the given file is executable by this user. We don't actually handle the group executable bit correctly right now, since it's a pain to find out what groups this user is actually in.

if ($finfo->is_symbolic_link) { ... }

Returns true (actually, returns the FileInfo structure) if the given file is a symbolic link.

is_writable

if ($dirinfo->is_writable) { ... }

Returns true (actually, returns the fileinfo structure) if the given directory can be written to. Because of the complexity of testing for permission, we test by actually trying to write a file to that directory.

$finfo->link_to($other_finfo);

Sets up $finfo to be a soft link to the file contained in $other_finfo.

lstat_array

$statinfo = $fileinfo->stat_array;
$uid = $statinfo->[4];	# Or whatever field you're interested in.

Returns the array of values returned by the lstat function on the file. The values are cached, so calling this repeatedly entails only minimal extra overhead.

may_have_changed

$finfo->may_have_changed;

Indicates that a file may have changed, so that any cached values (such as the signature or the file time) are invalid.

mkdir

$dirinfo->mkdir;

Makes the directory specified by the FileInfo structure (and any parent directories that are necessary).

parent

$dirinfo = $finfo->parent;

Returns the directory containing the file.

read_directory

$dirinfo->read_directory;

Rereads the given directory so we know what files are actually in it.

relative_filename

$str = $fileinfo->relative_filename;
$str = $fileinfo->relative_filename($dir);
$str = relative_filename($filename);
$str = relative_filename($filename, $dir);

Return a file name relative to the given directory, if specified. If no directory is specified, uses the current working directory. If the directory and the file have no directories in common (e.g., like "/home/mystuff/stuff" and "/usr/local/bin"), then an absolute file name is returned.

stat_array

$statinfo = $fileinfo->stat_array;
$statinfo = FileInfo::stat_array("filename");
$uid = $statinfo->[4];	# Or whatever field you're interested in.

Returns the array of values returned by the stat function on the file. The values are cached, so calling this repeatedly entails only minimal extra overhead.

If the file is a symbolic link, this returns the stat values for the file the link refers to.

traverse

FileInfo::traverse sub { 
   my (@finfos) = @_;

   foreach (@finfos) { ... do something }
}

Traverses through what we know of the entire file system. The subroutine is called with @_ as an unsorted array of all the FileInfo structures that are contained in that directory. The subroutine is invoked on parent directories before it is ivoked on child directories.

$fileinfo->unlink;

Removes the file and marks it in the cache as non-existent.

AUTHOR

Gary Holt (holt@lnc.usc.edu)