NAME
File::System::Object - Abstract class that every file system module builds upon
DESCRIPTION
Before reading this documentation, you should see File::System.
File system modules extend this class to provide their functionality. A file system object represents a path in the file system and provides methods to locate other file system objects either relative to this object or from an absolute root.
If you wish to write your own file system module, see the documentation below for "MODULE AUTHORS".
FEATURES
The basic idea is that every file system is comprised of objects. In general, all file systems will contain files and directories. Files are object which contain binary or textual data, while directories merely contain more files. Because any given file system might have arbitrarily many (or few) different types and the types might not always fall into the "file" or "directory" categories, the File::System::Object
attempts to generalize this functionality into "content" and "container".
More advanced types might also be possible, e.g. symbolic links, devices, FIFOs, etc. However, at this time, no general solution is provided for handling these. (Individual file system modules may choose to add support for these in whatever way seems appropriate.)
Each file system object must specify a method stating whether it contains file content and another method stating whether it may contain child files. It is possible that a given file system implementation provides both simultaneously in a single object.
All file system objects allow for the lookup of other file system object by relative or absolute path names.
PATH METHODS
These methods provide the most generalized functionality provided by all objects. Each path specified to each of these must follow the rules given by the "FILE SYSTEM PATHS" section and may either be relative or absolute. If absolute, the operation performed will be based around the file system root. If relative, the operation performed depends on whether the object is a container or not. If a container, paths are considered relative to this object. If not a container, paths are considered relative to the parent of the current object.
- $root = $obj->root
-
Return an object for the root file system.
- $test = $obj->exists($path)
-
Check the given path
$path
and determine whether a file system object exists at that path. Return a true value if there is such an object or false otherwise. If$path
is undefined, the method should assume$obj->path
. - $file = $obj->lookup($path)
-
Lookup the given path
$path
and return a File::System::Object reference for that path orundef
. - @objs = $obj->glob($glob)
-
Find all files matching the given file globs
$glob
. The glob should be a typical csh-style file glob---see "FILE SYSTEM PATHS" below. Returns all matching objects. Note that globs are matched against '.' and '..', so care must be taken in crafting a glob that hopes to match files starting with '.'. (The typical solution to match all files starting with '.' is '.??*' under the assumption that one letter names are exceedingly rare and to be avoided, by the same logic.) - @files = $obj->find($want, @paths)
-
This is similar in function to, but very different in implementation from File::Find.
Find all files matching or within the given paths
@paths
or any subdirectory of those paths, which pass the criteria specifed by the$want
subroutine. If no@paths
are given, then "$obj
" is considered to be the path to search within.The
$want
subroutine will be called once for every file found under the give paths. The$want
subroutine may expect a single argument, the File::System::Object representing the given file. The$want
subroutine should return true to add the file to the returned list or false to leave the file out. The$want
subroutine may also set the value of$File::System::prune
to a true value in order to cause all contained child object to be skipped from search.The implementation should perform a depth first search so that children are checked immediately after their parent (unless the children are pruned, of course).
- $test = $obj->is_creatable($path, $type)
-
Returns true if the user can use the
create
method to create an object at$path
. - $new_obj = $obj->create($path, $type)
-
Attempts to create the object at the given path,
$path
with type$type
. Type is a string containing one or more case-sensitive characters describing the type. Here are the meanings of the possible characters:- d
-
Create a container (named "d" for "directory"). This can be used alone or with the "f" flag.
- f
-
Create a content object (named "f" for "file"). This can be used alone or with the "d" flag.
The
is_creatable
method may be used first to determine if the operation is possible.
METADATA METHODS
These are the general methods that every File::System::Object will provide.
- "$obj"
-
The stringify operator is overloaded so that if this value is treated as a string it will take on the value of the "
path
" property. - $name = $obj->is_valid
-
This method returns whether or not the object is still valid (i.e., the object it refers to still exists).
- $name = $obj->basename
-
This is the base name of the object (local name with the rest of the path stripped out). This value is also available as
$obj->get_property('basename')
. Note that the root objectbasename
should be'/'
. This fits better with unix, but actually differs from how Perl normally works. - $path = $obj->dirname
-
This the absolute canonical path up to but not including the base name. If the object represents the root path of the file system (i.e., .. = .), then it is possible that
basename
=dirname
=path
. This value is also available as$obj->get_property('dirname')
. - $path = $obj->path
-
This is the absolute canonical path to the object. This value is also available as
$obj->get_property('path')
. - $test = $obj->is_root
-
Returns true if this file system object represents the file system root.
- $parent_obj = $obj->parent
-
This is equivalent to:
$parent_obj = $obj->lookup($obj->dirname);
of you can think of it as:
$parent_obj = $obj->lookup('..');
This will return the file system object for the container. It will return itself if this is the root container.
- @keys = $obj->properties
-
Files may have an arbitrary set of properties associated with them. This method merely returns all the possible keys into the
get_property
method. - @keys = $obj->settable_properties
-
The keys returned by this method should be a subset of the keys returned by
properties
. These are the modules upon which it is legal to call theset_property
method. - $value = $obj->get_property($key)
-
Files may have an arbitrary set of properties associated with them. Many of the common accessors are just shortcuts to calling this method.
In every implementation it must return values for at least the following keys:
- basename
-
See
basename
for a description. When implementing this, you may wish to use thebasename_of_path
helper. - dirname
-
See
dirname
for a description. When implementing this, you may wish to use thedirname_of_path
helper. - object_type
-
See
object_type
for a description. - path
-
See
path
for a description.
- $obj->set_property($key, $value)
-
This sets the property given by
$key
to the value in$value
. This should fail if the given key is not found in$key
. - $obj->rename($name)
-
Renames the name of the file to the new name. This method cannot be used to move the file to a different location. See
move
for that. - $obj->move($to, $force)
-
Moves the file to the given path. After running, this object should refer to the file in it's new location. The
$to
argument must be a reference to the file system container (from the same file system!) to move this object into. This method must fail if$obj
is a container and$force
isn't given or is false.If you move a container using the
$force
option, and you have references to files held within that container, all of those references are probably now invalid. - $copy = $obj->copy($to, $force)
-
Copies the file to the given path. This object should refer to the original. The object representing the copy is returned. The c<$to> argument must refer to a reference to a file system container (from the same file system!). This method must fail if
$obj
is a container and$force
isn't given or is false. - $obj->remove($force)
-
Deletes the object from the file system entirely. In general, this means that the object is now completely invalid.
The
$force
option, when set to a true value, will remove containers and all their children and children of children, etc. - $type = $obj->object_type
-
Synonym for:
$type = $obj->get_property("object_type");
The value returned is a string containing an arbitrary number of characters describing the type of the file system object. The following are defined:
- d
-
This object may contain other files.
- f
-
This object may have content.
- $test = $obj->has_content
-
Returns a true value if the object contains file content. See "CONTENT METHODS" for additional methods.
This is equivalent to:
$obj->object_type =~ /f/;
- $test = $obj->is_container
-
Returns a true value if the object may container other objects. See "CONTAINER METHODS" for additional methods.
This is equivalent to:
$obj->object_type =~ /d/;
CONTENT METHODS
These methods are provided if has_content
returns a true value.
- $test = $obj->is_readable
-
This returns a true value if the file data can be read from---this doesn't refer to file permissions, but to actual capabilities. Can someone read the file? This literally means, "Can the file be read as a stream?"
- $test = $obj->is_seekable
-
This returns a true value if the file data is available for random-access. This literally means, "Are the individual bytes of the file addressable?"
- $test = $obj->is_writable
-
This returns a true value if the file data can be written to---this doesn't refer to file permissions, but to actual capabilities. Can someone write to the file? This literally means, "Can the file be overwritten?"
TODO Can this be inferred from
is_seekable
andis_appendable
? - $test = $obj->is_appendable
-
This returns a true value if the file data be appended to. This literally means, "Can the file be written to as a stream?"
- $fh = $obj->open($access)
-
Using the same permissions,
$access
, as FileHandle, this method returns a file handle or a false value on failure. - $content = $obj->content
- @lines = $obj->content
-
In scalar context, this method returns the whole file in a single scalar. In list context, this method returns the whole file as an array of lines (with the newline terminator defined for the current system left intact).
CONTAINER METHODS
These methods are provided if is_container
returns a true value.
- $test = $obj->has_children
-
Returns true if this container has any child objects (i.e., any child objects in addition to the mandatory '.' and '..').
- @paths = $obj->children_paths
-
Returns the relative paths of all children of the given container. The first two paths should always be '.' and '..', respectively. These two paths should be present within anything that returns true for
is_container
. - @children = $obj->children
-
Returns the child
File::System::Object
s for all the actual children of this container. This is approxmiately the same as:@children = map { $vfs->lookup($_) } grep !/^\.\.?$/, $obj->children_paths;
Notice that the objects for '.' and '..' are not returned.
- $child = $obj->child($name)
-
Returns the child
File::System::Object
that matches the given$name
orundef
.
FILE SYSTEM PATHS
Paths are noted as follows:
- "/"
-
The "/" alone represents the ultimate root of the file system.
- "filename"
-
File names may contain any character except the forward slash.
The underlying file system may not be able to cope with all characters. As such, it is legal for a file system module to throw an exception if it is not able to cope with a given file name.
Files can never have the name "." or ".." because of their special usage (see below).
- "filename1/filename2"
-
The slash is used to indicate that "filename2" is contained within "filename1". In general, the file system module doesn't really cope with "relative" file names, as might be indicated here. However, the File::System::Object does provide this functionality in a way.
- "."
-
The single period indicates the current file. It is legal to embed multiples of these into a file path (e.g., "/./././././././" is still the root). Technically, the "." may only refer to files that may contain other files (otherwise the term makes no sense). In canonical form, all "." will be resolved by simply being removed from the path. (For example, "/./foo/./bar/./." is "/foo/bar" in canonical form.)
The single period has another significant "feature". If a single period is placed at the start of a file name it takes on the Unix semantic of a "hidden file". Basically, all that means is that a glob wishing to match such a file must explicit start with a '.'.
- ".."
-
The double period indicates the parent container. In the case of the root container, the root's parent is itself. In canonical form, all ".." will be resolved by replacing everything up to the ".." with the parent path. (For example, "/../foo/../bar/baz/.." is "/bar" in canonical form.)
- "////"
-
All adjacent slashes are treated as a single slash. Thus, in canonical form, multiple adjacent slashes will be condenced into a single slash. (For example, "////foo//bar" is "/foo/bar" in canonical form.)
- "?"
-
This character has special meaning in file globs. In a file glob it will match exactly one of any character. If you want to mean literally "?" instead, escape it with a backslash.
- "*"
-
This character has special meaning in file globs. In a file glob it will match zero or more of any character non-greedily. If you want to mean literally "*" instead, escape it with a backslash.
- "{a,b,c}"
-
The curly braces can be used to surround a comma separated list of alternatives in file globbing. If you mean a literal set of braces, then you need to escape them with a backslash.
- "[abc0-9]"
-
The square brackets can be used to match any character within the given character class. If you mean a literal set of brackets, then you need to escape them with a backslash.
MODULE AUTHORS
If you wish to extend this interface to provide a new implementation, do so by creating a class that subclasses File::System::Object. That class must then define several methods. In the process you may override any method of this object, but make sure it adheres to the interface described in the documentation.
package My::File::Sytem::Implementation;
use strict;
use warnings;
use base qw( File::System::Object );
# define your implementation...
Below are lists of the methods you must or should define for your implementation. There is also a section below containing documentation for additional helper methods module authors should find useful, but general users probably won't.
MUST DEFINE
A subclass of File::System::Object must define the following methods:
- root
- is_creatable
- create
- is_valid
- properties
- settable_properties
- get_property
- set_property
- rename
- move
- copy
- remove
The following methods must be provided if your file system object implementation may return a true value for the has_content()
method.
- is_readable
- is_seekable
- is_writable
- is_appendable
- open
- content
The following methods are container methods and must be defined if your file system object implementation may return true from the is_container()
method.
- has_children
- children_paths
- children
- child
SHOULD DEFINE
A subclass of File::System::Object ought to consider defining better implementations of the following. Once all the methods above are defined correctly, these methods will work. However, they may not work efficiently.
Any methods not listed here or in "MUST DEFINE" have default implementations that are generally adequate. Also, the methods listed below in "HELPER METHODS" probably shouldn't be overriden.
- exists
- glob
HELPER METHODS
This class also provides a few helpers that may be useful to module uathors, but probably not of much use to typical users.
- $clean_path = $obj->normalize_path($messy_path)
-
This method creates a canonical path out of the given path
$messy_path
. This is the single most important method offered to module authors. It provides several things:If the path being canonified is relative, this method checks to see if the current object is a container. Paths are relative to the current object if the current object is container. Otherwise, the paths are relative to this object's parent.
Converts all relative paths to absolute paths.
Removes all superfluous '.' and '..' names so that it gives the most concise and direct name for the named file.
Enforces the principle that '..' applied to the root returns the root. This provides security by preventing users from getting to a file outside of the root (assuming that is possible for a given file system implementation).
Always, always, always use this method to clean up your paths.
- @matched_paths = $obj->match_glob($glob, @all_paths)
-
This will match the given glob pattern
$glob
against the given paths@all_paths
and will return only those paths that match. This provides a de facto implementation of globbing so that any module can provide this functionality without having to invent this functionality or rely upon a third party module. - $basename = $obj->basename_of_path($normalized_path)
-
Given a normalized path, this method will return the basename for that path according to the rules employed by
File::System
. (Essentially, they are the same as File::Basename, except that the basename of "/" is "/" rather than "".) - $dirname = $obj->dirname_of_path($normalized_path)
-
Given a normalized path, this method will return the dirname for that path according to the rules employed by
File::System
. (These should be identical to the rules used by File::Basename as far as I know.)
SEE ALSO
AUTHOR
Andrew Sterling Hanenkamp, <hanenkamp@users.sourceforge.net>
COPYRIGHT AND LICENSE
Copyright 2005 Andrew Sterling Hanenkamp. All Rights Reserved.
This software is distributed and licensed under the same terms as Perl itself.