1 /*
2  * The Sleuth Kit
3  *
4  * Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
5  * Copyright (c) 2010-2012 Basis Technology Corporation. All Rights
6  * reserved.
7  *
8  * This software is distributed under the Common Public License 1.0
9  */
10 
11 #include "SectorRuns.h"
12 #include "tsk/framework/services/TskServices.h"
13 
14 /* This class is used to store a list of sector runs.  It is
15  * used to identify which runs contain unallocated data.
16  */
SectorRuns()17 SectorRuns::SectorRuns() :
18     m_runs(NULL),
19     m_numRunsUsed(0),
20     m_numRunsAlloc(0),
21     m_curRun(0)
22 {
23     // @@@
24     // Constructor should query the DB
25     // and build a list of IDs to empty sectors.
26     // The list is what will be iterated over.
27 }
28 
~SectorRuns()29 SectorRuns::~SectorRuns()
30 {
31     if (m_runs)
32         free(m_runs);
33     m_runs = NULL;
34 }
35 
36 
37 /**
38  * Add a run to the list.
39  *
40  * @param a_start Starting sector address relative to start of image file
41  * @param a_len Length of run in sectors.
42  * @param a_vol_id Volume ID that run is located in
43  * @returns -1 on error
44  */
addRun(uint64_t a_start,uint64_t a_len,int a_vol_id)45 int SectorRuns::addRun(uint64_t a_start, uint64_t a_len, int a_vol_id)
46 {
47     if (m_numRunsUsed == m_numRunsAlloc)
48     {
49         m_numRunsAlloc += 64;
50         if ((m_runs = (SectorRun *)realloc(m_runs, m_numRunsAlloc * sizeof(SectorRun))) == NULL)
51         {
52             TskServices::Instance().getLog().logError(L"SectorRuns::addRun - Error allocating sector runs\n");
53             return -1;
54         }
55     }
56     m_runs[m_numRunsUsed].start = a_start;
57     m_runs[m_numRunsUsed].len = a_len;
58     m_runs[m_numRunsUsed].vol_id = a_vol_id;
59     m_numRunsUsed++;
60     return 0;
61 }
62 
63 /**
64  * reset so that the next get() returns data on the first entry.
65  */
reset()66 void SectorRuns::reset()
67 {
68     m_curRun = 0;
69 }
70 
71 /**
72  * Advances internal pointer to next run.
73  *
74  * @returns -1 when at end of list
75  */
next()76 int SectorRuns::next()
77 {
78     if (m_curRun + 1 == m_numRunsUsed)
79         return -1;
80 
81     m_curRun++;
82     return 0;
83 }
84 
85 /**
86  * Get the length of the current entry.
87  * @returns length of run in sectors
88  */
getDataLen() const89 uint64_t SectorRuns::getDataLen() const
90 {
91     if (m_curRun >= m_numRunsUsed)
92         return 0;
93     return m_runs[m_curRun].len;
94 }
95 
96 /**
97  * Get starting address of current entry.
98  * @returns start of run in sectors
99  */
getDataStart() const100 uint64_t SectorRuns::getDataStart() const
101 {
102     if (m_curRun >= m_numRunsUsed)
103         return 0;
104     return m_runs[m_curRun].start;
105 }
106 
107 /**
108  * Get volume id of current entry.
109  * @returns volume ID of run in sectors
110  */
getVolID() const111 int SectorRuns::getVolID() const
112 {
113     if (m_curRun >= m_numRunsUsed)
114         return 0;
115     return m_runs[m_curRun].vol_id;
116 }
117 
118 /**
119  * Read data in the current entry into the buffer.
120  *
121  * @param a_offsetSect Sector offset to start reading from (relative to start of current sector run)
122  * @param a_lenSect Number of sectors to read
123  * @param a_buffer Buffer to read into (must be of size a_len * 512 or larger)
124  * @returns -1 on error or number of sectors read
125  */
getData(uint64_t a_offsetSect,int a_lenSect,char * a_buffer) const126 int SectorRuns::getData(uint64_t a_offsetSect, int a_lenSect, char * a_buffer) const
127 {
128     if (m_curRun >= m_numRunsUsed)
129         return -1;
130 
131     if (a_offsetSect > m_runs[m_curRun].len)
132         return -1;
133 
134     uint64_t len_toread = a_lenSect;
135     if (a_offsetSect + a_lenSect > m_runs[m_curRun].len)
136         len_toread = m_runs[m_curRun].len - a_offsetSect;
137 
138     return TskServices::Instance().getImageFile().getSectorData(m_runs[m_curRun].start + a_offsetSect, len_toread, a_buffer);
139 }
140