X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/d87e115847b84cc1c3a1ef198a20181cd85b5309..60c433a9f80a92b51b33f65f1f58883e8fe843be:/Security/utilities/src/SecDb.c diff --git a/Security/utilities/src/SecDb.c b/Security/utilities/src/SecDb.c index c1aa0640..572096c2 100644 --- a/Security/utilities/src/SecDb.c +++ b/Security/utilities/src/SecDb.c @@ -79,6 +79,7 @@ struct __OpaqueSecDb { dispatch_semaphore_t read_semaphore; bool didFirstOpen; bool (^opened)(SecDbConnectionRef dbconn, bool did_create, CFErrorRef *error); + dispatch_queue_t notifyQueue; SecDBNotifyBlock notifyPhase; }; @@ -207,10 +208,22 @@ SecDbIdleConnectionCount(SecDbRef db) { return count; } -void SecDbSetNotifyPhaseBlock(SecDbRef db, SecDBNotifyBlock notifyPhase) { +void SecDbSetNotifyPhaseBlock(SecDbRef db, dispatch_queue_t queue, SecDBNotifyBlock notifyPhase) { + if (db->notifyQueue) + dispatch_release(db->notifyQueue); if (db->notifyPhase) Block_release(db->notifyPhase); - db->notifyPhase = Block_copy(notifyPhase); + + if (queue) { + db->notifyQueue = queue; + dispatch_retain(db->notifyQueue); + } else { + db->notifyQueue = NULL; + } + if (notifyPhase) + db->notifyPhase = Block_copy(notifyPhase); + else + db->notifyPhase = NULL; } static void SecDbNotifyPhase(SecDbConnectionRef dbconn, SecDbTransactionPhase phase) { @@ -222,6 +235,20 @@ static void SecDbNotifyPhase(SecDbConnectionRef dbconn, SecDbTransactionPhase ph } } +static bool SecDbOnNotifyQueue(SecDbConnectionRef dbconn, bool (^perform)()) { + __block bool result = false; + + if (dbconn->db->notifyPhase) { + dispatch_sync(dbconn->db->notifyQueue, ^{ + result = perform(); + }); + } else { + result = perform(); + } + + return result; +} + CFStringRef SecDbGetPath(SecDbRef db) { return db->db_path; } @@ -530,18 +557,20 @@ static bool SecDbBeginTransaction(SecDbConnectionRef dbconn, SecDbTransactionTyp static bool SecDbEndTransaction(SecDbConnectionRef dbconn, bool commit, CFErrorRef *error) { - bool ok = true, commited = false; - if (commit) { - SecDbNotifyPhase(dbconn, kSecDbTransactionWillCommit); - commited = ok = SecDbExec(dbconn, CFSTR("END"), error); - } else { - ok = SecDbExec(dbconn, CFSTR("ROLLBACK"), error); - commited = false; - } - dbconn->inTransaction = false; - SecDbNotifyPhase(dbconn, commited ? kSecDbTransactionDidCommit : kSecDbTransactionDidRollback); - dbconn->source = kSecDbAPITransaction; - return ok; + return SecDbOnNotifyQueue(dbconn, ^{ + bool ok = true, commited = false; + if (commit) { + SecDbNotifyPhase(dbconn, kSecDbTransactionWillCommit); + commited = ok = SecDbExec(dbconn, CFSTR("END"), error); + } else { + ok = SecDbExec(dbconn, CFSTR("ROLLBACK"), error); + commited = false; + } + dbconn->inTransaction = false; + SecDbNotifyPhase(dbconn, commited ? kSecDbTransactionDidCommit : kSecDbTransactionDidRollback); + dbconn->source = kSecDbAPITransaction; + return ok; + }); } bool SecDbTransaction(SecDbConnectionRef dbconn, SecDbTransactionType type,