+ 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;
+
+ rc = (int) xpc_dictionary_get_int64(reply, "error");
+ if (rc == 0) {
+ reply_id = xpc_dictionary_get_data(reply, "identifier", &idLen);
+ if (reply_id != NULL) {
+ char *identifier = malloc(idLen);
+
+ memcpy(identifier, reply_id, idLen); // should already be NULL terminated, etc.
+ (*result) = identifier;
+
+ if (rec_type != NULL) {
+ (*rec_type) = (int) xpc_dictionary_get_int64(reply, "rectype");
+ }
+ } else {
+ (*result) = NULL;
+ rc = ENOENT;
+ }
+ }
+
+ xpc_release(reply);
+ }
+
+ xpc_release(payload);
+#endif
+
+ return rc;