blob: a938d21cd5bae99f2eda78d0fbecfc812eab95b1 [file] [log] [blame]
// Copyright 2018 The Tulsi Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
const char *db_path = "/Library/Application Support/Tulsi"
"/Scripts/symbol_cache.db";
// Response handler for each row returned by the sqlite3_exec query below.
static int callback(void *unused, int argc, char **argv, char **az_col_name) {
if (argc != 3) {
// If the number of columns returned wasn't 3, return an error.
return 1;
} else if (access(argv[1], F_OK) == -1) {
// If the file does not exist, return early. DebugSymbols.framework will not
// try to find the dSYM in Spotlight if we give it a non-existent result.
return 0;
}
// Print the plist needed by DebugSymbols.framework to find this dSYM.
printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n"
"<dict>\n"
"<key>%s</key>\n"
"<dict>\n"
"<key>DBGArchitecture</key>\n"
"<string>%s</string>\n"
"<key>DBGDSYMPath</key>\n"
"<string>%s</string>\n"
"</dict>\n"
"</dict>\n"
"</plist>\n", argv[0], argv[2], argv[1]);
return 0;
}
// This will be called by DebugSymbols.framework with the UUID as its sole arg.
int main(int argc, const char *argv[]) {
// Print usage information if no or more than one input was detected.
if (argc != 2) {
fprintf(stderr, "Usage: %s UUID\n", argv[0]);
return 1;
}
// The UUID is expected to be exactly 36 characters long,
// but we want to overestimate our buffers in C.
// Concatenate a path to the database.
int returncode;
sqlite3 *db_handler;
char path_buffer[512];
char *home_dir = getenv("HOME");
strlcpy(path_buffer, home_dir, sizeof(path_buffer));
strlcat(path_buffer, db_path, sizeof(path_buffer));
// Open a new connection with the database.
returncode = sqlite3_open(path_buffer, &db_handler);
if (returncode != SQLITE_OK) {
fprintf(stderr,
"Can't open database: %s\n",
sqlite3_errmsg(db_handler));
sqlite3_close(db_handler);
return 1;
}
// Execute a query to retrieve the three fields needed for a
// DebugSymbols.framework plist.
char *exec_error_msg = NULL;
char query_buffer[256]; // should fit in 128 but being safe...
sqlite3_snprintf(sizeof(query_buffer),
query_buffer,
"SELECT uuid, dsym_path, architecture "
"FROM symbol_cache "
"WHERE uuid=\"%q\" "
"LIMIT 1;",
argv[1]);
// Query prints out a single plist, via callback above.
returncode = sqlite3_exec(db_handler,
query_buffer,
callback,
0,
&exec_error_msg);
if (returncode != SQLITE_OK) {
fprintf(stderr,
"Couldn't execute query to find UUID: %s, %s\n",
sqlite3_errmsg(db_handler), exec_error_msg);
sqlite3_close(db_handler);
return 1;
}
// Close connection when we're finished.
return sqlite3_close(db_handler);
}