+/* ---------------------------
+ SFM structure
+ */
+#if 0
+typedef struct {
+ byte afpi_Signature[4]; /* Must be 0x00504641 */
+ byte afpi_Version[4]; /* Must be 0x00010000 */
+ byte afpi_Reserved1[4];
+ byte afpi_BackupTime[4]; /* Backup time for the file/dir */
+ byte finderinfo[32]; /* Finder info */
+ byte afpi_ProDosInfo[6]; /* ProDos Info */
+ byte afpi_Reserved2[6];
+} sfm_info;
+#endif
+
+static int ad_header_sfm_read(struct adouble *ad, struct stat *hst)
+{
+ char *buf = ad->ad_data;
+ const struct entry *eid;
+ u_int16_t nentries;
+ int len;
+ ssize_t header_len;
+ static int warning = 0;
+ struct stat st;
+
+ /* read the header */
+ if ((header_len = adf_pread( ad->ad_md, buf, sizeof(ad->ad_data), 0)) < 0) {
+ return -1;
+ }
+ if (header_len != AD_SFM_LEN) {
+ errno = EIO;
+ return -1;
+ }
+
+ memcpy(&ad->ad_magic, buf, sizeof( ad->ad_magic ));
+ memcpy(&ad->ad_version, buf + 4, sizeof( ad->ad_version ));
+
+ /* FIXME in the the great Microsoft tradition they aren't in network order */
+#if 0
+ if (ad->ad_magic == SFM_MAGIC && ad->ad_version == AD_VERSION1) {
+ if (!warning) {
+ LOG(log_debug, logtype_default, "notice: fixing up byte-swapped v1 magic/version.");
+ warning++;
+ }
+
+ } else {
+ ad->ad_magic = ntohl( ad->ad_magic );
+ ad->ad_version = ntohl( ad->ad_version );
+ }
+#endif
+ if ((ad->ad_magic != SFM_MAGIC) || ((ad->ad_version != AD_VERSION1) )) {
+ errno = EIO;
+ LOG(log_debug, logtype_default, "ad_header_sfm_read: can't parse AppleDouble header.");
+ return -1;
+ }
+
+ /* reinit adouble table */
+ eid = entry_order_sfm;
+ while (eid->id) {
+ ad->ad_eid[eid->id].ade_off = eid->offset;
+ ad->ad_eid[eid->id].ade_len = eid->len;
+ eid++;
+ }
+
+ /* steal some prodos for attribute */
+ {
+
+ u_int16_t attribute;
+ memcpy(&attribute, buf + 48 +4, sizeof(attribute));
+ ad_setattr(ad, attribute );
+ }
+
+ if (ad->ad_resource_fork.adf_fd != -1) {
+ /* we have a resource fork use it rather than the metadata */
+ if (fstat(ad->ad_resource_fork.adf_fd, &st) < 0) {
+ /* XXX set to zero ?
+ ad->ad_rlen = 0;
+ */
+ return 1;
+ }
+ ad->ad_rlen = st.st_size;
+ hst = &st;
+ }
+ else if (hst == NULL) {
+ hst = &st;
+ if (fstat(ad->ad_md->adf_fd, &st) < 0) {
+ return 1; /* fail silently */
+ }
+ }
+
+ /* fix up broken dates */
+ if (ad->ad_version == AD_VERSION1) {
+ u_int32_t aint;
+
+ /* check to see if the ad date is wrong. just see if we have
+ * a modification date in the future. */
+ if (((ad_getdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, &aint)) == 0) &&
+ (aint > TIMEWARP_DELTA + hst->st_mtime)) {
+ ad_setdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, aint - AD_DATE_DELTA);
+ ad_getdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, &aint);
+ ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, aint - AD_DATE_DELTA);
+ ad_getdate(ad, AD_DATE_BACKUP | AD_DATE_UNIX, &aint);
+ ad_setdate(ad, AD_DATE_BACKUP | AD_DATE_UNIX, aint - AD_DATE_DELTA);
+ }
+ }
+
+ return 0;
+}
+