+#if DS_AVAILABLE
+ xpc_object_t payload, reply;
+#endif
+ id_t tempID;
+ size_t identifier_len;
+ int rc = EIO;
+
+ if (identifier == NULL || result == NULL || identifier_size == 0) return EIO;
+
+ if (identifier_size == -1) {
+ identifier_size = strlen(identifier);
+ } else {
+ /* 10898647: For types that are known to be strings, send the smallest necessary amount of data. */
+ switch (id_type) {
+ case ID_TYPE_USERNAME:
+ case ID_TYPE_GROUPNAME:
+ case ID_TYPE_GROUP_NFS:
+ case ID_TYPE_USER_NFS:
+ case ID_TYPE_X509_DN:
+ case ID_TYPE_KERBEROS:
+ case ID_TYPE_NAME:
+ identifier_len = strlen(identifier);
+ if (identifier_size > identifier_len) {
+ identifier_size = identifier_len;
+ }
+ break;
+ }
+ }
+
+ switch (target_type) {
+ case ID_TYPE_GID:
+ case ID_TYPE_UID:
+ case ID_TYPE_UID_OR_GID:
+ /* shortcut UUIDs using compatibilty prefixes */
+ if (id_type == ID_TYPE_UUID) {
+ const uint8_t *uu = identifier;
+
+ if (identifier_size != sizeof(uuid_t)) return EINVAL;
+
+ if (memcmp(uu, _user_compat_prefix, COMPAT_PREFIX_LEN) == 0) {
+ id_t *tempRes = malloc(sizeof(*tempRes));
+ memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID));
+ (*tempRes) = ntohl(tempID);
+ (*result) = tempRes;
+ if (rec_type != NULL) {
+ (*rec_type) = MBR_REC_TYPE_USER;
+ }
+ return 0;
+ } else if (memcmp(uu, _group_compat_prefix, COMPAT_PREFIX_LEN) == 0) {
+ id_t *tempRes = malloc(sizeof(*tempRes));
+ memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID));
+ (*tempRes) = ntohl(tempID);
+ (*result) = tempRes;
+ if (rec_type != NULL) {
+ (*rec_type) = MBR_REC_TYPE_GROUP;
+ }
+ return 0;
+ }
+ }
+ break;
+
+ case ID_TYPE_UUID:
+ /* if this is a UID or GID translation, we shortcut UID/GID 0 */
+ /* or if no OD, we return compatibility UUIDs */
+ switch (id_type) {
+ case ID_TYPE_UID:
+ if (identifier_size != sizeof(tempID)) return EINVAL;
+
+ tempID = *((id_t *) identifier);
+ if ((tempID == 0) || (_mbr_od_available() == false)) {
+ uint8_t *tempUU = malloc(sizeof(uuid_t));
+ uuid_copy(tempUU, _user_compat_prefix);
+ *((id_t *) &tempUU[COMPAT_PREFIX_LEN]) = htonl(tempID);
+ (*result) = tempUU;
+ if (rec_type != NULL) {
+ (*rec_type) = MBR_REC_TYPE_USER;
+ }
+ return 0;
+ }
+ break;
+
+ case ID_TYPE_GID:
+ if (identifier_size != sizeof(tempID)) return EINVAL;
+
+ tempID = *((id_t *) identifier);
+ if ((tempID == 0) || (_mbr_od_available() == false)) {
+ uint8_t *tempUU = malloc(sizeof(uuid_t));
+ uuid_copy(tempUU, _group_compat_prefix);
+ *((id_t *) &tempUU[COMPAT_PREFIX_LEN]) = htonl(tempID);
+ (*result) = tempUU;
+ if (rec_type != NULL) {
+ (*rec_type) = MBR_REC_TYPE_GROUP;
+ }
+ return 0;
+ }
+ break;
+ }
+ break;
+ }
+
+#if DS_AVAILABLE
+ payload = xpc_dictionary_create(NULL, NULL, 0);
+ if (payload == NULL) return EIO;
+
+ xpc_dictionary_set_int64(payload, "requesting", target_type);
+ xpc_dictionary_set_int64(payload, "type", id_type);
+ xpc_dictionary_set_data(payload, "identifier", identifier, identifier_size);
+
+ reply = _od_rpc_call("mbr_identifier_translate", payload, _mbr_xpc_pipe);
+ if (reply != NULL) {
+ const void *reply_id;
+ size_t idLen;