+/* Convert the volume status DB from 64-bit (HFS-style) entries into full UUIDs */
+int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle) {
+ VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
+ struct VSDBEntryHFS entry64;
+ struct stat dbinfo;
+ int result;
+ u_int32_t iobuffersize;
+ void *iobuffer = NULL;
+ int i;
+
+ if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
+
+ if ((result = LockDB(dbstateptr, LOCK_EX)) != 0) return result;
+
+
+ /*
+ * This function locks the database file then tries to read in
+ * the size of a old-style HFS UUID database entry. If what it finds
+ * is a well-formatted HFS entry, then it will convert the entire database.
+ * If it finds that the file isn't long enough or isn't actually the
+ * format for the 64-bit UUID struct on-disk, then it will bail out and not
+ * touch it. Otherwise it will read the whole file and convert it
+ *
+ * In practice this means that if the file is empty or if we have already
+ * converted it then do nothing.
+ */
+ lseek(dbstateptr->dbfile, 0, SEEK_SET);
+ result = read(dbstateptr->dbfile, &entry64, sizeof(entry64));
+ if ((result != sizeof(entry64)) ||
+ (entry64.keySeparator != DBKEYSEPARATOR) ||
+ (entry64.space != DBBLANKSPACE) ||
+ (entry64.terminator != DBRECORDTERMINATOR)) {
+ result = 0;
+ goto ErrExit;
+ } else {
+ /* Read in a giant buffer */
+ if ((result = stat(gVSDBPath, &dbinfo)) != 0) goto ErrExit;
+ iobuffersize = dbinfo.st_size;
+ iobuffer = malloc(iobuffersize);
+ if (iobuffer == NULL) {
+ result = ENOMEM;
+ goto ErrExit;
+ };
+
+ lseek(dbstateptr->dbfile, 0, SEEK_SET);
+ result = read(dbstateptr->dbfile, iobuffer, iobuffersize);
+ if (result != iobuffersize) {
+ result = errno;
+ goto ErrExit;
+ };
+ if ((result = ftruncate(dbstateptr->dbfile, 0)) != 0) {
+ goto ErrExit;
+ };
+ for (i = 0; i < iobuffersize / sizeof(entry64); i++) {
+ volUUID_t volumeID;
+ u_int32_t VolumeStatus;
+ struct VSDBEntryUUID dbentry;
+
+ /*
+ * now iterate through the contents of the 64-bit entries in RAM
+ * and write them on top of the existing database file
+ */
+ entry64 = *(((struct VSDBEntryHFS *)iobuffer) + i);
+ if ((entry64.keySeparator != DBKEYSEPARATOR) ||
+ (entry64.space != DBBLANKSPACE) ||
+ (entry64.terminator != DBRECORDTERMINATOR)) {
+ continue;
+ }
+
+ ConvertHFSUUIDToUUID(entry64.key.uuid, &volumeID);
+ VolumeStatus = ConvertHexStringToULong(entry64.record.statusFlags, sizeof(entry64.record.statusFlags));
+
+ FormatDBEntry(&volumeID, VolumeStatus, &dbentry);
+ if ((result = AddVolumeRecord(dbstateptr, &dbentry)) != sizeof(dbentry)) {
+ warnx("couldn't convert volume status database: %s", strerror(result));
+ goto ErrExit;
+ };
+ };
+
+ fsync(dbstateptr->dbfile);
+
+ result = 0;
+ };
+
+ErrExit:
+ if (iobuffer) free(iobuffer);
+ UnlockDB(dbstateptr);
+ return result;
+}
+