TIP 118: Enhance [file attributes] and [file copy] on Mac OS X & BSD

Author:         Daniel A. Steffen <[email protected]>
State:          Final
Type:           Project
Vote:           Done
Created:        01-Nov-2002
Tcl-Version:    8.5
Tcl-Ticket:     626360


This TIP proposes a set of changes to [file attributes] and [file copy] to make them function better on MacOS X and other BSD-Unix systems.

Summary of Proposed Changes

This TIP proposes five sets of changes to [file attributes] and [file copy]:

  1. Add support for the Macintosh and Windows specific flag [file attributes -readonly] to Unixes that support the chflags() API, to allow the user immutable flag to be accessed & modified from Tcl.

  2. Add support for the Macintosh specific flags [file attributes -readonly -creator -type -hidden] to Mac OS X via the POSIX level API getattrlist().

  3. Add a new flag [file attributes -rsrclength] to Mac OS X and Mac OS 9 that gives the length of the resource fork of a file; 0 is the only value that this attribute can be set to, which strips the resource fork off a file.

  4. Change [file attributes] to return the list of attributes that can be retrieved without error for a given file, instead of aborting the whole command when any error occurs.

  5. Enhance [file copy] on Mac OS X (more precisely, the native file-system Tcl_FSCopyFile) to copy finder attributes (i.e. -readonly -creator -type -hidden) and resource forks transparently.


There is currently no way to access and modify HFS file-system metadata from Tcl on Mac OS X whereas Tcl on Mac OS 9 (or Classic) on the same Macintosh has that capability. Worse, [file copy] (and potentially even [file rename] if it results in a copy) on Mac OS X can be a destructive operation at present if it operates on a file that has essential data in its resource fork or its HFS metadata. This again in contrast to the same operations in Tcl on Mac OS 9 where this information is preserved. This TIP seeks to rectify these asymmetries in order to better hide such file-system related platform specificities from the scripter.


Additional information & examples:

  1. Unix versions that support chflags() include BSD >= 4.4 and Darwin/Mac OS X (where user immutable is the flag corresponding to the file locked state on the HFS file-system, which is what [file attributes -readonly] controls on Mac OS 9).

  2. The use of getattrlist() does not require linking with Carbon and thus allows access to HFS file-system metadata from Tcl on pure open-source Darwin systems (which is something no other scripting language can claim at present).

  3. The new attribute -rsrclength is useful to check whether a file has a resource fork and to calculate total file size on Mac OS 9 and X (note that [file size] returns the size of the data fork only). Stripping a file's resource fork (by setting -rsrclength to 0) is a common operation on Mac OS when dealing with files that are destined for other platforms. This is a feature that has been requested several times and given that it ties in well with the implementation of the other new attributes it comes at essentially no additional cost.

    % file attributes test
    -group admin -owner steffen -permissions 00644 -readonly 0 -creator Doug -type RSRC -hidden 0 -rsrclength 314
    % file attributes test -rsrclength 5
    setting nonzero rsrclength not supported
    % file attributes test -rsrclength 0
    % file attributes test
    -group admin -owner steffen -permissions 00644 -readonly 0 -creator Doug -type RSRC -hidden 0 -rsrclength 0
  4. On Mac OS X, trying to retrieve the new attributes -creator -type -rsrclength fails on non-regular files & directories (and on any file located on a non-HFS file-system that doesn't support getattrlist()). Returning only the list of attributes that are valid seems like much more sensible behaviour in this case than failing with an error and not returning anything. In the case where no valid attributes can be retrieved at all, the error returned by the last attempt is passed upstream, to preserve existing error handling. This proposed change in behaviour of [file attributes] seems necessary to allow the command to continue to work in a consistent way on all inputs and on all platforms; it should not impact existing code since for current attributes, failure to retrieve any one attribute is equivalent to failure to retrieve all attributes.

    % close [open test w]
    % file attributes test
    -group admin -owner steffen -permissions 00644 -readonly 0 -creator {} -type {} -hidden 0 -rsrclength 0
    % file delete test
    % file mkdir test
    % file attributes test
    -group admin -owner steffen -permissions 040755 -readonly 0 -hidden 0
    % file delete test
  5. Unlike the Finder and other HFS aware tools on Mac OS X, Tcl currently ignores HFS metadata and the resource fork, which will undoubtedly surprise scripters unpleasantly. [file copy] should hide such platform specificities and copy a file in the same way as the Finder:

    % file attributes test
    -group admin -owner steffen -permissions 00644 -readonly 0 -creator Doug -type RSRC -hidden 0 -rsrclength 314
    % file copy test test1
    % file attributes test1
    -group admin -owner steffen -permissions 00644 -readonly 0 -creator Doug -type RSRC -hidden 0 -rsrclength 314
    % file delete test1


Additional implementation details:

Reference Implementation

SourceForge patch #626360 http://sourceforge.net/tracker/index.php?func=detail&aid=626360&group_id=10894&atid=310894 implements this TIP as a patch to the current HEAD.

The patch has been tested on the SF compile-farm on hosts:

[Alpha] Linux 2.4 (Debian 3.0): where chflags() and getattrlist() are not available and no ill effects ensue (i.e. no new tests fail).

[x86] FreeBSD (4.7-RC): where chflags() is available and [file attributes -readonly] can successfully be interrogated (but not set due to permission issues at SourceForge). No new tests fail.

as well as on Mac OS 9, X 10.1.5 and X 10.2.1, where all the new functionality is available and no new tests fail.


This document has been placed in the public domain.