From b312017adf23a580f685a27401f7cbf7081ae68d Mon Sep 17 00:00:00 2001
From: Ann Priestman <apriestman@basistech.com>
Date: Thu, 7 Nov 2019 14:41:29 -0500
Subject: [PATCH] Adding new Pool object

---
 .../sleuthkit/datamodel/ContentVisitor.java   |  14 ++
 .../src/org/sleuthkit/datamodel/Pool.java     | 152 ++++++++++++++++++
 .../sleuthkit/datamodel/SleuthkitCase.java    | 143 +++++++++++++++-
 .../datamodel/SleuthkitItemVisitor.java       |  14 ++
 .../src/org/sleuthkit/datamodel/TskData.java  |  52 +++++-
 tsk/auto/auto.cpp                             |  16 +-
 tsk/auto/auto_db.cpp                          |  44 ++++-
 tsk/auto/db_postgresql.cpp                    |  17 ++
 tsk/auto/db_sqlite.cpp                        |  34 ++++
 tsk/auto/tsk_auto.h                           |  10 ++
 tsk/auto/tsk_case_db.h                        |   4 +-
 tsk/auto/tsk_db.h                             |   4 +
 tsk/auto/tsk_db_postgresql.h                  |   3 +
 tsk/auto/tsk_db_sqlite.h                      |   1 +
 14 files changed, 501 insertions(+), 7 deletions(-)
 create mode 100644 bindings/java/src/org/sleuthkit/datamodel/Pool.java

diff --git a/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java b/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java
index 511112868..8aa43c689 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/ContentVisitor.java
@@ -66,6 +66,15 @@ public interface ContentVisitor<T> {
 	 * @return result of the visit
 	 */
 	T visit(Image i);
+	
+	/**
+	 * Act on (visit) a Pool content object
+	 *
+	 * @param p pool to visit / act on
+	 *
+	 * @return result of the visit
+	 */
+	T visit(Pool p);	
 
 	/**
 	 * Act on (visit) a Volume content object
@@ -195,6 +204,11 @@ public T visit(Image i) {
 		public T visit(Volume v) {
 			return defaultVisit(v);
 		}
+		
+		@Override
+		public T visit(Pool p) {
+			return defaultVisit(p);
+		}
 
 		@Override
 		public T visit(VolumeSystem vs) {
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Pool.java b/bindings/java/src/org/sleuthkit/datamodel/Pool.java
new file mode 100644
index 000000000..f0a22ba25
--- /dev/null
+++ b/bindings/java/src/org/sleuthkit/datamodel/Pool.java
@@ -0,0 +1,152 @@
+/*
+ * Sleuth Kit Data Model
+ * 
+ * Copyright 2011-2017 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ * 
+ * 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.
+ */
+package org.sleuthkit.datamodel;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.sleuthkit.datamodel.TskData.TSK_DB_POOL_TYPE_ENUM;
+
+/**
+ * Represents a volume system. Populated based on data in database.
+ */
+public class Pool extends AbstractContent {
+
+	private volatile long volumeSystemHandle = 0;
+	private long type, imgOffset;
+
+	/**
+	 * Constructor most inputs are from the database
+	 *
+	 * @param db        case database handle
+	 * @param obj_id    the unique content object id for the volume system
+	 * @param name      name of the volume system
+	 * @param type      type of the volume system
+	 * @param imgOffset offset of the volume system with respect to image
+	 */
+	protected Pool(SleuthkitCase db, long obj_id, String name, long type, long imgOffset) {
+		super(db, obj_id, name);
+		this.type = type;
+		this.imgOffset = imgOffset;
+		System.out.println("### made a pool!\n");
+	}
+
+	@Override
+	public int read(byte[] readBuffer, long offset, long len) throws TskCoreException {
+		throw new TskCoreException("Not yet implemented");
+		//synchronized (this) {
+		//	if (volumeSystemHandle == 0) {
+		//		getVolumeSystemHandle();
+		//	}
+		//}
+		//return SleuthkitJNI.readVs(volumeSystemHandle, readBuffer, offset, len);
+	}
+
+	@Override
+	public long getSize() {
+		return 0;
+	}
+
+	/**
+	 * get the type
+	 *
+	 * @return type
+	 */
+	public TSK_DB_POOL_TYPE_ENUM getType() {
+		return TskData.TSK_DB_POOL_TYPE_ENUM.valueOf(type);
+	}
+
+	/**
+	 * get the byte offset
+	 *
+	 * @return byte offset
+	 */
+	public long getOffset() {
+		return imgOffset;
+	}
+
+
+	/**
+	 * get the volume system Handle pointer Open a new handle if needed,
+	 * otherwise resuse the existing handle.
+	 *
+	 * @return volume system Handle pointer
+	 *
+	 * @throws TskException
+	 */
+	//protected synchronized long getPoolHandle() throws TskCoreException {
+		//if (volumeSystemHandle == 0) {
+		//	Content dataSource = getDataSource();
+		//	if ((dataSource != null) && (dataSource instanceof Image)) {
+		//		Image image = (Image) dataSource;
+		//		volumeSystemHandle = SleuthkitJNI.openVs(image.getImageHandle(), imgOffset);
+		//	} else {
+		//		throw new TskCoreException("Volume System data source is not an image");
+		//	}
+		//}
+
+		//return volumeSystemHandle;
+	//}
+
+	@Override
+	public void close() {
+		//if (volumeSystemHandle != 0) {
+		//	synchronized (this) {
+		//		if (volumeSystemHandle != 0) {
+		//			// SleuthkitJNI.closeVs(volumeSystemHandle); // closeVs is currently a no-op
+		//			volumeSystemHandle = 0;
+		//		}
+		//	}
+		//}
+	}
+
+	@Override
+	public void finalize() throws Throwable {
+		try {
+			close();
+		} finally {
+			super.finalize();
+		}
+	}
+	
+	@Override
+	public <T> T accept(SleuthkitItemVisitor<T> v) {
+		return v.visit(this);
+	}
+
+	@Override
+	public <T> T accept(ContentVisitor<T> v) {
+		return v.visit(this);
+	}
+
+	@Override
+	public List<Content> getChildren() throws TskCoreException {
+		return getSleuthkitCase().getPoolChildren(this);
+	}
+
+	@Override
+	public List<Long> getChildrenIds() throws TskCoreException {
+		return getSleuthkitCase().getPoolChildrenIds(this);
+	}
+
+
+	@Override
+	public String toString(boolean preserveState) {
+		return super.toString(preserveState) + "Pool [\t" + "imgOffset " + imgOffset + "\t" + "type " + type + "]\t"; //NON-NLS
+	}
+}
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index 6ce85fd20..c4860edb5 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -4644,6 +4644,9 @@ public Content getContentById(long id) throws TskCoreException {
 				content = getVolumeById(id, parentId);
 				frequentlyUsedContentMap.put(id, content);
 				break;
+			case POOL:
+				content = getPoolById(id, parentId);
+				break;
 			case FS:
 				content = getFileSystemById(id, parentId);
 				frequentlyUsedContentMap.put(id, content);
@@ -7203,7 +7206,7 @@ public Image getImageById(long id) throws TskCoreException {
 	 * @throws TskCoreException thrown if a critical error occurred within tsk
 	 *                          core
 	 */
-	VolumeSystem getVolumeSystemById(long id, Image parent) throws TskCoreException {
+	VolumeSystem getVolumeSystemById(long id, Content parent) throws TskCoreException {
 		CaseDbConnection connection = connections.getConnection();
 		acquireSingleUserCaseReadLock();
 		Statement s = null;
@@ -7290,6 +7293,75 @@ FileSystem getFileSystemById(long id, long parentId) throws TskCoreException {
 	FileSystem getFileSystemById(long id, Volume parent) throws TskCoreException {
 		return getFileSystemByIdHelper(id, parent);
 	}
+	
+	/**
+	 * Get a pool by the object id
+	 *
+	 * @param id     of the pool
+	 * @param parent parent of the pool (image or volume)
+	 *
+	 * @return populated Pool object
+	 *
+	 * @throws TskCoreException thrown if a critical error occurred within tsk
+	 *                          core
+	 */
+	Pool getPoolById(long id, Content parent) throws TskCoreException {
+		return getPoolByIdHelper(id, parent);
+	}	
+	
+	/**
+	 * @param id       ID of the desired Volume
+	 * @param parentId ID of the Volume's parent
+	 *
+	 * @return the desired Volume
+	 *
+	 * @throws TskCoreException
+	 */
+	Pool getPoolById(long id, long parentId) throws TskCoreException {
+		Pool pool = getPoolById(id, null);
+		pool.setParentId(parentId);
+		return pool;
+	}
+	
+	/**
+	 * Get file system by id and Content parent
+	 *
+	 * @param id     of the filesystem to get
+	 * @param parent a direct parent Content object
+	 *
+	 * @return populated FileSystem object
+	 *
+	 * @throws TskCoreException thrown if a critical error occurred within tsk
+	 *                          core
+	 */
+	private Pool getPoolByIdHelper(long id, Content parent) throws TskCoreException {
+
+		CaseDbConnection connection = connections.getConnection();
+		acquireSingleUserCaseReadLock();
+		Statement s = null;
+		ResultSet rs = null;
+		try {
+			s = connection.createStatement();
+			rs = connection.executeQuery(s, "SELECT * FROM tsk_pool_info " //NON-NLS
+					+ "where obj_id = " + id); //NON-NLS
+			if (rs.next()) {
+				
+				Pool pool = new Pool(this, rs.getLong("obj_id"), "POOL!", rs.getLong("pool_type"), rs.getLong("addr"));
+				pool.setParent(parent);
+				
+				return pool;
+			} else {
+				throw new TskCoreException("No pool found for id:" + id);
+			}
+		} catch (SQLException ex) {
+			throw new TskCoreException("Error getting Pool by ID", ex);
+		} finally {
+			closeResultSet(rs);
+			closeStatement(s);
+			connection.close();
+			releaseSingleUserCaseReadLock();
+		}
+	}
 
 	/**
 	 * Get file system by id and Content parent
@@ -7552,6 +7624,9 @@ List<Content> getImageChildren(Image img) throws TskCoreException {
 					case VS:
 						children.add(getVolumeSystemById(info.id, img));
 						break;
+					case POOL:
+						children.add(getPoolById(info.id, img));
+						break;
 					case FS:
 						children.add(getFileSystemById(info.id, img));
 						break;
@@ -7593,6 +7668,7 @@ List<Long> getImageChildrenIds(Image img) throws TskCoreException {
 		List<Long> children = new ArrayList<Long>();
 		for (ObjectInfo info : childInfos) {
 			if (info.type == ObjectType.VS
+					|| info.type == ObjectType.POOL
 					|| info.type == ObjectType.FS
 					|| info.type == ObjectType.ABSTRACTFILE
 					|| info.type == ObjectType.ARTIFACT) {
@@ -7605,6 +7681,68 @@ List<Long> getImageChildrenIds(Image img) throws TskCoreException {
 		}
 		return children;
 	}
+	
+	/**
+	 * Returns the list of direct children for a given Pool
+	 *
+	 * @param pool pool to get children for
+	 *
+	 * @return list of pool children objects
+	 *
+	 * @throws TskCoreException thrown if a critical error occurred within tsk
+	 *                          core
+	 */
+	List<Content> getPoolChildren(Pool pool) throws TskCoreException {
+		Collection<ObjectInfo> childInfos = getChildrenInfo(pool);
+		List<Content> children = new ArrayList<Content>();
+		for (ObjectInfo info : childInfos) {
+			if (null != info.type) {
+				switch (info.type) {
+					case VS:
+						children.add(getVolumeSystemById(info.id, pool));
+						break;
+					case ABSTRACTFILE:
+						AbstractFile f = getAbstractFileById(info.id);
+						if (f != null) {
+							children.add(f);
+						}
+						break;
+					case ARTIFACT:
+						BlackboardArtifact art = getArtifactById(info.id);
+						if (art != null) {
+							children.add(art);
+						}
+						break;
+					default:
+						throw new TskCoreException("Pool has child of invalid type: " + info.type);
+				}
+			}
+		}
+		return children;
+	}
+
+	/**
+	 * Returns the list of direct children IDs for a given Pool
+	 *
+	 * @param pool pool to get children for
+	 *
+	 * @return list of pool children IDs
+	 *
+	 * @throws TskCoreException thrown if a critical error occurred within tsk
+	 *                          core
+	 */
+	List<Long> getPoolChildrenIds(Pool pool) throws TskCoreException {
+		Collection<ObjectInfo> childInfos = getChildrenInfo(pool);
+		List<Long> children = new ArrayList<Long>();
+		for (ObjectInfo info : childInfos) {
+			if (info.type == ObjectType.VS || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
+				children.add(info.id);
+			} else {
+				throw new TskCoreException("Pool has child of invalid type: " + info.type);
+			}
+		}
+		return children;
+	}	
 
 	/**
 	 * Returns the list of direct children for a given VolumeSystem
@@ -7684,6 +7822,9 @@ List<Content> getVolumeChildren(Volume vol) throws TskCoreException {
 		for (ObjectInfo info : childInfos) {
 			if (null != info.type) {
 				switch (info.type) {
+					case POOL:
+						children.add(getPoolById(info.id, vol));
+						break;
 					case FS:
 						children.add(getFileSystemById(info.id, vol));
 						break;
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java
index 47fb37e06..7a01c580a 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitItemVisitor.java
@@ -87,6 +87,15 @@ public interface SleuthkitItemVisitor<T> {
 	 * @return result of the visit
 	 */
 	T visit(VolumeSystem vs);
+	
+	/**
+	 * Act on (visit) a Pool content object
+	 *
+	 * @param pool the volume system to visit / act on
+	 *
+	 * @return result of the visit
+	 */
+	T visit(Pool pool);
 
 	/**
 	 * Act on (visit) a blackboard artifact object
@@ -211,6 +220,11 @@ public T visit(Volume v) {
 		public T visit(VolumeSystem vs) {
 			return defaultVisit(vs);
 		}
+		
+		@Override
+		public T visit(Pool p) {
+			return defaultVisit(p);
+		}
 
 		@Override
 		public T visit(BlackboardArtifact ba) {
diff --git a/bindings/java/src/org/sleuthkit/datamodel/TskData.java b/bindings/java/src/org/sleuthkit/datamodel/TskData.java
index 8e13bba34..0330c6c0f 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/TskData.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/TskData.java
@@ -630,7 +630,8 @@ public enum ObjectType {
 		FS(3), ///< File System - see tsk_fs_info for more details
 		ABSTRACTFILE(4), ///< File - see tsk_files for more details
 		ARTIFACT(5),	/// Artifact - see blackboard_artifacts for more details
-		REPORT(6)	///< Report - see reports for more details
+		REPORT(6),	///< Report - see reports for more details
+		POOL(7)     ///< Pool
 		; 
 		private short objectType;
 
@@ -721,6 +722,55 @@ public String getName() {
 			return name;
 		}
 	}
+	
+	/**
+	 * The type of file in a database, such as file system versus local file.
+	 * This is the type field in the tsk_files table.
+	 */
+	public enum TSK_DB_POOL_TYPE_ENUM {
+		TSK_POOL_TYPE_DETECT(0, "Auto detect"), ///< Use autodetection methods
+		TSK_POOL_TYPE_APFS(1, "APFS"), ///< APFS Pooled Volumes
+		TSK_POOL_TYPE_UNSUPP(0xffff, "Unsupported") ///< Unsupported pool container type
+		;
+
+		private final long poolType;
+		private final String name;
+
+		private TSK_DB_POOL_TYPE_ENUM(int poolType, String name) {
+			this.poolType = (short) poolType;
+			this.name = name;
+		}
+
+		/**
+		 * Convert db pool type short value to the enum type
+		 *
+		 * @param poolType long value to convert
+		 *
+		 * @return the enum type
+		 */
+		public static TSK_DB_POOL_TYPE_ENUM valueOf(long poolType) {
+			for (TSK_DB_POOL_TYPE_ENUM type : TSK_DB_POOL_TYPE_ENUM.values()) {
+				if (type.poolType == poolType) {
+					return type;
+				}
+			}
+			throw new IllegalArgumentException(
+					MessageFormat.format(bundle.getString("TskData.tskDbFilesTypeEnum.exception.msg1.text"), poolType)); // TODO
+		}
+
+		/**
+		 * Get short value of the file type
+		 *
+		 * @return the long value of the file type
+		 */
+		public long getPoolType() {
+			return poolType;
+		}
+
+		public String getName() {
+			return name;
+		}
+	}	
 
 	/**
 	 * Identifies if a file was in a hash database or not. This is the known
diff --git a/tsk/auto/auto.cpp b/tsk/auto/auto.cpp
index 38ea60738..49e568a42 100755
--- a/tsk/auto/auto.cpp
+++ b/tsk/auto/auto.cpp
@@ -208,7 +208,14 @@ TskAuto::filterPoolVol(const TSK_POOL_VOLUME_INFO * /*pool_vol*/)
     /* Most of our tools can't handle pool volumes yet */
     if (tsk_verbose)
         fprintf(stderr, "filterPoolVol: Pool handling is not yet implemented for this tool\n");
-    printf("no pool!\n");
+    return TSK_FILTER_SKIP;
+}
+
+TSK_FILTER_ENUM
+TskAuto::filterPool(const TSK_POOL_INFO * /*pool_info*/) {
+    /* Most of our tools can't handle pool volumes yet */
+    if (tsk_verbose)
+        fprintf(stderr, "filterPoolVol: Pool handling is not yet implemented for this tool\n");
     return TSK_FILTER_SKIP;
 }
 
@@ -422,6 +429,13 @@ TskAuto::findFilesInPool(TSK_OFF_T start, TSK_POOL_TYPE_ENUM ptype)
         return TSK_ERR;
     }
 
+    // see if the super class wants to continue with this.
+    TSK_FILTER_ENUM retval1 = filterPool(pool);
+    //if (retval1 == TSK_FILTER_SKIP)
+    //    return TSK_WALK_CONT;
+    //else if ((retval1 == TSK_FILTER_STOP) || (tsk->getStopProcessing()))
+    //    return TSK_WALK_STOP;
+
     /* Only APFS pools are currently supported */
     if (pool->ctype == TSK_POOL_TYPE_APFS) {
 
diff --git a/tsk/auto/auto_db.cpp b/tsk/auto/auto_db.cpp
index 506173e1a..81b38b174 100755
--- a/tsk/auto/auto_db.cpp
+++ b/tsk/auto/auto_db.cpp
@@ -46,6 +46,7 @@ TskAutoDb::TskAutoDb(TskDb * a_db, TSK_HDB_INFO * a_NSRLDb, TSK_HDB_INFO * a_kno
     m_blkMapFlag = false;
     m_vsFound = false;
     m_volFound = false;
+    m_poolFound = false;
     m_stopped = false;
     m_foundStructure = false;
     m_imgTransactionOpen = false;
@@ -303,13 +304,40 @@ TSK_FILTER_ENUM TskAutoDb::filterVs(const TSK_VS_INFO * vs_info)
     return TSK_FILTER_CONT;
 }
 
+TSK_FILTER_ENUM
+TskAutoDb::filterPool(const TSK_POOL_INFO * pool_info)
+{
+    printf("filterPool\n");
+
+    m_poolFound = true; // TODO - this needs to get reset at some point
+
+    if (m_volFound && m_vsFound) {
+        // there's a volume system and volume
+        if (m_db->addPoolInfo(pool_info, m_curVolId, m_curPoolVs)) {
+            registerError();
+            return TSK_FILTER_STOP;
+        }
+    }
+    else {
+        // pool doesn't live in a volume, use image as parent
+        if (m_db->addPoolInfo(pool_info, m_curImgId, m_curPoolVs)) {
+            registerError();
+            return TSK_FILTER_STOP;
+        }
+    }
+
+    
+
+    return TSK_FILTER_CONT;
+}
+
 TSK_FILTER_ENUM
 TskAutoDb::filterPoolVol(const TSK_POOL_VOLUME_INFO * pool_vol)
 {
     printf("filterPoolVol 0x%llx\n", pool_vol->index);
-    m_curPoolVol = pool_vol->index;
+    //m_curPoolVol = pool_vol->index;
 
-    if (m_db->addPoolVolumeInfo(pool_vol, m_curPoolVsId, m_curPoolVol)) {
+    if (m_db->addPoolVolumeInfo(pool_vol, m_curPoolVs, m_curPoolVol)) {
         registerError();
         return TSK_FILTER_STOP;
     }
@@ -338,7 +366,14 @@ TskAutoDb::filterFs(TSK_FS_INFO * fs_info)
     TSK_FS_FILE *file_root;
     m_foundStructure = true;
 
-    if (m_volFound && m_vsFound) {
+    if (m_poolFound) {
+        // there's a pool
+        if (m_db->addFsInfo(fs_info, m_curPoolVol, m_curFsId)) {
+            registerError();
+            return TSK_FILTER_STOP;
+        }
+    }
+    else if (m_volFound && m_vsFound) {
         // there's a volume system and volume
         if (m_db->addFsInfo(fs_info, m_curVolId, m_curFsId)) {
             registerError();
@@ -530,6 +565,9 @@ TskAutoDb::startAddImage(TSK_IMG_INFO * img_info, const char* deviceId)
         return 1;
     }
 
+    printf("TskAutoDb::startAddImage\n");
+    fflush(stdout);
+
     if (tsk_verbose)
         tsk_fprintf(stderr, "TskAutoDb::startAddImage: Starting add image process\n");
 
diff --git a/tsk/auto/db_postgresql.cpp b/tsk/auto/db_postgresql.cpp
index 83653cf7b..77f0f4193 100755
--- a/tsk/auto/db_postgresql.cpp
+++ b/tsk/auto/db_postgresql.cpp
@@ -1008,6 +1008,23 @@ int TskDbPostgreSQL::addImageName(int64_t objId, char const *imgName, int sequen
     return ret;
 }
 
+int
+TskDbPostgreSQL::addPoolInfo(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId) {
+    return TSK_ERR; // TODO TODO
+}
+
+/**
+* Adds the sector addresses of the pool volumes into the db.
+* @returns 1 on error, 0 on success
+*/
+int
+TskDbPostgreSQL::addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
+    int64_t parObjId, int64_t& objId)
+{
+
+    return TSK_ERR; // TODO TODO
+}
+
 
 /**
 * @returns 1 on error, 0 on success
diff --git a/tsk/auto/db_sqlite.cpp b/tsk/auto/db_sqlite.cpp
index d15a3d5ed..379d311a8 100755
--- a/tsk/auto/db_sqlite.cpp
+++ b/tsk/auto/db_sqlite.cpp
@@ -305,6 +305,10 @@ TskDbSqlite::initialize()
             "Error creating tsk_vol_info table: %s\n")
         ||
         attempt_exec
+        ("CREATE TABLE tsk_pool_info (obj_id INTEGER PRIMARY KEY, addr INTEGER NOT NULL, pool_type INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+            "Error creating tsk_pool_info table: %s\n")
+        ||
+        attempt_exec
         ("CREATE TABLE tsk_fs_info (obj_id INTEGER PRIMARY KEY, img_offset INTEGER NOT NULL, fs_type INTEGER NOT NULL, block_size INTEGER NOT NULL, block_count INTEGER NOT NULL, root_inum INTEGER NOT NULL, first_inum INTEGER NOT NULL, last_inum INTEGER NOT NULL, display_name TEXT, pool_block INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
             "Error creating tsk_fs_info table: %s\n")
         ||
@@ -748,6 +752,36 @@ TskDbSqlite::addVsInfo(const TSK_VS_INFO* vs_info, int64_t parObjId,
                         "Error adding data to tsk_vs_info table: %s\n");
 }
 
+int
+TskDbSqlite::addPoolInfo(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId) {
+
+    char
+        stmt[1024];
+
+    // Temp - Make pool and then VS
+    int64_t poolObjId;
+    if (addObject(TSK_DB_OBJECT_TYPE_POOL, parObjId, poolObjId))
+        return 1;
+
+    snprintf(stmt, 1024,
+        "INSERT INTO tsk_pool_info (obj_id, addr, pool_type) VALUES (%" PRId64 ",%" PRIuDADDR ",%d)", poolObjId, 0, pool_info->ctype); // TODO - offset
+
+
+    int retVal = attempt_exec(stmt,
+        "Error adding data to tsk_pool_info table: %s\n");
+    if (retVal) {
+        return retVal;
+    }
+
+    if (addObject(TSK_DB_OBJECT_TYPE_VS, poolObjId, objId))
+        return 1;
+
+    snprintf(stmt, 1024,
+        "INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (%" PRId64 ", %d,%" PRIuDADDR ",%d)", objId, 0, 0, pool_info->block_size); // TODO - offset
+
+    return attempt_exec(stmt,
+        "Error adding data to tsk_vs_info table: %s\n");
+}
 
 /**
 * Adds the sector addresses of the pool volumes into the db.
diff --git a/tsk/auto/tsk_auto.h b/tsk/auto/tsk_auto.h
index d737efb92..4929854fd 100644
--- a/tsk/auto/tsk_auto.h
+++ b/tsk/auto/tsk_auto.h
@@ -120,6 +120,16 @@ class TskAuto {
      */
     virtual TSK_FILTER_ENUM filterVol(const TSK_VS_PART_INFO * vs_part);
 
+    /**
+    * TskAuto calls this method before it processes each pool that is found. 
+    * You can use this to learn about each pool before it is processed
+    * and you can force TskAuto to skip this volume.
+    *
+    * @param pool_vol Pool details
+    * @returns Value to show if pool should be processed, skipped, or process should stop.
+    */
+    virtual TSK_FILTER_ENUM filterPool(const TSK_POOL_INFO * pool_info);
+
     /**
     * TskAuto calls this method before it processes each pool volume that is found in a
     * pool. You can use this to learn about each volume before it is processed
diff --git a/tsk/auto/tsk_case_db.h b/tsk/auto/tsk_case_db.h
index c408363b3..2ed918755 100644
--- a/tsk/auto/tsk_case_db.h
+++ b/tsk/auto/tsk_case_db.h
@@ -45,6 +45,7 @@ class TskAutoDb:public TskAuto {
 
     virtual TSK_FILTER_ENUM filterVs(const TSK_VS_INFO * vs_info);
     virtual TSK_FILTER_ENUM filterVol(const TSK_VS_PART_INFO * vs_part);
+    virtual TSK_FILTER_ENUM filterPool(const TSK_POOL_INFO * pool_info);
     virtual TSK_FILTER_ENUM filterPoolVol(const TSK_POOL_VOLUME_INFO * pool_vol);
     virtual TSK_FILTER_ENUM filterFs(TSK_FS_INFO * fs_info);
     virtual TSK_RETVAL_ENUM processFile(TSK_FS_FILE * fs_file,
@@ -128,7 +129,7 @@ class TskAutoDb:public TskAuto {
     int64_t m_curVsId;      ///< Object ID of volume system currently being processed
     int64_t m_curVolId;     ///< Object ID of volume currently being processed
     int64_t m_curPoolVol; // POOL
-    int64_t m_curPoolVsId = 59; // POOL - temp
+    int64_t m_curPoolVs; // POOL - temp
     int64_t m_curFsId;      ///< Object ID of file system currently being processed
     int64_t m_curFileId;    ///< Object ID of file currently being processed
     TSK_INUM_T m_curDirAddr;		///< Meta address the directory currently being processed
@@ -140,6 +141,7 @@ class TskAutoDb:public TskAuto {
     bool m_fileHashFlag;
     bool m_vsFound;
     bool m_volFound;
+    bool m_poolFound;
     bool m_stopped;
     bool m_imgTransactionOpen;
     TSK_HDB_INFO * m_NSRLDb;
diff --git a/tsk/auto/tsk_db.h b/tsk/auto/tsk_db.h
index 8db94738c..e3024da59 100755
--- a/tsk/auto/tsk_db.h
+++ b/tsk/auto/tsk_db.h
@@ -40,6 +40,9 @@ typedef enum {
     TSK_DB_OBJECT_TYPE_VOL,     ///< Object is a volume 
     TSK_DB_OBJECT_TYPE_FS,      ///< Object is a file system
     TSK_DB_OBJECT_TYPE_FILE,    ///< Object is a file (exact type can be determined in the tsk_files table via TSK_DB_FILES_TYPE_ENUM)
+    TSK_DB_OBJECT_TYPE_ARTIFACT, ///< Autopsy placeholder
+    TSK_DB_OBJECT_TYPE_REPORT,   ///< Autopsy placeholder
+    TSK_DB_OBJECT_TYPE_POOL     ///< Object is a pool
 } TSK_DB_OBJECT_TYPE_ENUM;
 
 /**
@@ -175,6 +178,7 @@ class TskDb {
     virtual int addImageName(int64_t objId, char const *imgName, int sequence) = 0;
     virtual int addVsInfo(const TSK_VS_INFO * vs_info, int64_t parObjId, int64_t & objId) = 0;
     virtual int addVolumeInfo(const TSK_VS_PART_INFO * vs_part, int64_t parObjId, int64_t & objId) = 0;
+    virtual int addPoolInfo(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId) = 0;
     virtual int addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
         int64_t parObjId, int64_t& objId) = 0;
     virtual int addFsInfo(const TSK_FS_INFO * fs_info, int64_t parObjId, int64_t & objId) = 0;
diff --git a/tsk/auto/tsk_db_postgresql.h b/tsk/auto/tsk_db_postgresql.h
index e2234b718..90c070ef0 100755
--- a/tsk/auto/tsk_db_postgresql.h
+++ b/tsk/auto/tsk_db_postgresql.h
@@ -58,6 +58,9 @@ class TskDbPostgreSQL : public TskDb {
         int64_t & objId);
     int addFsInfo(const TSK_FS_INFO * fs_info, int64_t parObjId,
         int64_t & objId);
+    int addPoolInfo(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId);
+    int addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
+        int64_t parObjId, int64_t& objId);
     int addFsFile(TSK_FS_FILE * fs_file, const TSK_FS_ATTR * fs_attr,
         const char *path, const unsigned char *const md5,
         const TSK_DB_FILES_KNOWN_ENUM known, int64_t fsObjId,
diff --git a/tsk/auto/tsk_db_sqlite.h b/tsk/auto/tsk_db_sqlite.h
index 4c90d3803..b07f79fa2 100755
--- a/tsk/auto/tsk_db_sqlite.h
+++ b/tsk/auto/tsk_db_sqlite.h
@@ -50,6 +50,7 @@ class TskDbSqlite : public TskDb {
     int addImageName(int64_t objId, char const *imgName, int sequence);
     int addVsInfo(const TSK_VS_INFO * vs_info, int64_t parObjId,
         int64_t & objId);
+    int addPoolInfo(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId);
     int addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
         int64_t parObjId, int64_t& objId);
     int addVolumeInfo(const TSK_VS_PART_INFO * vs_part, int64_t parObjId,
-- 
GitLab