chickadee » hfs+



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).



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-followDo not follow symlinks; operate on the symlink itself.


list-extended-attributes file #!rest optionsprocedure

List extended attribute names of FILE.

Returns a list containing one string per attribute name.

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


get-extended-attribute file attribute #!rest optionsprocedure

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! file attribute value #!rest optionsprocedure

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:

#:createRaise error if attribute exists.
#:replaceRaise 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! file attribute #!rest optionsprocedure

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:

#:silentDo 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 from to #!rest optionsprocedure

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:

#:statCOPYFILE_STATCopy POSIX stat(2) items
#:extended-attributesCOPYFILE_XATTRCopy HFS+ extended attributes
#:dataCOPYFILE_DATACopy file data
#:securityCOPYFILE_SECURITYEquivalent to #:acls #:stat
#:metadataCOPYFILE_METADATAEquivalent to #:extended-attributes #:security
#:allCOPYFILE_ALLEquivalent to #:metadata #:data

These options are flags which affect the copy operation:

#:checkCOPYFILE_CHECKDry-run; determine which metadata would be copied
#:packCOPYFILE_PACKPack metadata in FROM to TO in AppleDouble format
#:unpackCOPYFILE_UNPACKApply packed metadata in FROM to TO
#:exclusiveCOPYFILE_EXCLRaise error if TO already exists
#:no-follow-sourceCOPYFILE_NOFOLLOW_SRCDo not follow symlink on FROM
#:no-follow-destCOPYFILE_NOFOLLOW_DSTDo not follow symlink on TO
#:no-followCOPYFILE_NOFOLLOWEquivalent to #:no-follow-source #:no-follow-dest
#:moveCOPYFILE_MOVEUnlink FROM after the copy
#:unlinkCOPYFILE_UNLINKUnlink 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.



get-extended-attributes file #!rest optionsprocedure

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

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


clear-extended-attributes! file #!rest optionsprocedure

Remove all extended attributes from FILE.


copyfile-check from #!rest optionsprocedure

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:

statCOPYFILE_STATPOSIX stat(2) data
extended-attributesCOPYFILE_XATTRExtended 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.


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


pack-appledouble from to #!rest optionsprocedure

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 from to #!rest optionsprocedure

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


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


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" '
                         "courtesy of Chicken")
$ 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" ' #:silent)
(set-extended-attribute! "examples.scm" '
                         "courtesy of Chicken" #:create)
$ cat examples.scm/rsrc ; echo
courtesy of Chicken


Jim Ursetto

Version history



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.

Contents »