Dan Ellis : Resources :

Decoding Dates from .AppleDouble files


I had a problem: I was writing scripts to convert my digital photos into web pages, and I wanted to include the exact date and time that the photo was taken as part of the annotation.

My upload procedure stores this as the 'creation time' of the file on my Macintosh. I copy these files onto my Unix system using netatalk to make the Unix box work as a Macintosh-style fileserver for my mac. This means that I can both back up my mac, and access the jpeg images from my unix scripts.

But what about the dates? It turns out that although the MacOS stores the creation date and last modification date for each file, Unix instead stores the last modification date and the last access (read) date, but *not* the creation date. Consequently, the MacOS creation date was not reflected in the Unix directory structure. In fact, netatalk doesn't even try to make the last-modiication dates match, since it has to use a separate data structure anyway.

After a long while, I managed to reverse-engineer the netatalk files to locate the creation and modification dates, which are stored in the 'parallel file' under the .AppleDouble subdirectory that netatalk creates for all mac files.

I wrote a little Tcl program to extract the dates and format them nicely. It turns out that these dates are stored as number of seconds since jan 01 2000 GMT, much to my surprise - must be a MacOS 9 thing or something.

Anyway, here's the code. You pass it the name of an AppleDouble file and it returns the creation and modification dates. You can get them formatted differently by giving it a format string as the first argument, but you'll have to look at the syntax of Tcl's "clock format" command to figure out how. Hope it's some use.

Update 2002-05-05: This is just a hack that happens to work with the AppleDouble files written by this version of NetAtalk and my MacOS. For a more general solution, we need to parse the actual data in the AppleDouble file according to this specification (originally found at http://www.nulib.com/library/FTN.e000023.htm).


#!/usr/local/bin/tclsh
#
# adtodate
#
# Read the appledouble extension and report the created/modified dates within
# 
# 2002-02-08 [email protected]
# $Header: /homes/dpwe/public_html/resources/RCS/appledoubledates.html,v 1.2 2002/06/05 14:24:15 dpwe Exp $

if {[llength $argv] == 1} {
    set cfmt "%a %b %d %H:%M:%S %Z %Y"
    set fname $argv
} elseif {[llength $argv] == 2} {
    set cfmt [lindex $argv 0]
    set fname [lindex $argv 1]
} else {
    puts stderr "Usage: $argv0 \[formatstring\] AppleDoubleFile"
    exit 1
}

set f [open $fname "r"]
fconfigure $f -translation binary

set dummy [read $f 541]

set ctime [read $f 4]

set mtime [read $f 4]

close $f

# Convert to integers

binary scan $ctime "I" ctimesecs
binary scan $mtime "I" mtimesecs

set baseclock [clock scan "00:00:00 Jan 01 2000 GMT"]

puts "ctime [clock format [expr $baseclock + $ctimesecs] -format $cfmt]"
puts "mtime [clock format [expr $baseclock + $mtimesecs] -format $cfmt]"


Dan Ellis <[email protected]>
2002-02-08