hfs+

  1. hfs+
    1. Synopsis
    2. Interface
      1. Overview
      2. list-extended-attributes
      3. get-extended-attribute
      4. set-extended-attribute!
      5. remove-extended-attribute!
      6. copyfile
        1. copyfile options
        2. copyfile deficiencies
    3. Utilities
      1. get-extended-attributes
      2. clear-extended-attributes!
      3. copyfile-check
      4. pack-appledouble
      5. unpack-appledouble
    4. Errors
    5. Notes
      1. Resource forks
    6. Author
    7. Version history
    8. License

Synopsis

hfs+ is a interface to the HFS+ filesystem on Mac OS X 10.4 and above.

The current implementation provides access to HFS+ extended attributes, including resource forks. It also implements an interface to copyfile(3).

Interface

Overview

All calls taking a FILE argument accept either a filename or an open POSIX file descriptor.

All calls taking an ATTRIBUTE argument accept either a string or a symbol.

All extended attribute calls allow the following options:

#:no-follow Do not follow symlinks; operate on the symlink itself.

list-extended-attributes

[procedure] (list-extended-attributes file . options)

List extended attribute names of FILE.

Returns a list containing one string per attribute name.

 (list-extended-attributes "examples.scm" #:no-follow)
 ; => ("com.apple.FinderInfo" "com.apple.ResourceFork")

get-extended-attribute

[procedure] (get-extended-attribute file attribute . options)

Get the value of extended attribute ATTRIBUTE from FILE.

Returns a string representing the value. The string may contain binary data.

Returns #f if the attribute does not exist.

set-extended-attribute!

[procedure] (set-extended-attribute! file attribute value . options)

Set extended attribute ATTRIBUTE on FILE to VALUE, and return an unspecified value.

VALUE may be a string or a blob.

In addition to #:no-follow, set-extended-attribute! allows the following two mutually-exclusive options:

#:create Raise error if attribute exists.
#:replace Raise error if attribute does not exist.

If neither option is specified, existing attribute values are silently overwritten.

(set-extended-attribute! "examples.scm" 'org.callcc "courtesy of Chicken")
(get-extended-attribute "examples.scm" 'org.callcc)
; => "courtesy of Chicken"

remove-extended-attribute!

[procedure] (remove-extended-attribute! file attribute . options)

Remove extended attribute ATTRIBUTE from FILE. By default, if ATTRIBUTE does not exist, an error is signaled.

remove-extended-attribute! also accepts the following options:

#:silent Do not raise an error if the attribute is missing.

The #:silent option is useful if, for example, you wish to truncate a resource fork but are not sure if one is already present. See below for an example.

copyfile

[procedure] (copyfile from to . options)

Copies FROM file to TO file using the OS X copyfile(3) API, preserving HFS+ metadata as specified in copyfile OPTIONS. Always returns a true value, indicating success; failure will raise an error. In the current implementation, both FROM and TO must be filenames; ports are not accepted.

If the #:check option is given, copyfile will determine which metadata would be copied from the source, without copying it. It returns zero if there is no corresponding metadata, and a positive value if there is metadata to copy. Either way, the return value is true, indicating success.

If #:pack is given, copyfile serializes the desired metadata to an AppleDouble file named by the TO argument. #:unpack is the opposite of #:pack. This AppleDouble file is the same format as that produced when writing a file to a non-HFS+ filesystem, such as across a network to NFS or Samba. Because an AppleDouble file is always created when packing, even if there is no metadata to copy, you may wish to use #:check first to avoid this.

copyfile options

Refer to the copyfile(3) manpage for details.

These options specify which data to copy:

#:acls COPYFILE_ACL Copy ACLs
#:stat COPYFILE_STAT Copy POSIX stat(2) items
#:extended-attributes COPYFILE_XATTR Copy HFS+ extended attributes
#:data COPYFILE_DATA Copy file data
#:security COPYFILE_SECURITY Equivalent to #:acls #:stat
#:metadata COPYFILE_METADATA Equivalent to #:extended-attributes #:security
#:all COPYFILE_ALL Equivalent to #:metadata #:data

These options are flags which affect the copy operation:

#:check COPYFILE_CHECK Dry-run; determine which metadata would be copied
#:pack COPYFILE_PACK Pack metadata in FROM to TO in AppleDouble format
#:unpack COPYFILE_UNPACK Apply packed metadata in FROM to TO
#:exclusive COPYFILE_EXCL Raise error if TO already exists
#:no-follow-source COPYFILE_NOFOLLOW_SRC Do not follow symlink on FROM
#:no-follow-dest COPYFILE_NOFOLLOW_DST Do not follow symlink on TO
#:no-follow COPYFILE_NOFOLLOW Equivalent to #:no-follow-source #:no-follow-dest
#:move COPYFILE_MOVE Unlink FROM after the copy
#:unlink COPYFILE_UNLINK Unlink TO prior to copy
copyfile deficiencies

copyfile(3) is present on OS X 10.4, but not officially supported. On 10.4, we recommend using copyfile only to pack and unpack metadata to and from AppleDouble format. Certain options do not work properly: #:move has no effect; #:no-follow has no effect during a pack/unpack; #:data will fail with an error (and may even cause a segfault). There may be other deficiencies.

Utilities

get-extended-attributes

[procedure] (get-extended-attributes file . options)

Returns an alist mapping attribute names (symbols) to values (strings).

(get-extended-attributes "examples.scm")
;=> ((com.apple.FinderInfo . "TEXTEMAx")
     (com.apple.ResourceFork . "courtesy of Chicken")
     (org.callcc . "courtesy of Chicken"))

clear-extended-attributes!

[procedure] (clear-extended-attributes! file . options)

Remove all extended attributes from FILE.

copyfile-check

[procedure] (copyfile-check from . options)

Determines if any metadata is present in FROM using the #:check option to copyfile. Returns a list of symbols denoting metadata types that are present, from the following possibilities:

acls COPYFILE_ACL ACLs
stat COPYFILE_STAT POSIX stat(2) data
extended-attributes COPYFILE_XATTR Extended attributes

Note: another way to check merely for the presence of metadata is to use the #:check option to copyfile. A positive value means present, a zero value means not present.

Example:

#;> (copyfile-check "foo.txt" #:metadata)
(acls stat extended-attributes)
#;> (copyfile-check "foo.txt" #:extended-attributes)
(extended-attributes)
#;> (copyfile-check "bar.txt" #:metadata)
()
#;> (> (copyfile "foo.txt" #f #:check #:metadata) 0)
#t
#;> (> (copyfile "bar.txt" #f #:check #:metadata) 0)
#f

pack-appledouble

[procedure] (pack-appledouble from to . options)

Serialize all HFS+ metadata (extended attributes, ACLs, stat(2) data) in FROM to AppleDouble file TO. Returns false when no metadata was present (and does not write a file) or true if metadata was present (and a file is written). May also throw a file error.

Extra options are passed into copyfile; relevant ones might be #:exclusive, #:move and #:no-follow, although #:move and #:no-follow do not work correctly under Tiger.

unpack-appledouble

[procedure] (unpack-appledouble from to . options)

Unserialize all HFS+ metadata in AppleDouble file FROM to TO. Always returns true, or throws an error on I/O error.

Errors

If the system API returns an unrecoverable error, a Scheme error will be raised. The exception is of type (exn file hfs+).

Notes

Resource forks

Special care is required when writing resource fork data. OS X will not truncate an existing resource fork if you write a shorter value, so you must remove the resource fork prior to writing.

Incorrect example:

$ echo -n "courtesy of the command-line" > examples.scm/rsrc
$ csi -q -R hfs+ <<EOF
(set-extended-attribute! "examples.scm" 'com.apple.ResourceFork
                         "courtesy of Chicken")
EOF
$ cat examples.scm/rsrc ; echo
courtesy of Chickenmand-line

Correct example:

$ echo -n "courtesy of the command-line" > examples.scm/rsrc
$ csi -q -R hfs+ <<EOF
(remove-extended-attribute! "examples.scm" 'com.apple.ResourceFork #:silent)
(set-extended-attribute! "examples.scm" 'com.apple.ResourceFork
                         "courtesy of Chicken" #:create)
EOF
$ cat examples.scm/rsrc ; echo
courtesy of Chicken

Author

Jim Ursetto

Version history

License

BSD.

The Apple header copyfile.h is not present on Tiger, so it is included in the egg. The header is under the Apple Public Source License.