((section 2 "Outdated egg!" (p "This is an egg for CHICKEN 4, the unsupported old release.  You're almost certainly looking for " (int-link "/eggref/5/hfs+" "the CHICKEN 5 version of this egg") ", if it exists.") (p "If it does not exist, there may be equivalent functionality provided by another egg; have a look at the " (link "https://wiki.call-cc.org/chicken-projects/egg-index-5.html" "egg index") ". Otherwise, please consider porting this egg to the current version of CHICKEN.")) (section 2 "hfs+" (toc) (section 3 "Synopsis" (p (b "hfs+") " is a interface to the HFS+ filesystem on Mac OS X 10.4 and above.") (p "The current implementation provides access to HFS+ extended attributes, including resource forks.  It also implements an interface to " (tt "copyfile(3)") ".")) (section 3 "Interface" (section 4 "Overview" (p "All calls taking a " (tt "FILE") " argument accept either a filename or an open POSIX file descriptor.") (p "All calls taking an " (tt "ATTRIBUTE") " argument accept either a string or a symbol.") (p "All extended attribute calls allow the following options:") ((table "\n" (tr (td "#:no-follow") (td "Do not follow symlinks; operate on the symlink itself.")) "\n"))) (section 4 "list-extended-attributes" (def (sig (procedure "(list-extended-attributes file . options)" (id list-extended-attributes))) (p "List extended attribute names of " (tt "FILE") ".") (p "Returns a list containing one string per attribute name.") (pre " (list-extended-attributes \"examples.scm\" #:no-follow)\n ; => (\"com.apple.FinderInfo\" \"com.apple.ResourceFork\")"))) (section 4 "get-extended-attribute" (def (sig (procedure "(get-extended-attribute file attribute . options)" (id get-extended-attribute))) (p "Get the value of extended attribute " (tt "ATTRIBUTE") " from " (tt "FILE") ".") (p "Returns a string representing the value.  The string may contain binary data.") (p "Returns " (tt "#f") " if the attribute does not exist."))) (section 4 "set-extended-attribute!" (def (sig (procedure "(set-extended-attribute! file attribute value . options)" (id set-extended-attribute!))) (p "Set extended attribute " (tt "ATTRIBUTE") " on " (tt "FILE") " to " (tt "VALUE") ", and return an unspecified value.") (p (tt "VALUE") " may be a string or a blob.") (p "In addition to " (tt "#:no-follow") ", " (tt "set-extended-attribute!") " allows the following two mutually-exclusive options:") ((table "\n" (tr (td "#:create") (td "Raise error if attribute exists.")) "\n" (tr (td "#:replace") (td "Raise error if attribute does not exist.")) "\n")) (p "If neither option is specified, existing attribute values are silently overwritten.") (pre "(set-extended-attribute! \"examples.scm\" 'org.callcc \"courtesy of Chicken\")\n(get-extended-attribute \"examples.scm\" 'org.callcc)\n; => \"courtesy of Chicken\""))) (section 4 "remove-extended-attribute!" (def (sig (procedure "(remove-extended-attribute! file attribute . options)" (id remove-extended-attribute!))) (p "Remove extended attribute " (tt "ATTRIBUTE") " from " (tt "FILE") ".  By default, if " (tt "ATTRIBUTE") " does not exist, an error is signaled.") (p (tt "remove-extended-attribute!") " also accepts the following options:") ((table "\n" (tr (td "#:silent") (td "Do not raise an error if the attribute is missing.")) "\n")) (p "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."))) (section 4 "copyfile" (def (sig (procedure "(copyfile from to . options)" (id copyfile))) (p "Copies " (tt "FROM") " file to " (tt "TO") " file using the OS X " (tt "copyfile(3)") " API, preserving HFS+ metadata as specified in copyfile " (tt "OPTIONS") ". Always returns a true value, indicating success; failure will raise an error.  In the current implementation, both " (tt "FROM") " and " (tt "TO") " must be filenames; ports are not accepted.") (p "If the " (tt "#:check") " option is given, " (tt "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.") (p "If " (tt "#:pack") " is given, " (tt "copyfile") " serializes the desired metadata to an AppleDouble file named by the " (tt "TO") " argument.  " (tt "#:unpack") " is the opposite of " (tt "#: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 " (tt "#:check") " first to avoid this.")) (section 5 "copyfile options" (p "Refer to the " (link "http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/copyfile.3.html" "copyfile(3) manpage") " for details.") (p "These options specify " (i "which") " data to copy:") ((table "\n" (tr (td "#:acls") (td "COPYFILE_ACL") (td "Copy ACLs")) "\n" (tr (td "#:stat") (td "COPYFILE_STAT") (td "Copy POSIX stat(2) items")) "\n" (tr (td "#:extended-attributes") (td "COPYFILE_XATTR") (td "Copy HFS+ extended attributes")) "\n" (tr (td "#:data") (td "COPYFILE_DATA") (td "Copy file data")) "\n" (tr (td "#:security") (td "COPYFILE_SECURITY") (td "Equivalent to #:acls #:stat")) "\n" (tr (td "#:metadata") (td "COPYFILE_METADATA") (td "Equivalent to #:extended-attributes #:security")) "\n" (tr (td "#:all") (td "COPYFILE_ALL") (td "Equivalent to #:metadata #:data")) "\n")) (p "These options are flags which affect the copy operation:") ((table "\n" (tr (td "#:check") (td "COPYFILE_CHECK") (td "Dry-run; determine which metadata would be copied")) "\n" (tr (td "#:pack") (td "COPYFILE_PACK") (td "Pack metadata in FROM to TO in AppleDouble format")) "\n" (tr (td "#:unpack") (td "COPYFILE_UNPACK") (td "Apply packed metadata in FROM to TO")) "\n" (tr (td "#:exclusive") (td "COPYFILE_EXCL") (td "Raise error if TO already exists")) "\n" (tr (td "#:no-follow-source") (td "COPYFILE_NOFOLLOW_SRC") (td "Do not follow symlink on FROM")) "\n" (tr (td "#:no-follow-dest") (td "COPYFILE_NOFOLLOW_DST") (td "Do not follow symlink on TO")) "\n" (tr (td "#:no-follow") (td "COPYFILE_NOFOLLOW") (td "Equivalent to #:no-follow-source #:no-follow-dest")) "\n" (tr (td "#:move") (td "COPYFILE_MOVE") (td "Unlink FROM after the copy")) "\n" (tr (td "#:unlink") (td "COPYFILE_UNLINK") (td "Unlink TO prior to copy")) "\n"))) (section 5 "copyfile deficiencies" (p (tt "copyfile(3)") " is present on OS X 10.4, but not officially supported. On 10.4, we recommend using " (tt "copyfile") " only to pack and unpack metadata to and from AppleDouble format.  Certain options do not work properly: " (tt "#:move") " has no effect; " (tt "#: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.")))) (section 3 "Utilities" (section 4 "get-extended-attributes" (def (sig (procedure "(get-extended-attributes file . options)" (id get-extended-attributes))) (p "Returns an alist mapping attribute names (symbols) to values (strings).") (pre "(get-extended-attributes \"examples.scm\")\n;=> ((com.apple.FinderInfo . \"TEXTEMAx\")\n     (com.apple.ResourceFork . \"courtesy of Chicken\")\n     (org.callcc . \"courtesy of Chicken\"))"))) (section 4 "clear-extended-attributes!" (def (sig (procedure "(clear-extended-attributes! file . options)" (id clear-extended-attributes!))) (p "Remove all extended attributes from " (tt "FILE") "."))) (section 4 "copyfile-check" (def (sig (procedure "(copyfile-check from . options)" (id copyfile-check))) (p "Determines if any metadata is present in " (tt "FROM") " using the " (tt "#:check") " option to " (tt "copyfile") ".  Returns a list of symbols denoting metadata types that are present, from the following possibilities:") ((table "\n" (tr (td "acls") (td "COPYFILE_ACL") (td "ACLs")) "\n" (tr (td "stat") (td "COPYFILE_STAT") (td "POSIX stat(2) data")) "\n" (tr (td "extended-attributes") (td "COPYFILE_XATTR") (td "Extended attributes")) "\n")) (p "Note: another way to check merely for the presence of metadata is to use the " (tt "#:check") " option to copyfile.  A positive value means present, a zero value means not present.") (p "Example:") (pre "#;> (copyfile-check \"foo.txt\" #:metadata)\n(acls stat extended-attributes)\n#;> (copyfile-check \"foo.txt\" #:extended-attributes)\n(extended-attributes)\n#;> (copyfile-check \"bar.txt\" #:metadata)\n()\n#;> (> (copyfile \"foo.txt\" #f #:check #:metadata) 0)\n#t\n#;> (> (copyfile \"bar.txt\" #f #:check #:metadata) 0)\n#f"))) (section 4 "pack-appledouble" (def (sig (procedure "(pack-appledouble from to . options)" (id pack-appledouble))) (p "Serialize all HFS+ metadata (extended attributes, ACLs, stat(2) data) in " (tt "FROM") " to AppleDouble file " (tt "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.") (p "Extra options are passed into " (tt "copyfile") "; relevant ones might be " (tt "#:exclusive") ", " (tt "#:move") " and " (tt "#:no-follow") ", although " (tt "#:move") " and " (tt "#:no-follow") " do not work correctly under Tiger."))) (section 4 "unpack-appledouble" (def (sig (procedure "(unpack-appledouble from to . options)" (id unpack-appledouble))) (p "Unserialize all HFS+ metadata in AppleDouble file " (tt "FROM") " to " (tt "TO") ". Always returns true, or throws an error on I/O error.")))) (section 3 "Errors" (p "If the system API returns an unrecoverable error, a Scheme error will be raised.  The exception is of type " (tt "(exn file hfs+)") ".")) (section 3 "Notes" (section 4 "Resource forks" (p "Special care is required when writing resource fork data.  OS X will " (i "not") " truncate an existing resource fork if you write a shorter value, so you must remove the resource fork prior to writing.") (p "Incorrect example:") (pre "$ echo -n \"courtesy of the command-line\" > examples.scm/rsrc\n$ csi -q -R hfs+ <<EOF\n(set-extended-attribute! \"examples.scm\" 'com.apple.ResourceFork\n                         \"courtesy of Chicken\")\nEOF\n$ cat examples.scm/rsrc ; echo\ncourtesy of Chickenmand-line") (p "Correct example:") (pre "$ echo -n \"courtesy of the command-line\" > examples.scm/rsrc\n$ csi -q -R hfs+ <<EOF\n(remove-extended-attribute! \"examples.scm\" 'com.apple.ResourceFork #:silent)\n(set-extended-attribute! \"examples.scm\" 'com.apple.ResourceFork\n                         \"courtesy of Chicken\" #:create)\nEOF\n$ cat examples.scm/rsrc ; echo\ncourtesy of Chicken"))) (section 3 "Author" (p "Jim Ursetto")) (section 3 "Version history" (ul (li "0.3 Add copyfile interface") (li "0.2 Add #:silent option to remove, clear-extended-attributes!") (li "0.1 Initial release"))) (section 3 "License" (p "BSD.") (p "The Apple header " (link "http://www.opensource.apple.com/source/Libc/Libc-391.5.18/darwin/copyfile.h" "copyfile.h") " is not present on Tiger, so it is included in the egg.  The header is under the " (link "http://www.opensource.apple.com/apsl/" "Apple Public Source License") "."))))