# filename.h | documentation

    #charset "us-ascii"
    #pragma once

    /*
     *   Copyright (c) 2001, 2006 Michael J. Roberts
     *
     *   This file is part of TADS 3.
     *
     *   This header defines the FileName intrinsic class.
     */

    /* include our base class definition */
    #include "systype.h"

    /* if we're using FileName objects, we probably want File objects as well */
    #include "file.h"

    /* ------------------------------------------------------------------------ */
    /*
     *   A FileName represents the name of a file in the local operating
     *   system.  The File object methods that take filename specifications
     *   accept FileName objects as well as ordinary strings.
     *
     *   It's easier to write portable code if you manipulate filenames using
     *   the FileName class rather than using ordinary strings.  TADS runs on
     *   several different operating systems with differing syntax rules for
     *   constructing file names and directory paths.  The FileName class
     *   handles the different rules that apply on each system.
     *
     *   Construction:
     *
     *.    new FileName() - creates a FileName object representing the working
     *.            directory (e.g., '.' on Unix or Windows)
     *
     *.    new FileName(str) - creates a FileName from a string 'str' giving a
     *.            file path in local filename syntax.
     *
     *.    new FileName(path, name) - creates a FileName from a path and
     *.            a file name.  'path' and 'name' can each be a FileName
     *.            object or a string using local filename syntax.  The
     *.            new object represents the combined path
     *
     *.    new FileName(specialID) - creates a FileName from one of the special
     *.            file identifiers defined in file.h.
     *
     *   You can also use the fromUniversal() static method, which creates a
     *   FileName from a path in universal (URL-style) notation.
     *
     *   String conversions: using a FileName object in a context where a
     *   string is required (such as displaying it) automatically converts the
     *   object to a string giving the local file name path.
     *
     *   Operators:
     *
     *.    FileName + string  => yields a new FileName object combining
     *.            the path given by FileName and the string naming a file,
     *.            in local naming conventions.
     *
     *.    FileName + FileName  => yields a new FileName object combining
     *.            the two names, treating the first as a directory path.
     *
     *.    FileName == string (or !=) OR
     *.    FileName == FileName
     *.            Compares the FileName to the string or other filename path.
     *.            This does a superficial comparison of the path contents,
     *.            without attempting to correlate the path to the actual file
     *.            system layout.  For example, it doesn't resolve symbolic
     *.            links on Unix or apply working directories to local paths.
     */
    intrinsic class FileName 'filename/030000' : Object
    {
        /*
         *   Get the filename.  This returns a string with the filename this
         *   object represents, in the local syntax used by the host operating
         *   system, including the path and base filename portions.  (This is
         *   the same string returned for toString(self), and the same string
         *   used if the filename is displayed as though it were a string, such
         *   as with "<< >>".)
         */
        getName();

        /*
         *   Get the base filename portion, without the path.  This returns a
         *   string giving the filename without any directory location
         *   information; for a Unix-style path or Windows-style path, this is
         *   simply the last element of the path.
         */
        getBaseName();

        /*
         *   Get the path portion name, without the file name.  This returns a
         *   FileName object containing the path portion of the file name, with
         *   the last path element removed.  If the path only contains one path
         *   element (so it contains only a file name, not a directory path),
         *   this returns nil.
         */
        getPath();

        /*
         *   Create a new FileName object from a path in universal URL-style
         *   syntax.  Path elements are separated with "/" characters.  The
         *   universal path syntax is converted to the local path notation for
         *   the new FileName object.
         */
        static fromUniversal(path);

        /*
         *   Get the universal URL-style notation for this file name.  Returns
         *   a string giving the universal notation for the file name
         *   (including any path portion).
         */
        toUniversal();

        /*
         *   Add a path element (a string or FileName object) to the end of
         *   this filename, yielding a new FileName object with the combined
         *   path.  Uses the correct local syntax to combine the path elements.
         *   This yields the same results as FileName + element.
         *
         *   The new FileName object is in canonical form, meaning that any
         *   internal relative path elements (e.g., Unix "." and "..") are
         *   processed by combining them with adjacent elements as appropriate.
         *   For example, adding ".." to the Unix path "a/b/c" yields "a/b".
         */
        addToPath(element);

        /*
         *   Is this an absolute path on the local system?  An absolute path is
         *   one that contains a root folder specification, such as a Unix path
         *   starting with "/", Windows path starting with "C:\", or a Windows
         *   UNC name such as "\\SERVER\SHARE".
         *
         *   Note that a Windows path can start with a drive letter without
         *   being absolute, as in "C:path\file" (that's relative to the
         *   working folder on the C: drive), and can start with a backslash
         *   without being absolute, as in "\path\file" (that's relative to the
         *   working drive letter).  Similar subtleties might apply to other
         *   systems; this routine figures it out using local conventions.
         */
        isAbsolute();

        /*
         *   Get a FileName giving the absolute path to this file.  This
         *   applies the current working directory and/or volume (e.g., drive
         *   letter on Windows) to produce the full path in absolute notation,
         *   using the appropriate syntax for the local operating system.  If
         *   the name is already in absolute format, the result will usually be
         *   unchanged, although the exact syntax might be modified on some
         *   systems to change the name to a more canonical format.
         *
         *   If it's not possible to convert the filename into an absolute
         *   path, returns nil.
         */
        getAbsolutePath();

        /*
         *   Get the list of root directories on the local system.  Returns a
         *   list of FileName objects representing the root directories.  The
         *   list only includes roots that are accessible under the file safety
         *   settings for getFileInfo(); note that other operations, such as
         *   listing the directory contents, might not be allowed even if the
         *   metdata are accessible.
         *
         *   Most Unix-like systems only have one root directory, usually
         *   called '/'.  Many other systems have a separate root directory for
         *   each volume or device; for example, Windows has a root folder for
         *   each drive letter, so the root list might contain paths like C:\,
         *   D:\, etc.  Some systems have no concept of a root directory at
         *   all, in which case the result will be an empty list; this is the
         *   case for the network storage server.
         */
        static getRootDirs();

       /*
        *   Get the type of the file.  If the file named by this object exists,
        *   returns an integer with a bitwise combination of FileTypeXxx values
        *   indicating the type of the file.  If the file doesn't exist, or
        *   can't be accessed due to file system permissions or some other
        *   operating system error, the return value is nil.  Note that it's
        *   also possible for the return value to be zero, which means
        *   something different from nil: zero means that the file exists, but
        *   it doesn't fit any of the FileTypeXxx classifications.
        *
        *   If the file is a symbolic link, the method's behavior depends on
        *   'asLink'.  A symbolic link is a special type of file supported on
        *   some operating systems that serves as a pointer or proxy for
        *   another file.  If the file is a link, and 'asLink' is omitted or
        *   nil, the method returns information on the target of the link; this
        *   is the default because symbolic links in generally act as
        *   transparent proxies for their targets, so for most purposes a
        *   caller should be interested in the target file's metadata.
        *   However, a symbolic link also has a separate identity of its own as
        *   a link, so callers might sometimes be interested in the metadata
        *   for the link rather than its target.  To get information on the
        *   link itself, set 'asLink' to true.  'asLink' has no effect for
        *   ordinary non-link files, and also has no effect for "hard" links on
        *   systems that support those as well.
        *
        *   Most of the FileTypeXxx bits are mutually exclusive, but it's
        *   possible that more than one bit will be set, so test using '&'
        *   (e.g., (f.getFileType() & FileTypeDir)).
        *
        *   The file safety settings must allow read access to the file.
        */
        getFileType(followLinks?);

        /*
         *   Get extended information on the file named by this object.  This
         *   retrieves the size of the file, timestamps, and the file's type,
         *   and returns the information as a FileInfo object (see file.t).  If
         *   the file doesn't exist, or can't be accessed for some other reason
         *   at the operating system level, returns nil.
         *
         *   'asLink' has the same meaning as in getFileType(), and has no
         *   effect at all unless the file named is a symbolic link.
         *
         *   The file safety settings must allow read access to the file.
         */
        getFileInfo(followLinks?);

        /*
         *   Delete the disk file named by this object.  The file safety level
         *   must allow write access to the file; a file safety exception is
         *   thrown if not.
         */
        deleteFile();

        /*
         *   Rename or move the file.  This changes the name and/or file path
         *   location of the file named by 'self' to the given new path, which
         *   can be a string giving a filename in local path notation, or a
         *   FileName object with the new name.  The file safety settings must
         *   allow write access to both the original file and the new file.
         *   The new file must not already exist.
         */
        renameFile(newname);

        /*
         *   Get a list of files in the directory named by this object.  Returns
         *   a list of FileName objects giving the names of the files.
         *
         *   The file safety settings must allow read access to the directory's
         *   contents.
         *
         *   On systems where the file system has special directory entries for
         *   relative links, such as "." and ".." on Windows and Unix-likes, the
         *   listing that this method returns will include entries for those
         *   relative links.  Be careful with these when performing recursive
         *   directory traversals, since recursing into "." or ".." would cause
         *   an infinite loop.  You can test an entry in the returned list to see
         *   if it's one of these special links by calling its getFileInfo()
         *   method, and testing the specialLink property of the returned
         *   information object.  Not that if you're performing a recursive
         *   directory traversal, it might be easier to use forEachFile() with
         *   the 'recurse' argument flag set to true.
         */
        listDir();

        /*
         *   Invoke a callback for each file in the directory named by this
         *   object.  'func' is a callback function; for each file in the
         *   directory, this is invoked as func(f), where 'f' is a FileName
         *   object describing the file.  If 'recursive' is true, the method
         *   recursively scans the contents of subdirectories; if 'recursive'
         *   is nil or is omitted, only the direct contents of the directory
         *   are scanned.
         */
        forEachFile(func, recursive?);

        /*
         *   Create a directory with the name contained in this object.  The
         *   file safety settings must allow write access to the parent folder.
         *
         *   If 'createParents' is specified, it's a true or nil value
         *   specifying whether or not to create intermediate parent
         *   directories.  The default is nil if it's omitted.  If it's true,
         *   and 'dirname' contains multiple path elements, any parents of the
         *   named directory that don't already exist will be created as well.
         *   For example, on Linux, if dirname is '/a/b/c', and directory '/a'
         *   exists but not '/a/b', the routine will first create '/a/b' and
         *   then create '/a/b/c'.
         */
        createDirectory(createParents?);

        /*
         *   Remove the directory named by this object.  The file safety settings
         *   must allow write access to the directory.
         *
         *   If 'removeContents' is provided, it's a true or nil value specifying
         *   whether or not to delete the contents of the directory before
         *   deleting the directory itself.  If this is true, and the directory
         *   contains any files or subdirectories, the routine will attempt to
         *   delete those contents before deleting the directory itself.  Any
         *   subdirectories will be recursively emptied and removed.  For obvious
         *   reasons, use caution when using this flag.  If any of the contents
         *   can't be deleted, the function will stop and throw an error.  Note
         *   that if this occurs, the function might have successfully deleted
         *   some of the contents of the directory before encountering the error;
         *   those deletions won't be undone.
         *
         *   If 'removeContents' is omitted or nil, and the directory isn't
         *   already empty, the method simply returns nil (indicating failure)
         *   without deleting anything.  This is the default because it helps
         *   avoid accidentally deleting contents that the application didn't
         *   explicitly choose to remove.  (Special system files that are always
         *   present, such as "." and ".." on Unix, don't count when determining
         *   if the directory is empty.)
         */
        removeDirectory(removeContents?);
    }

    /* ------------------------------------------------------------------------ */
    /*
     *   File type constants.  These are returned from getFileType(), and from
     *   getFileInfo() in the fileType property.  These are bit flags, so test
     *   for them using (fileType & FileTypeXxx).
     */

    /* ordinary file (on disk or similar storage device) */
    #define FileTypeFile   0x0001

    /* directory (folder) */
    #define FileTypeDir    0x0002

    /* character-mode device (e.g., console) */
    #define FileTypeChar   0x0004

    /* block-mode device (e.g., Linux raw disk device) */
    #define FileTypeBlock  0x0008

    /* pipe (sometimes called a FIFO) or similar interprocess channel */
    #define FileTypePipe   0x0010

    /* network socket */
    #define FileTypeSocket 0x0020

    /* symbolic link (a filename that links to another file or directory) */
    #define FileTypeLink   0x0040

    /* special system-defined directory link to self (such as Unix ".") */
    #define FileTypeSelfLink    0x0080

    /* special system-defined parent directory link (such as Unix "..") */
    #define FileTypeParentLink  0x0100

    /* ------------------------------------------------------------------------ */
    /*
     *   File attribute constants.  These are returned from getFileInfo() in the
     *   fileAttrs property.  These are bit flags, so test for them using
     *   (fileAttrs & FileAttrXxx).
     */

    /*
     *   Hidden file.  When this attribute is set, the file should be omitted
     *   from default views in the user interface and from wildcard matches in
     *   user commands (e.g., "rm *").  On some systems, a naming convention is
     *   used to mark files as hidden, such as ".xxx" files on Unix; on other
     *   systems, there's formal file system metadata corresponding to this
     *   attribute, such as on Windows.  Note that actually hiding files marked
     *   as hidden is up to the user interface; at a programmatic level, hidden
     *   files are treated the same as any other file, and in particular they're
     *   included in listDir() results.  It's up to the caller to decide whether
     *   or not to filter hidden files out of listDir() results, and if so to do
     *   the filtering.  The hidden attribute isn't enforced as a security or
     *   permissions mechanism in the file system; it doesn't prevent a user from
     *   explicitly viewing or deleting a file.  It's merely designed as a
     *   convenience for the user, to reduce clutter in normal directory listings
     *   by filtering out system or application files (such as preference files,
     *   caches, or indices) that the user doesn't normally access directly.
     */
    #define FileAttrHidden 0x0001

    /*
     *   System file.  This is a file system attribute on some systems (notably
     *   Windows) that marks a file as belonging to or being part of the
     *   operating system.  For practical purposes, system files should be
     *   treated the same as hidden files; the only reason we distinguish
     *   "system" as a separate attribute from "hidden" is to allow applications
     *   to display the two attributes separately when presenting file
     *   information to the user, who might expect to see both attributes on
     *   systems where both exist.  There's no equivalent of this attribute on
     *   most systems other than DOS and Windows; it won't ever appear in a
     *   file's attributes on systems where there's no equivalent.
     */
    #define FileAttrSystem 0x0002

    /*
     *   The file is readable by the current process.  If this is set, it means
     *   that the program has the necessary ownership and access privileges to
     *   read the file.  It's not guaranteed that a given attempt to read the
     *   file will actually succeed, since other conditions could arise, such as
     *   physical media errors or locking by another process that prevents
     *   concurrent access.
     */
    #define FileAttrRead   0x0004

    /*
     *   The file is writable by the current process.  If this is set, it means
     *   that the program has the necessary ownership and access privileges to
     *   write to the file.  It's not guaranteed that a given attempt to write to
     *   the file will actually succeed, since other conditions could arise, such
     *   as insufficient disk space, physical media errors, or locking by another
     *   process that prevents concurrent access.
     */
    #define FileAttrWrite  0x0008

TADS 3 Library Manual
Generated on 5/16/2013 from TADS version 3.1.3