+static int sl_createCNIDArray(slq_t *slq, const DALLOC_CTX *p)
+{
+ EC_INIT;
+ uint64_t *cnids = NULL;
+
+ EC_NULL( cnids = talloc_array(slq, uint64_t, talloc_array_length(p)) );
+
+ for (int i = 0; i < talloc_array_length(p); i++) {
+ memcpy(&cnids[i], p->dd_talloc_array[i], sizeof(uint64_t));
+ }
+ qsort(cnids, talloc_array_length(p), sizeof(uint64_t), cnid_comp_fn);
+
+ slq->slq_cnids = cnids;
+ slq->slq_cnids_num = talloc_array_length(p);
+
+EC_CLEANUP:
+ if (ret != 0) {
+ if (cnids)
+ talloc_free(cnids);
+ }
+ EC_EXIT;
+}
+
+static char *tracker_to_unix_path(TALLOC_CTX *mem_ctx, const char *uri)
+{
+ GFile *f;
+ char *path;
+ char *talloc_path = NULL;
+
+ f = g_file_new_for_uri(uri);
+ if (!f) {
+ return NULL;
+ }
+
+ path = g_file_get_path(f);
+ g_object_unref(f);
+
+ if (!path) {
+ return NULL;
+ }
+
+ talloc_path = talloc_strdup(mem_ctx, path);
+ g_free(path);
+
+ return talloc_path;
+}
+
+/**
+ * Add requested metadata for a query result element
+ *
+ * This could be rewritten to something more sophisticated like
+ * querying metadata from Tracker.
+ *
+ * If path or sp is NULL, simply add nil values for all attributes.
+ **/
+static bool add_filemeta(sl_array_t *reqinfo,
+ sl_array_t *fm_array,
+ const char *path,
+ const struct stat *sp)
+{
+ sl_array_t *meta;
+ sl_nil_t nil;
+ int i, metacount;
+ uint64_t uint64var;
+ sl_time_t sl_time;
+ char *p, *name;
+
+ metacount = talloc_array_length(reqinfo->dd_talloc_array);
+ if (metacount == 0 || path == NULL || sp == NULL) {
+ dalloc_add_copy(fm_array, &nil, sl_nil_t);
+ return true;
+ }
+
+ meta = talloc_zero(fm_array, sl_array_t);
+
+ for (i = 0; i < metacount; i++) {
+ if (strequal(reqinfo->dd_talloc_array[i], "kMDItemDisplayName")
+ || strequal(reqinfo->dd_talloc_array[i], "kMDItemFSName")) {
+ if ((p = strrchr(path, '/'))) {
+ name = dalloc_strdup(meta, p + 1);
+ dalloc_add(meta, name, "char *");
+ }
+ } else if (strequal(reqinfo->dd_talloc_array[i],
+ "kMDItemPath")) {
+ name = dalloc_strdup(meta, path);
+ dalloc_add(meta, name, "char *");
+ } else if (strequal(reqinfo->dd_talloc_array[i],
+ "kMDItemFSSize")) {
+ uint64var = sp->st_size;
+ dalloc_add_copy(meta, &uint64var, uint64_t);
+ } else if (strequal(reqinfo->dd_talloc_array[i],
+ "kMDItemFSOwnerUserID")) {
+ uint64var = sp->st_uid;
+ dalloc_add_copy(meta, &uint64var, uint64_t);
+ } else if (strequal(reqinfo->dd_talloc_array[i],
+ "kMDItemFSOwnerGroupID")) {
+ uint64var = sp->st_gid;
+ dalloc_add_copy(meta, &uint64var, uint64_t);
+ } else if (strequal(reqinfo->dd_talloc_array[i],
+ "kMDItemFSContentChangeDate")) {
+ sl_time.tv_sec = sp->st_mtime;
+ dalloc_add_copy(meta, &sl_time, sl_time_t);
+ } else {
+ dalloc_add_copy(meta, &nil, sl_nil_t);
+ }
+ }
+
+ dalloc_add(fm_array, meta, sl_array_t);
+ return true;
+}
+
+/**
+ * Allocate result handle used in the async Tracker cursor result
+ * handler for storing results
+ **/
+static bool create_result_handle(slq_t *slq)
+{
+ sl_nil_t nil = 0;
+ struct sl_rslts *query_results;
+
+ if (slq->query_results) {
+ LOG(log_error, logtype_sl,"unexpected existing result handle");
+ return false;
+ }
+
+ query_results = talloc_zero(slq, struct sl_rslts);
+
+ /* CNIDs */
+ query_results->cnids = talloc_zero(query_results, sl_cnids_t);
+ if (query_results->cnids == NULL) {
+ return false;
+ }
+ query_results->cnids->ca_cnids = talloc_zero(query_results->cnids,
+ DALLOC_CTX);
+ if (query_results->cnids->ca_cnids == NULL) {
+ return false;
+ }
+
+ query_results->cnids->ca_unkn1 = 0xadd;
+ query_results->cnids->ca_context = slq->slq_ctx2;
+
+ /* FileMeta */
+ query_results->fm_array = talloc_zero(query_results, sl_array_t);
+ if (query_results->fm_array == NULL) {
+ return false;
+ }
+
+ /* For some reason the list of results always starts with a nil entry */
+ dalloc_add_copy(query_results->fm_array, &nil, sl_nil_t);
+
+ slq->query_results = query_results;
+ return true;
+}
+
+static bool add_results(sl_array_t *array, slq_t *slq)
+{
+ sl_filemeta_t *fm;
+ uint64_t status = 0;
+
+ /* FileMeta */
+ fm = talloc_zero(array, sl_filemeta_t);
+ if (!fm) {
+ return false;
+ }
+
+ dalloc_add_copy(array, &status, uint64_t);
+ dalloc_add(array, slq->query_results->cnids, sl_cnids_t);
+ if (slq->query_results->num_results > 0) {
+ dalloc_add(fm, slq->query_results->fm_array, sl_array_t);
+ }
+ dalloc_add(array, fm, sl_filemeta_t);
+
+ /* This ensure the results get clean up after been sent to the client */
+ talloc_steal(array, slq->query_results);
+ slq->query_results = NULL;
+
+ if (!create_result_handle(slq)) {
+ LOG(log_error, logtype_sl, "couldn't add result handle");
+ slq->slq_state = SLQ_STATE_ERROR;
+ return false;
+ }
+
+ return true;
+}
+
+/******************************************************************************