diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.cpp b/bindings/java/jni/dataModel_SleuthkitJNI.cpp index b69469ac088ebb74029be1f2189a2380e003e833..d856587341cc8e51478cf3a043ca6ef1114ab20f 100644 --- a/bindings/java/jni/dataModel_SleuthkitJNI.cpp +++ b/bindings/java/jni/dataModel_SleuthkitJNI.cpp @@ -1003,7 +1003,6 @@ JNIEXPORT void JNICALL return; } - // move the strings into the C++ world // get pointers to each of the file names @@ -1080,6 +1079,95 @@ JNIEXPORT void JNICALL // if process completes successfully, must call revertAddImgNat or commitAddImgNat to free the TskAutoDb } +/* + * Create a database for the given image using a pre-created process which can be cancelled. + * MUST call commitAddImg or revertAddImg afterwards once runAddImg returns. If there is an + * error, you do not need to call revert or commit and the 'process' handle will be deleted. + * @return the 0 for success 1 for failure + * @param env pointer to java environment this was called from + * @param obj the java object this was called from + * @param process the add-image process created by initAddImgNat + * @param dataSrcId An identifier for the data source that is unique across multiple cases (e.g., a UUID) + * @param imgPath The full path to the image + * @param timezone the timezone the image is from + */ +JNIEXPORT void JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_runAddImgNat(JNIEnv * env, jclass obj, jlong process, jstring dataSrcId, jstring imgPath, jstring timeZone) { + + // Validate arguments. + TskAutoDb *tskAuto = ((TskAutoDb *) process); + if (!tskAuto || tskAuto->m_tag != TSK_AUTO_TAG) { + setThrowTskCoreError(env, "runAddImgNat: Invalid process argument"); + return; + } + if (env->GetStringLength(dataSrcId) <= 0) { + setThrowTskCoreError(env, "runAddImgNat: Invalid data source id argument"); + return; + } + if (env->GetStringLength(imgPath) <= 0) { + setThrowTskCoreError(env, "runAddImgNat: Invalid image path argument"); + return; + } + + // Convert the string arguments into native strings. + jboolean isCopy; + const char *data_src_id = (const char *) env->GetStringUTFChars(dataSrcId, &isCopy); + if (NULL == data_src_id) { + setThrowTskCoreError(env, "runAddImgNat: Can't convert data source id string"); + return; + } + char **image_paths = (char **) tsk_malloc(1 * sizeof(char *)); + if (NULL == image_paths) { + setThrowTskCoreError(env, "runAddImgNat: Can't malloc array for image path string"); + env->ReleaseStringUTFChars(dataSrcId, (const char *) data_src_id); + return; + } + image_paths[0] = (char *) env->GetStringUTFChars(imgPath, &isCopy); + + // Set the time zone. + if (env->GetStringLength(timeZone) > 0) { + const char *time_zone = env->GetStringUTFChars(timeZone, &isCopy); + tskAuto->setTz(string(time_zone)); + env->ReleaseStringUTFChars(timeZone, time_zone); + } + + // Add the image. + uint8_t ret = 0; + if ( (ret = tskAuto->startAddImage(1, image_paths, TSK_IMG_TYPE_DETECT, 0)) != 0) { + stringstream msgss; + msgss << "runAddImgNat: Errors occured while ingesting image " << std::endl; + vector<TskAuto::error_record> errors = tskAuto->getErrorList(); + for (size_t i = 0; i < errors.size(); i++) { + msgss << (i+1) << ". "; + msgss << (TskAuto::errorRecordToString(errors[i])); + msgss << " " << std::endl; + } + if (ret == 1) { + //fatal error + setThrowTskCoreError(env, msgss.str().c_str()); + } + else if (ret == 2) { + if(tskAuto->isDbOpen()) { + // if we can still talk to the database, it's a non-fatal error + setThrowTskDataError(env, msgss.str().c_str()); + } + else { + // we cannot talk to the database, fatal error + setThrowTskCoreError(env, msgss.str().c_str()); + } + } + } + + // @@@ SHOULD WE CLOSE HERE before we commit / revert etc. + //close image first before freeing the image paths + tskAuto->closeImage(); + + // cleanup + env->ReleaseStringUTFChars(imgPath, (const char *) image_paths[0]); + free(image_paths); + env->ReleaseStringUTFChars(dataSrcId, (const char *) data_src_id); + + // if process completes successfully, must call revertAddImgNat or commitAddImgNat to free the TskAutoDb +} /* diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java index 4090fa42191f162d375f503cc9696d429c259472..5b88b6a67b43c925f3fc0f6d1eb69c7a89ecb264 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java @@ -40,7 +40,7 @@ * application */ public class SleuthkitJNI { - + // Lock used to synchronize image and file system cache private static final Object cacheLock = new Object(); @@ -60,6 +60,7 @@ public class SleuthkitJNI { private static native void closeCaseDbNat(long db) throws TskCoreException; + //hash-lookup database private static native int hashDbOpenNat(String hashDbPath) throws TskCoreException; private static native int hashDbNewNat(String hashDbPath) throws TskCoreException; @@ -86,7 +87,6 @@ public class SleuthkitJNI { private static native void hashDbClose(int dbHandle) throws TskCoreException; - //hash-lookup database functions private static native void hashDbCreateIndexNat(int dbHandle) throws TskCoreException; private static native boolean hashDbIndexExistsNat(int dbHandle) throws TskCoreException; @@ -97,11 +97,13 @@ public class SleuthkitJNI { private static native HashHitInfo hashDbLookupVerbose(String hash, int dbHandle) throws TskCoreException; - //load image + //add image private static native long initAddImgNat(long db, String timezone, boolean addUnallocSpace, boolean noFatFsOrphans) throws TskCoreException; private static native void runAddImgNat(long process, String[] imgPath, int splits, String timezone) throws TskCoreException, TskDataException; // if runAddImg finishes without being stopped, revertAddImg or commitAddImg MUST be called + private static native void runAddImgNat(long process, String dataSourceId, String imgPath, String timezone) throws TskCoreException, TskDataException; // if runAddImg finishes without being stopped, revertAddImg or commitAddImg MUST be called + private static native void stopAddImgNat(long process) throws TskCoreException; private static native void revertAddImgNat(long process) throws TskCoreException; @@ -213,8 +215,8 @@ void free() throws TskCoreException { * Start the process of adding a disk image to the case * * @param timezone Timezone that image was from - * @param addUnallocSpace true to create virtual files for unallocated space - * the image + * @param addUnallocSpace true to create virtual files for unallocated + * space the image * @param noFatFsOrphans true if to skip processing of orphans on FAT * filesystems * @@ -268,6 +270,33 @@ public void run(String[] imgPath) throws TskCoreException, TskDataException { runAddImgNat(autoDbPointer, imgPath, imgPath.length, timezone); } + /** + * Start the process of adding an image to the case database. MUST + * call either commit() or revert() after calling run(). + * + * @param dataSourceId An identifier for the data source that is + * unique across multiple cases (e.g., a UUID). + * @param imgPath Full path to the image file. + * @throws TskCoreException exception thrown if critical error + * occurs within TSK + * @throws TskDataException exception thrown if non-critical error + * occurs within TSK (should be OK to continue) + */ + public void run(String dataSourceId, String imagePath) throws TskCoreException, TskDataException { + if (autoDbPointer != 0) { + throw new TskCoreException("AddImgProcess:run: AutoDB pointer is already set"); + } + + synchronized (this) { + autoDbPointer = initAddImgNat(caseDbPointer, timezoneLongToShort(timezone), addUnallocSpace, noFatFsOrphans); + } + if (autoDbPointer == 0) { + //additional check in case initAddImgNat didn't throw exception + throw new TskCoreException("AddImgProcess::run: AutoDB pointer is NULL after initAddImgNat"); + } + runAddImgNat(autoDbPointer, dataSourceId, imagePath, timezone); + } + /** * Call while run() is executing in another thread to prematurely * halt the process. Must call revert() in the other thread once the