diff --git a/tsk/auto/auto.cpp b/tsk/auto/auto.cpp
index 6c08103fb23f4e25cb84cb76eb8653703033c919..fc95317e234d14153a54749a07718e83ba59eff9 100755
--- a/tsk/auto/auto.cpp
+++ b/tsk/auto/auto.cpp
@@ -146,6 +146,10 @@ uint8_t TskAuto::openImageHandle(TSK_IMG_INFO * a_img_info)
 void
  TskAuto::closeImage()
 {
+    for (int i = 0; i < m_poolInfos.size(); i++) {
+        tsk_pool_close(m_poolInfos[i]);
+    }
+
     if ((m_img_info) && (m_internalOpen)) {
         tsk_img_close(m_img_info);
     }
@@ -493,7 +497,10 @@ TskAuto::findFilesInPool(TSK_OFF_T start, TSK_POOL_TYPE_ENUM ptype)
         registerError();
         return TSK_ERR;
     }
-    pool->close(pool);
+
+    // Store the pool_info for later use. It will be closed at the end of the add image process.
+    m_poolInfos.push_back(pool);
+
     return TSK_OK;
 }
 
diff --git a/tsk/auto/auto_db.cpp b/tsk/auto/auto_db.cpp
index 43b84169e186b4603470bb4dbb7f1b41a38e8d00..0fdfdf67090eb6468ae72143481e4f75e3f48afe 100755
--- a/tsk/auto/auto_db.cpp
+++ b/tsk/auto/auto_db.cpp
@@ -315,6 +315,8 @@ TskAutoDb::filterPool(const TSK_POOL_INFO * pool_info)
             registerError();
             return TSK_FILTER_STOP;
         }
+        // Save the parent obj ID for the pool
+        m_poolOffsetToParentId[pool_info->img_offset] = m_curVolId;
     }
     else {
         // pool doesn't live in a volume, use image as parent
@@ -322,13 +324,81 @@ TskAutoDb::filterPool(const TSK_POOL_INFO * pool_info)
             registerError();
             return TSK_FILTER_STOP;
         }
+        // Save the parent obj ID for the pool
+        m_poolOffsetToParentId[pool_info->img_offset] = m_curImgId;
     }
 
-    
+    // Store the volume system object ID for later use
+    m_poolOffsetToVsId[pool_info->img_offset] = m_curPoolVs;
 
     return TSK_FILTER_CONT;
 }
 
+/**
+* Adds unallocated pool blocks to a new volume.
+*
+* @param numPool Will be updated with the number of pools processed
+*
+* @return Returns 0 for success, 1 for failure
+*/
+TSK_RETVAL_ENUM
+TskAutoDb::addUnallocatedPoolBlocksToDb(size_t & numPool) {
+
+    for (int i = 0; i < m_poolInfos.size(); i++) {
+        const TSK_POOL_INFO * pool_info = m_poolInfos[i];
+        if (m_poolOffsetToVsId.find(pool_info->img_offset) == m_poolOffsetToVsId.end()) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_AUTO_DB);
+            tsk_error_set_errstr("Error addUnallocatedPoolBlocksToDb() - could not find volume system object ID for pool at offset %lld", pool_info->img_offset);
+            return TSK_ERR;
+        }
+        int64_t curPoolVs = m_poolOffsetToVsId[pool_info->img_offset];
+
+        /* Make sure  the pool_info is still allocated */
+        if (pool_info->tag != TSK_POOL_INFO_TAG) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_AUTO_DB);
+            tsk_error_set_errstr("Error addUnallocatedPoolBlocksToDb() - pool_info is not allocated");
+            return TSK_ERR;
+        }
+
+        /* Only APFS pools are currently supported */
+        if (pool_info->ctype != TSK_POOL_TYPE_APFS) {
+            continue;
+        }
+
+        /* Increment the count of pools found */
+        numPool++;
+
+        /* Create the volume */
+        int64_t unallocVolObjId;
+        m_db->addUnallocatedPoolVolume(pool_info->num_vols, curPoolVs, unallocVolObjId);
+
+        /* Create the unallocated space files */
+        TSK_FS_ATTR_RUN * unalloc_runs = tsk_pool_unallocated_runs(pool_info);
+        TSK_FS_ATTR_RUN * current_run = unalloc_runs;
+        vector<TSK_DB_FILE_LAYOUT_RANGE> ranges;
+        while (current_run != NULL) {
+
+            TSK_DB_FILE_LAYOUT_RANGE tempRange(current_run->addr * pool_info->block_size, current_run->len * pool_info->block_size, 0);
+
+            ranges.push_back(tempRange);
+            int64_t fileObjId = 0;
+            if (m_db->addUnallocBlockFile(unallocVolObjId, NULL, current_run->len * pool_info->block_size, ranges, fileObjId, m_curImgId)) {
+                registerError();
+                tsk_fs_attr_run_free(unalloc_runs);
+                return TSK_ERR;
+            }
+
+            current_run = current_run->next;
+            ranges.clear();
+        }
+        tsk_fs_attr_run_free(unalloc_runs);
+    }
+
+    return TSK_OK;
+}
+
 TSK_FILTER_ENUM
 TskAutoDb::filterPoolVol(const TSK_POOL_VOLUME_INFO * pool_vol)
 {
@@ -1032,7 +1102,7 @@ TSK_WALK_RET_ENUM TskAutoDb::fsWalkUnallocBlocksCb(const TSK_FS_BLOCK *a_block,
 */
 TSK_RETVAL_ENUM TskAutoDb::addFsInfoUnalloc(const TSK_DB_FS_INFO & dbFsInfo) {
 
-    // Unalloc space is not yet implemented for APFS
+    // Unalloc space is handled separately for APFS
     if (dbFsInfo.fType == TSK_FS_TYPE_APFS) {
         return TSK_OK;
     }
@@ -1103,18 +1173,20 @@ TSK_RETVAL_ENUM TskAutoDb::addUnallocSpaceToDb() {
 
     size_t numVsP = 0;
     size_t numFs = 0;
+    size_t numPool = 0;
 
     TSK_RETVAL_ENUM retFsSpace = addUnallocFsSpaceToDb(numFs);
     TSK_RETVAL_ENUM retVsSpace = addUnallocVsSpaceToDb(numVsP);
+    TSK_RETVAL_ENUM retPoolSpace = addUnallocatedPoolBlocksToDb(numPool);
 
-    //handle case when no fs and no vs partitions
+    //handle case when no fs and no vs partitions or pools
     TSK_RETVAL_ENUM retImgFile = TSK_OK;
-    if (numVsP == 0 && numFs == 0) {
+    if (numVsP == 0 && numFs == 0 && numPool == 0) {
         retImgFile = addUnallocImageSpaceToDb();
     }
     
     
-    if (retFsSpace == TSK_ERR || retVsSpace == TSK_ERR || retImgFile == TSK_ERR)
+    if (retFsSpace == TSK_ERR || retVsSpace == TSK_ERR || retPoolSpace == TSK_ERR || retImgFile == TSK_ERR)
         return TSK_ERR;
     else
         return TSK_OK;
@@ -1217,6 +1289,19 @@ TSK_RETVAL_ENUM TskAutoDb::addUnallocVsSpaceToDb(size_t & numVsP) {
                 //skip processing this vspart
                 continue;
             }
+
+            // Check if the volume contains a pool
+            bool hasPool = false;
+            for (std::map<int64_t, int64_t>::iterator iter = m_poolOffsetToParentId.begin(); iter != m_poolOffsetToParentId.end(); ++iter) {
+                if (iter->second == vsPart.objId) {
+                    hasPool = true;
+                }
+            }
+            if (hasPool) {
+                // Skip processing this vspart
+                continue;
+            }
+
         } //end checking vspart flags
 
         //get sector size and image offset from parent vs info
diff --git a/tsk/auto/db_postgresql.cpp b/tsk/auto/db_postgresql.cpp
index 4afe0e00fa6e847e3ae87dca409565b229ca162a..b7bc126d7bcb8bff0cfb8f7140ac6a74cf621f07 100755
--- a/tsk/auto/db_postgresql.cpp
+++ b/tsk/auto/db_postgresql.cpp
@@ -1012,8 +1012,18 @@ int TskDbPostgreSQL::addImageName(int64_t objId, char const *imgName, int sequen
     return ret;
 }
 
+/**
+* Creates a new tsk_pool_info database entry and a new tsk_vs_info
+* entry with the tsk_pool_info as its parent.
+*
+* @ param pool_info The pool to save to the database
+* @ param parObjId The ID of the parent of the pool object
+* @ param vsObjId Will be set to the object ID of the new volume system created as a child of
+*               the new pool.
+* @returns 1 on error, 0 on success
+*/
 int
-TskDbPostgreSQL::addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId) {
+TskDbPostgreSQL::addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& vsObjId) {
 
     char stmt[1024];
 
@@ -1032,11 +1042,11 @@ TskDbPostgreSQL::addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObj
     }
 
     // Add volume system
-    if (addObject(TSK_DB_OBJECT_TYPE_VS, poolObjId, objId))
+    if (addObject(TSK_DB_OBJECT_TYPE_VS, poolObjId, vsObjId))
         return 1;
 
     snprintf(stmt, 1024,
-        "INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (%" PRId64 ", %d,%" PRIuDADDR ",%d)", objId, TSK_VS_TYPE_APFS, pool_info->img_offset, pool_info->block_size);
+        "INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (%" PRId64 ", %d,%" PRIuDADDR ",%d)", vsObjId, TSK_VS_TYPE_APFS, pool_info->img_offset, pool_info->block_size);
 
     return attempt_exec(stmt,
         "Error adding data to tsk_vs_info table: %s\n");
@@ -1044,6 +1054,11 @@ TskDbPostgreSQL::addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObj
 
 /**
 * Adds the sector addresses of the pool volumes into the db.
+*
+* @param pool_vol The pool volume to save to the DB
+* @param parObjId The ID of the parent of the pool volume (should be a volume system)
+* @param objId    Will be set to the object ID of the new volume
+*
 * @returns 1 on error, 0 on success
 */
 int
@@ -1073,6 +1088,41 @@ TskDbPostgreSQL::addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
     return TSK_OK;
 }
 
+/**
+* Adds a fake volume that will hold the unallocated blocks for the pool.
+*
+* @param vol_index The index for the new volume (should be one higher than the number of pool volumes)
+* @param parObjId  The object ID of the parent volume system
+* @param objId     Will be set to the object ID of the new volume
+*
+* @returns 1 on error, 0 on success
+*/
+int
+TskDbPostgreSQL::addUnallocatedPoolVolume(int vol_index, int64_t parObjId, int64_t& objId)
+{
+
+    char stmt[1024];
+
+    if (addObject(TSK_DB_OBJECT_TYPE_VOL, parObjId, objId))
+        return 1;
+
+    char *desc = "Unallocated Blocks";
+    char *desc_sql = PQescapeLiteral(conn, desc, strlen(desc));
+
+    snprintf(stmt, 1024,
+        "INSERT INTO tsk_vs_parts (obj_id, addr, start, length, descr, flags)"
+        "VALUES (%lld, %" PRIuPNUM ",%d, %d, %s, %d)",
+        objId, vol_index, 0, 0, desc_sql, 0);
+
+    if (attempt_exec(stmt, "Error adding data to tsk_vs_parts table: %s\n")) {
+        PQfreemem(desc_sql);
+        return TSK_ERR;
+    }
+
+    PQfreemem(desc_sql);
+    return TSK_OK;
+}
+
 
 /**
 * @returns 1 on error, 0 on success
diff --git a/tsk/auto/db_sqlite.cpp b/tsk/auto/db_sqlite.cpp
index 2f82aa51bff69cb0af9aec79938993790515de57..2a0e8868f9ef1d5eee4e4726627b772c27ba3655 100644
--- a/tsk/auto/db_sqlite.cpp
+++ b/tsk/auto/db_sqlite.cpp
@@ -754,17 +754,17 @@ TskDbSqlite::addVsInfo(const TSK_VS_INFO* vs_info, int64_t parObjId,
 }
 
 /**
-* Creats a new tsk_pool_info database entry and a new tsk_vs_info 
+* Creates a new tsk_pool_info database entry and a new tsk_vs_info 
 * entry with the tsk_pool_info as its parent.
 *
 * @ param pool_info The pool to save to the database
 * @ param parObjId The ID of the parent of the pool object
-* @ param objId Will be set to the object ID of the new volume system created as a child of 
+* @ param vsObjId Will be set to the object ID of the new volume system created as a child of 
 *               the new pool.
 * @returns 1 on error, 0 on success
 */
 int
-TskDbSqlite::addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId) {
+TskDbSqlite::addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& vsObjId) {
 
     char
         stmt[1024];
@@ -784,22 +784,54 @@ TskDbSqlite::addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId,
     }
 
     // Add volume system
-    if (addObject(TSK_DB_OBJECT_TYPE_VS, poolObjId, objId))
+    if (addObject(TSK_DB_OBJECT_TYPE_VS, poolObjId, vsObjId))
         return 1;
 
     snprintf(stmt, 1024,
-        "INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (%" PRId64 ", %d,%" PRIuDADDR ",%d)", objId, TSK_VS_TYPE_APFS, pool_info->img_offset, pool_info->block_size); // TODO - offset
+        "INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (%" PRId64 ", %d,%" PRIuDADDR ",%d)", vsObjId, TSK_VS_TYPE_APFS, pool_info->img_offset, 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.
+* Adds a fake volume that will hold the unallocated blocks for the pool.
+*
+* @param vol_index The index for the new volume (should be one higher than the number of pool volumes)
+* @param parObjId  The object ID of the parent volume system
+* @param objId     Will be set to the object ID of the new volume
+*
+* @returns 1 on error, 0 on success
+*/
+int
+TskDbSqlite::addUnallocatedPoolVolume(int vol_index, int64_t parObjId, int64_t& objId)
+{
+    char* zSQL;
+    int ret;
+
+    if (addObject(TSK_DB_OBJECT_TYPE_VOL, parObjId, objId))
+        return 1;
+
+    char* desc = "Unallocated Blocks";
+    zSQL = sqlite3_mprintf(
+        "INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags)"
+        "VALUES (%lld, %" PRIuPNUM ",%" PRIuDADDR ",%" PRIuDADDR ",'%q',%d)",
+        objId, vol_index, 0, 0,
+        desc, 0);
 
+    ret = attempt_exec(zSQL,
+        "Error adding data to tsk_vs_parts table: %s\n");
+    sqlite3_free(zSQL);
+    return ret;
+}
+
+/**
+* Adds the sector addresses of the pool volumes into the db.
+*
 * @param pool_vol The pool volume to save to the DB
 * @param parObjId The ID of the parent of the pool volume (should be a volume system)
-* @param objId Will be set to the object ID of the new volume
+* @param objId    Will be set to the object ID of the new volume
+*
 * @returns 1 on error, 0 on success
 */
 int
diff --git a/tsk/auto/tsk_auto.h b/tsk/auto/tsk_auto.h
index 631625614cc14882b82ad74c572af82fa00d4cb7..028a95d82b7a37ced4054ffb3c2ec9bdbd4afe50 100644
--- a/tsk/auto/tsk_auto.h
+++ b/tsk/auto/tsk_auto.h
@@ -263,10 +263,11 @@ class TskAuto {
 
   protected:
     TSK_IMG_INFO * m_img_info;
+    std::vector<const TSK_POOL_INFO*> m_poolInfos;
+
     bool m_internalOpen;        ///< True if m_img_info was opened in TskAuto and false if passed in
     bool m_stopAllProcessing;   ///< True if no further processing should occur
 
-
     uint8_t isNtfsSystemFiles(TSK_FS_FILE * fs_file, const char *path);
     uint8_t isFATSystemFiles(TSK_FS_FILE * fs_file);
     uint8_t isDotDir(TSK_FS_FILE * fs_file);
diff --git a/tsk/auto/tsk_case_db.h b/tsk/auto/tsk_case_db.h
index eee845990c82acf2f44045eb540398e6f53ce6e3..422ca330d66ab1bac894d558d5fc433bb02413e9 100644
--- a/tsk/auto/tsk_case_db.h
+++ b/tsk/auto/tsk_case_db.h
@@ -154,6 +154,12 @@ class TskAutoDb:public TskAuto {
     bool m_foundStructure;  ///< Set to true when we find either a volume or file system
     bool m_attributeAdded; ///< Set to true when an attribute was added by processAttributes
 
+    // These are used to write unallocated blocks for pools at the end of the add image
+    // process. We can't load the pool_info objects directly from the database so we will
+    // store info about them here.
+    std::map<int64_t, int64_t> m_poolOffsetToParentId;
+    std::map<int64_t, int64_t> m_poolOffsetToVsId;
+
     // prevent copying until we add proper logic to handle it
     TskAutoDb(const TskAutoDb&);
     TskAutoDb & operator=(const TskAutoDb&);
@@ -186,7 +192,7 @@ class TskAutoDb:public TskAuto {
         TSK_OFF_T offset, TSK_DADDR_T addr, char *buf, size_t size,
         TSK_FS_BLOCK_FLAG_ENUM a_flags, void *ptr);
     int md5HashAttr(unsigned char md5Hash[16], const TSK_FS_ATTR * fs_attr);
-
+    TSK_RETVAL_ENUM addUnallocatedPoolBlocksToDb(size_t & numPool);
     static TSK_WALK_RET_ENUM fsWalkUnallocBlocksCb(const TSK_FS_BLOCK *a_block, void *a_ptr);
     TSK_RETVAL_ENUM addFsInfoUnalloc(const TSK_DB_FS_INFO & dbFsInfo);
     TSK_RETVAL_ENUM addUnallocFsSpaceToDb(size_t & numFs);
diff --git a/tsk/auto/tsk_db.h b/tsk/auto/tsk_db.h
index 291f0c30c821b66fc53deff128af666987e9d4d7..a95aaecc5fa95db67f4d3cb6146d7ac9d4ea51e8 100755
--- a/tsk/auto/tsk_db.h
+++ b/tsk/auto/tsk_db.h
@@ -180,9 +180,10 @@ 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 addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId) = 0;
+    virtual int addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& vsObjId) = 0;
     virtual int addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
         int64_t parObjId, int64_t& objId) = 0;
+    virtual int addUnallocatedPoolVolume(int vol_index, int64_t parObjId, int64_t& objId) = 0;
     virtual int addFsInfo(const TSK_FS_INFO * fs_info, int64_t parObjId, int64_t & objId) = 0;
     virtual int addFsFile(TSK_FS_FILE * fs_file, const TSK_FS_ATTR * fs_attr,
         const char *path, const unsigned char *const md5,
diff --git a/tsk/auto/tsk_db_postgresql.h b/tsk/auto/tsk_db_postgresql.h
index 873b142babca2158d569deeb9c580a089da15d79..c4cfa763158af9f356f828f9e31cb0b6f708debf 100755
--- a/tsk/auto/tsk_db_postgresql.h
+++ b/tsk/auto/tsk_db_postgresql.h
@@ -58,9 +58,10 @@ class TskDbPostgreSQL : public TskDb {
         int64_t & objId);
     int addFsInfo(const TSK_FS_INFO * fs_info, int64_t parObjId,
         int64_t & objId);
-    int addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId);
+    int addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& vsObjId);
     int addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
         int64_t parObjId, int64_t& objId);
+    int addUnallocatedPoolVolume(int vol_index, 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 7fa3abae9a08da0c338145d9b6ce865a174720e6..13d55412167e0b8e77de117e7c35f0afce86a3ca 100755
--- a/tsk/auto/tsk_db_sqlite.h
+++ b/tsk/auto/tsk_db_sqlite.h
@@ -50,9 +50,10 @@ 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 addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId);
+    int addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& vsObjId);
     int addPoolVolumeInfo(const TSK_POOL_VOLUME_INFO* pool_vol,
         int64_t parObjId, int64_t& objId);
+    int addUnallocatedPoolVolume(int vol_index, int64_t parObjId, int64_t& objId);
     int addVolumeInfo(const TSK_VS_PART_INFO * vs_part, int64_t parObjId,
         int64_t & objId);
     int addFsInfo(const TSK_FS_INFO * fs_info, int64_t parObjId,