+ if (off > st.st_size) {
+ LOG(log_error, logtype_default, "ad_v1tov2: invalid resource fork offset. (off: %u)", off);
+ errno = EIO;
+ goto bail_lock;
+ }
+
+ if (ad->ad_eid[ADEID_RFORK].ade_len > st.st_size - off) {
+ LOG(log_error, logtype_default, "ad_v1tov2: invalid resource fork length. (rfork len: %u)", ad->ad_eid[ADEID_RFORK].ade_len);
+ errno = EIO;
+ goto bail_lock;
+ }
+
+ if ((void *) (buf = (char *)
+ mmap(NULL, st.st_size + shiftdata,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==
+ MAP_FAILED) {
+ goto bail_lock;
+ }
+
+ /* last place for failure. */
+
+ if (sys_ftruncate(fd, st.st_size + shiftdata) < 0) {
+ goto bail_lock;
+ }
+
+ /* move the RFORK. this assumes that the RFORK is at the end */
+ if (off) {
+ memmove(buf + ADEDOFF_RFORK_V2, buf + off, ad->ad_eid[ADEID_RFORK].ade_len);
+ }
+
+ munmap(buf, st.st_size + shiftdata);
+
+ /* now, fix up our copy of the header */
+ memset(ad->ad_filler, 0, sizeof(ad->ad_filler));
+
+ /* replace FILEI with FILEDATESI */
+ ad_getattr(ad, &attr);
+ ad->ad_eid[ADEID_FILEDATESI].ade_off = ADEDOFF_FILEDATESI;
+ ad->ad_eid[ADEID_FILEDATESI].ade_len = ADEDLEN_FILEDATESI;
+ ad->ad_eid[ADEID_FILEI].ade_off = 0;
+ ad->ad_eid[ADEID_FILEI].ade_len = 0;
+
+ /* add in the new entries */
+ ad->ad_eid[ADEID_DID].ade_off = ADEDOFF_DID;
+ ad->ad_eid[ADEID_DID].ade_len = ADEDLEN_DID;
+ ad->ad_eid[ADEID_AFPFILEI].ade_off = ADEDOFF_AFPFILEI;
+ ad->ad_eid[ADEID_AFPFILEI].ade_len = ADEDLEN_AFPFILEI;
+ ad->ad_eid[ADEID_SHORTNAME].ade_off = ADEDOFF_SHORTNAME;
+ ad->ad_eid[ADEID_SHORTNAME].ade_len = ADEDLEN_INIT;
+ ad->ad_eid[ADEID_PRODOSFILEI].ade_off = ADEDOFF_PRODOSFILEI;
+ ad->ad_eid[ADEID_PRODOSFILEI].ade_len = ADEDLEN_PRODOSFILEI;
+
+ ad->ad_eid[ADEID_PRIVDEV].ade_off = ADEDOFF_PRIVDEV;
+ ad->ad_eid[ADEID_PRIVDEV].ade_len = ADEDLEN_INIT;
+ ad->ad_eid[ADEID_PRIVINO].ade_off = ADEDOFF_PRIVINO;
+ ad->ad_eid[ADEID_PRIVINO].ade_len = ADEDLEN_INIT;
+ ad->ad_eid[ADEID_PRIVSYN].ade_off = ADEDOFF_PRIVSYN;
+ ad->ad_eid[ADEID_PRIVSYN].ade_len = ADEDLEN_INIT;
+ ad->ad_eid[ADEID_PRIVID].ade_off = ADEDOFF_PRIVID;
+ ad->ad_eid[ADEID_PRIVID].ade_len = ADEDLEN_INIT;
+
+ /* shift the old entries (NAME, COMMENT, FINDERI, RFORK) */
+ ad->ad_eid[ADEID_NAME].ade_off = ADEDOFF_NAME_V2;
+ ad->ad_eid[ADEID_COMMENT].ade_off = ADEDOFF_COMMENT_V2;
+ ad->ad_eid[ADEID_FINDERI].ade_off = ADEDOFF_FINDERI_V2;
+ ad->ad_eid[ADEID_RFORK].ade_off = ADEDOFF_RFORK_V2;
+
+ /* switch to dest version */
+ ad->ad_version = (toV2)?AD_VERSION2:AD_VERSION1;
+
+ /* move our data buffer to make space for the new entries. */
+ memmove(ad->ad_data + ADEDOFF_NAME_V2, ad->ad_data + ADEDOFF_NAME_V1,
+ ADEDOFF_RFORK_V1 - ADEDOFF_NAME_V1);
+
+ /* now, fill in the space with appropriate stuff. we're
+ operating as a v2 file now. */
+ ad_setdate(ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime);
+ memset(ad_entry(ad, ADEID_DID), 0, ADEDLEN_DID);
+ memset(ad_entry(ad, ADEID_AFPFILEI), 0, ADEDLEN_AFPFILEI);
+ ad_setattr(ad, attr);
+ memset(ad_entry(ad, ADEID_SHORTNAME), 0, ADEDLEN_SHORTNAME);
+ memset(ad_entry(ad, ADEID_PRODOSFILEI), 0, ADEDLEN_PRODOSFILEI);
+
+ /* rebuild the header and cleanup */
+ ad_flush(ad );
+ ret = 0;
+
+bail_lock:
+ ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0, 0);
+bail_err:
+ return ret;
+}
+#endif /* AD_VERSION == AD_VERSION2 */
+
+/* -------------------------------------
+ read in the entries