diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.cpp b/bindings/java/jni/dataModel_SleuthkitJNI.cpp index 7cdeb65bcaa1f77ea78f70291ff58674305be05f..3d17438dc4c5ebc163f5c682aef6d26accd92d0b 100644 --- a/bindings/java/jni/dataModel_SleuthkitJNI.cpp +++ b/bindings/java/jni/dataModel_SleuthkitJNI.cpp @@ -333,23 +333,18 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbBeginTransactionNat( return 1; } - if(!db->accepts_updates()) { - setThrowTskCoreError(env, "Database does not accept updates"); - return 1; - } - - return 0; + return tsk_hdb_begin_transaction(db); } /** - * Ends a hash database transaction. + * Commits a hash database transaction. * @param env Pointer to Java environment from which this method was called. * @param obj The Java object from which this method was called. * @param dbHandle A handle for the hash database. * @return 1 on error and 0 on success. */ JNIEXPORT jint JNICALL -Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbEndTransactionNat( +Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbCommitTransactionNat( JNIEnv * env, jclass obj, jint dbHandle) { if((size_t) dbHandle > hashDbs.size()) { @@ -363,12 +358,32 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbEndTransactionNat( return 1; } - if(!db->accepts_updates()) { - setThrowTskCoreError(env, "Database does not accept updates"); + return tsk_hdb_commit_transaction(db); +} + +/** + * Rolls back a hash database transaction. + * @param env Pointer to Java environment from which this method was called. + * @param obj The Java object from which this method was called. + * @param dbHandle A handle for the hash database. + * @return 1 on error and 0 on success. + */ +JNIEXPORT jint JNICALL +Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbRollbackTransactionNat( + JNIEnv * env, jclass obj, jint dbHandle) +{ + if((size_t) dbHandle > hashDbs.size()) { + setThrowTskCoreError(env, "Invalid database handle"); return 1; } - return 0; + TSK_HDB_INFO * db = hashDbs.at(dbHandle-1); + if(!db) { + setThrowTskCoreError(env, "Invalid database handle"); + return 1; + } + + return tsk_hdb_rollback_transaction(db); } /** diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.h b/bindings/java/jni/dataModel_SleuthkitJNI.h index dc36be5b0eaa7162399e58337827e6920703cb3f..bfdd3eb45b383d76d0266ec604e76e7bfbf7fcd0 100644 --- a/bindings/java/jni/dataModel_SleuthkitJNI.h +++ b/bindings/java/jni/dataModel_SleuthkitJNI.h @@ -70,7 +70,11 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbBeginTransactionNat( JNIEnv * env, jclass obj, jint dbHandle); JNIEXPORT jint JNICALL -Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbEndTransactionNat( +Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbCommitTransactionNat( + JNIEnv * env, jclass obj, jint dbHandle); + +JNIEXPORT jint JNICALL +Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbRollbackTransactionNat( JNIEnv * env, jclass obj, jint dbHandle); /* diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java index f0104ce4f4aac0f88edbcd9ed4cb9222a121b473..f35c73ad4b5bb9f3b10b295fc4cfefe5b34c1c15 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java @@ -57,7 +57,9 @@ public class SleuthkitJNI { private static native int hashDbBeginTransactionNat(int dbHandle) throws TskCoreException; - private static native int hashDbEndTransactionNat(int dbHandle) throws TskCoreException; + private static native int hashDbCommitTransactionNat(int dbHandle) throws TskCoreException; + + private static native int hashDbRollbackTransactionNat(int dbHandle) throws TskCoreException; private static native int hashDbAddEntryNat(String filename, String hashMd5, String hashSha1, String hashSha256, String comment, int dbHandle) throws TskCoreException; @@ -697,9 +699,17 @@ public static void addToHashDatabase(List<HashEntry> hashes, int dbHandle) throw for (HashEntry entry : hashes) { hashDbAddEntryNat(entry.getFileName(), entry.getMd5Hash(), entry.getSha1Hash(), entry.getSha256Hash(), entry.getComment(), dbHandle); } + hashDbCommitTransactionNat(dbHandle); } - finally { - hashDbEndTransactionNat(dbHandle); + catch (TskCoreException ex) { + try { + hashDbRollbackTransactionNat(dbHandle); + } + catch (TskCoreException ex2) { + ex2.initCause(ex); + throw ex2; + } + throw ex; } } diff --git a/tsk/hashdb/hdb_base.c b/tsk/hashdb/hdb_base.c index dafc0c808accd5379a06a25db65e3061c65e95fb..99281792e4398fd4cd7de265852cbca6994823fc 100755 --- a/tsk/hashdb/hdb_base.c +++ b/tsk/hashdb/hdb_base.c @@ -89,6 +89,8 @@ hdb_info_base_open(TSK_HDB_INFO *hdb_info, const TSK_TCHAR *db_path) hdb_info->db_type = TSK_HDB_DBTYPE_INVALID_ID; tsk_init_lock(&hdb_info->lock); + hdb_info->transaction_in_progress = 0; + hdb_info->get_db_path = hdb_base_get_db_path; hdb_info->get_display_name = hdb_base_get_display_name; hdb_info->uses_external_indexes = hdb_base_uses_external_indexes; @@ -101,6 +103,9 @@ hdb_info_base_open(TSK_HDB_INFO *hdb_info, const TSK_TCHAR *db_path) hdb_info->lookup_verbose_str = hdb_base_lookup_verbose_str; hdb_info->accepts_updates = hdb_base_accepts_updates; hdb_info->add_entry = hdb_base_add_entry; + hdb_info->begin_transaction = hdb_base_begin_transaction; + hdb_info->commit_transaction = hdb_base_commit_transaction; + hdb_info->rollback_transaction = hdb_base_rollback_transaction; hdb_info->close_db = hdb_info_base_close; return 0; @@ -134,7 +139,7 @@ hdb_base_uses_external_indexes() const TSK_TCHAR* hdb_base_get_index_path(TSK_HDB_INFO *hdb_info, TSK_HDB_HTYPE_ENUM htype) { - // The "base class" assumption is that the hash database does not use + // The "base class" assumption is that the hash database does not have // user-accessible external index files (e.g., it is a relational // database). It follows that the hash database path and index path are // the same, assuming that the hash database is implemented @@ -145,10 +150,10 @@ hdb_base_get_index_path(TSK_HDB_INFO *hdb_info, TSK_HDB_HTYPE_ENUM htype) uint8_t hdb_base_has_index(TSK_HDB_INFO *hdb_info, TSK_HDB_HTYPE_ENUM htype) { - // The "base class" assumption is that the hash database does not use - // external index files (e.g., it is a relational database). It follows - // that the hash database has an index as soon as it is created. This - // implementation of this function also says that look ups for all hash + // The "base class" assumption is that the hash database does not have + // user-accessible external index files (e.g., it is a relational database). + // It follows that the hash database has an index as soon as it is created. + // This implementation of this function also says that look ups for all hash // algorithm types are supported. return 1; } @@ -156,7 +161,7 @@ hdb_base_has_index(TSK_HDB_INFO *hdb_info, TSK_HDB_HTYPE_ENUM htype) uint8_t hdb_base_make_index(TSK_HDB_INFO *hdb_info, TSK_TCHAR *htype) { - // The "base class" assumption is that the hash database does not use + // The "base class" assumption is that the hash database does not have // user-accessible external index files (e.g., it is a relational // database). It follows that the hash database has an index upon creation. // Make this a no-op by simply returning the success code. @@ -221,7 +226,37 @@ hdb_base_add_entry(TSK_HDB_INFO *hdb_info, const char *file_name, const char *md tsk_error_reset(); tsk_error_set_errno(TSK_ERR_HDB_UNSUPFUNC); tsk_error_set_errstr("hdb_base_add_entry: operation not supported for hdb_info->db_type=%u", hdb_info->db_type); - return -1; + return 1; +} + +uint8_t hdb_base_begin_transaction(TSK_HDB_INFO *hdb_info) +{ + // This function needs an "override" by "derived classes" unless there is an + // "override" of the accepts_updates function that returns 0 (false). + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_UNSUPFUNC); + tsk_error_set_errstr("hdb_base_begin_transaction: operation not supported for hdb_info->db_type=%u", hdb_info->db_type); + return 1; +} + +uint8_t hdb_base_commit_transaction(TSK_HDB_INFO *hdb_info) +{ + // This function needs an "override" by "derived classes" unless there is an + // "override" of the accepts_updates function that returns 0 (false). + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_UNSUPFUNC); + tsk_error_set_errstr("hdb_base_commit_transaction: operation not supported for hdb_info->db_type=%u", hdb_info->db_type); + return 1; +} + +uint8_t hdb_base_rollback_transaction(TSK_HDB_INFO *hdb_info) +{ + // This function needs an "override" by "derived classes" unless there is an + // "override" of the accepts_updates function that returns 0 (false). + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_UNSUPFUNC); + tsk_error_set_errstr("hdb_base_rollback_transaction: operation not supported for hdb_info->db_type=%u", hdb_info->db_type); + return 1; } /** diff --git a/tsk/hashdb/sqlite_hdb.cpp b/tsk/hashdb/sqlite_hdb.cpp index 5040cd7fd930c5b0c317a61c97678c1778330bd2..c5bb2026ebb8e8461f44fb2ce7a5e2ff0e578c1a 100644 --- a/tsk/hashdb/sqlite_hdb.cpp +++ b/tsk/hashdb/sqlite_hdb.cpp @@ -281,6 +281,9 @@ TSK_HDB_INFO *sqlite_hdb_open(TSK_TCHAR *db_path) hdb_info->base.lookup_raw = sqlite_hdb_lookup_bin; hdb_info->base.lookup_verbose_str = sqlite_hdb_lookup_verbose_str; hdb_info->base.add_entry = sqlite_hdb_add_entry; + hdb_info->base.begin_transaction = sqlite_hdb_begin_transaction; + hdb_info->base.commit_transaction = sqlite_hdb_commit_transaction; + hdb_info->base.rollback_transaction = sqlite_hdb_rollback_transaction; hdb_info->base.close_db = sqlite_hdb_close; return (TSK_HDB_INFO*)hdb_info; @@ -654,6 +657,60 @@ int8_t sqlite_hdb_lookup_verbose_bin(TSK_HDB_INFO *hdb_info_base, uint8_t *hash, return 1; } +/** + * \ingroup hashdblib + * \internal + * Begins a transaction on a hash database. + * @param hdb_info A hash database info object + * @return 1 on error, 0 on success + */ +uint8_t sqlite_hdb_begin_transaction(TSK_HDB_INFO *hdb_info_base) +{ + TSK_SQLITE_HDB_INFO *hdb_info = reinterpret_cast<TSK_SQLITE_HDB_INFO*>(hdb_info_base); + if (sqlite_hdb_attempt_exec("BEGIN", "sqlite_hdb_base_begin_transaction: %s\n", hdb_info->db)) { + return 1; + } + else { + return 0; + } +} + +/** + * \ingroup hashdblib + * \internal + * Commits a transaction on a hash database. + * @param hdb_info A hash database info object + * @return 1 on error, 0 on success + */ +uint8_t sqlite_hdb_commit_transaction(TSK_HDB_INFO *hdb_info_base) +{ + TSK_SQLITE_HDB_INFO *hdb_info = reinterpret_cast<TSK_SQLITE_HDB_INFO*>(hdb_info_base); + if (sqlite_hdb_attempt_exec("COMMIT", "sqlite_hdb_base_end_transaction: %s\n", hdb_info->db)) { + return 1; + } + else { + return 0; + } +} + +/** + * \ingroup hashdblib + * \internal + * Rolls back a transaction on a hash database. + * @param hdb_info A hash database info object + * @return 1 on error, 0 on success + */ +uint8_t sqlite_hdb_rollback_transaction(TSK_HDB_INFO *hdb_info_base) +{ + TSK_SQLITE_HDB_INFO *hdb_info = reinterpret_cast<TSK_SQLITE_HDB_INFO*>(hdb_info_base); + if (sqlite_hdb_attempt_exec("ROLLBACK", "sqlite_hdb_base_end_transaction: %s\n", hdb_info->db)) { + return 1; + } + else { + return 0; + } +} + /* * Closes an SQLite hash database. * @param idx_info the index to close diff --git a/tsk/hashdb/tsk_hashdb.c b/tsk/hashdb/tsk_hashdb.c index 600660fac8bd4dd8c74494cfbda9899b362ec1c3..a5445ad1b8f907c4bb0de73c446891986450166e 100644 --- a/tsk/hashdb/tsk_hashdb.c +++ b/tsk/hashdb/tsk_hashdb.c @@ -495,13 +495,29 @@ tsk_hdb_lookup_verbose_str(TSK_HDB_INFO *hdb_info, const char *hash, void *resul return hdb_info->lookup_verbose_str(hdb_info, hash, result); } -uint8_t tsk_hdb_accepts_updates(TSK_HDB_INFO *hdb_info) +/** + * \ingroup hashdblib + * Indicates whether a hash database accepts updates. + * @param hdb_info The hash database object + * @return 1 if hash database accepts updates, 0 if it does not + */ +uint8_t +tsk_hdb_accepts_updates(TSK_HDB_INFO *hdb_info) { + const char *func_name = "tsk_hdb_accepts_updates"; + if (!hdb_info) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_HDB_ARG); - tsk_error_set_errstr("tsk_hdb_accepts_updates: NULL hdb_info"); - return -1; + tsk_error_set_errstr("%s: NULL hdb_info", func_name); + return 0; + } + + if (!hdb_info->accepts_updates) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_ARG); + tsk_error_set_errstr("%s: NULL add_entry function ptr", func_name); + return 0; } return hdb_info->accepts_updates(); @@ -509,45 +525,200 @@ uint8_t tsk_hdb_accepts_updates(TSK_HDB_INFO *hdb_info) /** * \ingroup hashdblib - * Add a binary hash entry to the index - * - * @param hdb_info the hash database object - * @param filename Name of the file that was hashed (can be null) - * @param md5 Text of MD5 hash (can be null) - * @param sha1 Text of SHA1 hash (can be null) - * @param sha256 Text of SHA256 hash (can be null) - * @return 1 on error, 0 on success, -1 if not updateable + * Adds a new entry to a hash database. + * @param hdb_info The hash database object + * @param filename Name of the file that was hashed (can be NULL) + * @param md5 Text representation of MD5 hash (can be NULL) + * @param sha1 Text representation of SHA1 hash (can be NULL) + * @param sha256 Text representation of SHA256 hash (can be NULL) + * @param sha256 A comment to asociate with the hash (can be NULL) + * @return 1 on error, 0 on success */ -int8_t -tsk_hdb_add_entry(TSK_HDB_INFO * hdb_info, const char *filename, const char *md5, +uint8_t +tsk_hdb_add_entry(TSK_HDB_INFO *hdb_info, const char *filename, const char *md5, const char *sha1, const char *sha256, const char *comment) { - int8_t ret = 0; + const char *func_name = "tsk_hdb_add_entry"; if (!hdb_info) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_HDB_ARG); - tsk_error_set_errstr("tsk_hdb_add_entry: NULL hdb_info"); + tsk_error_set_errstr("%s: NULL hdb_info", func_name); + return 1; + } + + if (!hdb_info->add_entry) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_ARG); + tsk_error_set_errstr("%s: NULL add_entry function ptr", func_name); return 1; } if (hdb_info->accepts_updates()) { - hdb_info->add_entry(hdb_info, filename, md5, sha1, sha256, comment); + return hdb_info->add_entry(hdb_info, filename, md5, sha1, sha256, comment); } else { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_HDB_PROC); - tsk_error_set_errstr("tsk_hdb_add_entry: operation not supported for this database type (=%u)", hdb_info->db_type); - return -1; + tsk_error_set_errstr("%s: operation not supported for this database type (=%u)", hdb_info->db_type, func_name); + return 1; } +} - return ret; +/** + * \ingroup hashdblib + * Begins a transaction on a hash database. + * @param hdb_info A hash database info object + * @return 1 on error, 0 on success + */ +uint8_t +tsk_hdb_begin_transaction(TSK_HDB_INFO *hdb_info) +{ + const char *func_name = "tsk_hdb_begin_transaction"; + + if (!hdb_info) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_ARG); + tsk_error_set_errstr("%s: NULL hdb_info", func_name); + return 1; + } + + if (!hdb_info->begin_transaction) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_ARG); + tsk_error_set_errstr("%s: NULL begin_transaction function ptr", func_name); + return 1; + } + + if (hdb_info->accepts_updates()) { + if (!hdb_info->transaction_in_progress) { + if (hdb_info->begin_transaction(hdb_info)) { + return 1; + } + else { + hdb_info->transaction_in_progress = 1; + return 0; + } + } + else { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_PROC); + tsk_error_set_errstr("%s: transaction already begun", func_name); + return 1; + } + } + else { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_PROC); + tsk_error_set_errstr("%s: operation not supported for this database type (=%u)", func_name, hdb_info->db_type); + return 1; + } +} + +/** + * \ingroup hashdblib + * Commits a transaction on a hash database. + * @param hdb_info A hash database info object + * @return 1 on error, 0 on success + */ +uint8_t +tsk_hdb_commit_transaction(TSK_HDB_INFO *hdb_info) +{ + const char *func_name = "tsk_hdb_commit_transaction"; + + if (!hdb_info) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_ARG); + tsk_error_set_errstr("%s: NULL hdb_info", func_name); + return 1; + } + + if (!hdb_info->commit_transaction) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_ARG); + tsk_error_set_errstr("%s: NULL commit_transaction function ptr", func_name); + return 1; + } + + if (hdb_info->accepts_updates()) { + if (hdb_info->transaction_in_progress) { + if (hdb_info->commit_transaction(hdb_info)) { + return 1; + } + else { + hdb_info->transaction_in_progress = 0; + return 0; + } + } + else { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_PROC); + tsk_error_set_errstr("%s: transaction not begun", func_name); + return 1; + } + } + else { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_PROC); + tsk_error_set_errstr("%s: operation not supported for this database type (=%u)", func_name, hdb_info->db_type); + return 1; + } +} + +/** + * \ingroup hashdblib + * Rolls back a transaction on a hash database. + * @param hdb_info A hash database info object + * @return 1 on error, 0 on success + */ +uint8_t +tsk_hdb_rollback_transaction(TSK_HDB_INFO *hdb_info) +{ + const char *func_name = "tsk_hdb_rollback_transaction"; + + if (!hdb_info) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_ARG); + tsk_error_set_errstr("%s: NULL hdb_info", func_name); + return 1; + } + + if (!hdb_info->rollback_transaction) { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_ARG); + tsk_error_set_errstr("%s: NULL rollback_transaction function ptr", func_name); + return 1; + } + + if (hdb_info->accepts_updates()) { + if (hdb_info->transaction_in_progress) { + if (hdb_info->commit_transaction(hdb_info)) { + return 1; + } + else { + hdb_info->transaction_in_progress = 0; + return 0; + } + } + else { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_PROC); + tsk_error_set_errstr("%s: transaction not begun", func_name); + return 1; + } + } + else { + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_HDB_PROC); + tsk_error_set_errstr("%s: operation not supported for this database type (=%u)", func_name, hdb_info->db_type); + return 1; + } } /** * \ingroup hashdblib * Closes an open hash database. - * @param hdb_info database to close + * @param hdb_info The hash database object */ void tsk_hdb_close(TSK_HDB_INFO *hdb_info) diff --git a/tsk/hashdb/tsk_hashdb.h b/tsk/hashdb/tsk_hashdb.h index bc190993aec79ef81e31f671c9af8aa7e0e85b9a..eb5865451413b5e8baf83eea7700ebb6f32ebd6a 100644 --- a/tsk/hashdb/tsk_hashdb.h +++ b/tsk/hashdb/tsk_hashdb.h @@ -117,6 +117,7 @@ extern "C" { char db_name[TSK_HDB_NAME_MAXLEN]; ///< Name of the database, for callbacks TSK_HDB_DBTYPE_ENUM db_type; ///< Type of database tsk_lock_t lock; ///< Lock for lazy loading and idx_lbuf + uint8_t transaction_in_progress; ///< Flag set and unset when transaction are begun and ended const TSK_TCHAR*(*get_db_path)(TSK_HDB_INFO*); const char*(*get_display_name)(TSK_HDB_INFO*); uint8_t(*uses_external_indexes)(); @@ -129,6 +130,9 @@ extern "C" { int8_t(*lookup_verbose_str)(TSK_HDB_INFO *, const char *, void *); uint8_t(*accepts_updates)(); uint8_t(*add_entry)(TSK_HDB_INFO*, const char*, const char*, const char*, const char*, const char *); + uint8_t(*begin_transaction)(TSK_HDB_INFO *); + uint8_t(*commit_transaction)(TSK_HDB_INFO *); + uint8_t(*rollback_transaction)(TSK_HDB_INFO *); void(*close_db)(TSK_HDB_INFO *); }; @@ -193,8 +197,11 @@ extern "C" { TSK_HDB_FLAG_ENUM, TSK_HDB_LOOKUP_FN, void *); extern int8_t tsk_hdb_lookup_verbose_str(TSK_HDB_INFO *, const char *, void *); extern uint8_t tsk_hdb_accepts_updates(TSK_HDB_INFO *); - extern int8_t tsk_hdb_add_entry(TSK_HDB_INFO *, const char*, const char*, + extern uint8_t tsk_hdb_add_entry(TSK_HDB_INFO *, const char*, const char*, const char*, const char*, const char*); + extern uint8_t tsk_hdb_begin_transaction(TSK_HDB_INFO *); + extern uint8_t tsk_hdb_commit_transaction(TSK_HDB_INFO *); + extern uint8_t tsk_hdb_rollback_transaction(TSK_HDB_INFO *); extern void tsk_hdb_close(TSK_HDB_INFO *); #ifdef __cplusplus diff --git a/tsk/hashdb/tsk_hashdb_i.h b/tsk/hashdb/tsk_hashdb_i.h index 0a63f1502bd6b42c651d69869be64f398d8cd803..b3bea769b0296327074ad3da1027e4abb7e004b5 100644 --- a/tsk/hashdb/tsk_hashdb_i.h +++ b/tsk/hashdb/tsk_hashdb_i.h @@ -69,6 +69,9 @@ extern "C" { extern int8_t hdb_base_lookup_verbose_str(TSK_HDB_INFO *, const char *, void *); extern uint8_t hdb_base_accepts_updates(); extern uint8_t hdb_base_add_entry(TSK_HDB_INFO *, const char *, const char *, const char *, const char *, const char *); + extern uint8_t hdb_base_begin_transaction(TSK_HDB_INFO *); + extern uint8_t hdb_base_commit_transaction(TSK_HDB_INFO *); + extern uint8_t hdb_base_rollback_transaction(TSK_HDB_INFO *); extern void hdb_info_base_close(TSK_HDB_INFO *); // Hash database functions common to all text format hash databases @@ -144,6 +147,9 @@ extern "C" { extern int8_t sqlite_hdb_lookup_verbose_bin(TSK_HDB_INFO *, uint8_t *, uint8_t, void *); extern uint8_t sqlite_hdb_add_entry(TSK_HDB_INFO *, const char *, const char *, const char *, const char *, const char *); + extern uint8_t sqlite_hdb_begin_transaction(TSK_HDB_INFO *); + extern uint8_t sqlite_hdb_commit_transaction(TSK_HDB_INFO *); + extern uint8_t sqlite_hdb_rollback_transaction(TSK_HDB_INFO *); extern void sqlite_hdb_close(TSK_HDB_INFO *); #ifdef __cplusplus