NAME

FileInfo -- cached information about files and directories

USAGE

Note that we show both a functional and an object oriented syntax here. Since the latter has a measurable overhead, and as this module is very heavily used, the functional syntax is to be preferred.

  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');

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


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

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

  if (exists_or_can_be_built( $finfo )) {}
  if ($finfo->exists_or_can_be_built) {}
  my $dir_finfo = parent( $finfo );
  my $dir_finfo = $finfo->parent; # The directory containing this file.
  $name = absolute_filename( $finfo );
  $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 = relative_filename( $finfo );
  $name = $finfo->relative_filename;
  $relative_fname = relative_filename( $finfo, 'dir');
  $relative_fname = $finfo->relative_filename('dir');
  $relative_fname = relative_filename($finfo, $dirinfo);
  $relative_fname = $finfo->relative_filename($dirinfo);
				# Returns name relative to given directory.

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

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

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

  FileInfo::unlink( $finfo );
  $finfo->unlink;		# Deletes the file.

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

  read_directory( $finfo );
  $finfo->read_directory;	# Try to (re)read the contents of a directory.

  my $stat_array = stat_array( $finfo ); # Return the array returned by stat().
  my $stat_array = $finfo->stat_array; # Return the array returned by stat().
  my $lstat_array = lstat_array( $finfo ); # Return the array returned by lstat().
  my $lstat_array = $finfo->lstat_array; # Return the array returned by lstat().
  FileInfo::relative_filename('file', 'dir'); # Returns relative name of file
				# with respect to the directory.

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 modify existing 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.

case_sensitive_filenames

True if we think makepp should treat filenames as case sensitive.

At present, makepp can be either 100% case insensitive, converting all filenames to lower case, or 100% case sensitive. Makepp currently cannot handle some files coming from a case-insensitive file system and other files coming from a case-sensitive file system.

This routine is just a guess. We look at the current directory to see if it looks case sensitive, and switch makepp into the appropriate mode.

$stat_exe_separate

On Windows this is true if you can't stat 'xyz', when only 'xyz.exe' exists. That is ActiveState at least until 5.10.0 and possibly older Cygwin versions.

absolute_filename

$str = absolute_filename( $fileinfo );

Returns the absolute file name.

chdir('new dir')

chdir('new dir')
chdir($dirinfo)

Changes to the indicated directory, and keeps track of the change in the variable $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 = dereference( $fileinfo );

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.

file_exists

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

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.

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

  foreach (@{dir_contents( $finfo )}) {
    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.

path_file_info

Does the work of file_info when filename contains directory separators. You can call this explicitly in places where filename is (almost) sure to have directory separators.

file_mtime

$date = file_mtime( $file_info );
$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. Return undef if it doesn't exist.

is_dir

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

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 (is_or_will_be_dir( $fileinfo )) { ... }

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 (is_executable( $finfo )) { ... }

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.

is_readable

if (is_readable( $finfo )) { ... }

Returns true if the given file or directory can be read.

have_read_permission

if (have_read_permission( $finfo )) { ... }

Returns true if the given file or directory has its read permission set for the effective user ID. This is not the same as is_readable, because there are other reasons that you might not be able to read the file.

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

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

is_writable

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

Returns true 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.

is_writable_owner

if (is_writable_user( $finfo ))

Determines if a given file is writable by its owner by just checking the mode bits. This does not test whether the current user is the owner.

touched_filesystem

A static method with no arguments. Call this to notify this package that some code has been run that might have changed something (especially in the case of adding files) that we might care about without updating the database.

lstat_array

$statinfo = stat_array( $fileinfo );
$uid = $statinfo->[STAT_UID];	# 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

may_have_changed( $finfo );

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

check_for_change

check_for_change( $finfo );

Like may_have_changed, indicates that a file may have changed, but retains the build info unless the signature actually changed. This is used in place of may_have_changed in order to prevent the unnecessary destruction of build info, which is expensive to compute in some cases.

mkdir

FileInfo::mkdir( $dirinfo );

Unless it exists, makes the directory specified by the FileInfo structure (and any parent directories that are necessary).

parent

$dirinfo = parent( $finfo );

Returns the directory containing the file.

read_directory

read_directory( $dirinfo );

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

relative_filename

$str = relative_filename( $fileinfo ); # Relative to current directory.
$str = relative_filename( $fileinfo, $dirinfo);
$n = relative_filename( $fileinfo, $dirinfo, $distance ); # Only count hops.

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 = stat_array( $fileinfo );
$statinfo = stat_array('filename');
$uid = $statinfo->[STAT_SIZE];	# 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.

dir_stat_array

Similar to stat_array, except that you need to call this instead if it's a directory and you need to get accurate timestamps or link counts.

FileInfo::unlink( $fileinfo );

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

AUTHOR

Gary Holt (holt@lnc.usc.edu)