1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
|
// ****************************************************************************
// Project: GUYMAGER
// ****************************************************************************
// Programmer: Guy Voncken
// Police Grand-Ducale
// Service de Police Judiciaire
// Section Nouvelles Technologies
// ****************************************************************************
// Copyright 2008, 2009, 2010, 2011 Guy Voncken
//
// This file is part of guymager.
//
// guymager is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// guymager is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with guymager. If not, see <http://www.gnu.org/licenses/>.
#ifndef __DEVICE_H__
#define __DEVICE_H__
#include "hash.h"
#include <parted/parted.h>
#include <QMetaType>
#include <QReadWriteLock>
#include <QMutex>
#include <QTime>
#include "fifo.h"
#include "info.h"
#include "file.h"
#include "media.h"
#include "config.h"
class t_ThreadRead;
class t_ThreadHash;
class t_ThreadCompress;
class t_ThreadWrite;
#define DEVICE_DEFAULT_SECTOR_SIZE ((size_t)512)
class t_Device
{
public:
typedef enum
{
Idle,
Acquire,
AcquirePaused,
Verify,
VerifyPaused,
Cleanup,
Finished,
Aborted
} t_State;
typedef enum
{
None,
UserRequest,
ThreadWriteWriteError,
ThreadWriteVerifyError,
ThreadReadFileError,
InfoWriteError,
AcquisitionStartFailed
} t_AbortReason;
static const int AutoFracLen = -1; // Use up to 2 digits after decimal point (min. 3 significant digits)
static const int AutoUnitThreshold = -1;
static const int FileDescEmpty = -1;
class t_Acquisition
{
public:
QString ImagePath; // Always end with /
QString InfoPath; // Always end with /
QString ImageFilename; // Image filename, without extension
QString InfoFilename; // Info filename, without extension
t_File::Format Format;
bool Clone;
bool CalcMD5;
bool CalcSHA256;
bool VerifySrc;
bool VerifyDst;
QString CaseNumber;
QString EvidenceNumber;
QString Examiner;
QString Description;
QString Notes;
quint64 SplitFileSize; // 0 means do not split
};
class t_ImageFileHash // Holds the hash of a complete image file (not just the image contents)
{
public:
t_ImageFileHash (const QString &Filename, t_pHashMD5Digest pMD5Digest=NULL, bool MD5ok=false)
{
this->Filename = Filename;
MD5Valid = (pMD5Digest != NULL) && MD5ok;
if (MD5Valid)
MD5Digest = *pMD5Digest;
}
public:
QString Filename;
bool MD5Valid;
t_HashMD5Digest MD5Digest;
};
class t_AddStateInfo // Allows the user to add state information to a device
{
public:
t_AddStateInfo () : CanBeAcquired(true),
Color(COLOR_DEFAULT)
{};
public:
QString Info;
bool CanBeAcquired;
int Color; // Refers to the color AdditionalState1, AdditionalState2, ... in the configuration file.
};
typedef QList<t_ImageFileHash *> t_ImageFileHashList;
public:
t_Device (const QString &SerialNumber=QString(), const PedDevice *pPedDev=NULL);
t_Device (const QString &SerialNumber, const QString &LinuxDevice, const QString &Model,
quint64 SectorSize, quint64 SectorSizePhys, quint64 Size=0);
~t_Device ();
static QVariant GetSerialNumber (t_pDevice pDevice);
static QVariant GetLinuxDevice (t_pDevice pDevice);
static QVariant GetModel (t_pDevice pDevice);
static QVariant GetState (t_pDevice pDevice);
static QVariant GetAddStateInfo (t_pDevice pDevice);
static QVariant GetSectorSize (t_pDevice pDevice);
static QVariant GetSectorSizePhys (t_pDevice pDevice);
static QVariant GetBadSectorCount (t_pDevice pDevice);
static QVariant GetBadSectorCountVerify(t_pDevice pDevice);
static QVariant GetSize (t_pDevice pDevice);
static QVariant GetSizeHuman (t_pDevice pDevice);
static QVariant GetSizeHumanFrac (t_pDevice pDevice, bool SI=true, int FracLen=AutoFracLen, int UnitThreshold=AutoUnitThreshold);
static QVariant GetHiddenAreas (t_pDevice pDevice);
static QVariant GetProgress (t_pDevice pDevice);
static QVariant GetCurrentSpeed (t_pDevice pDevice);
static QVariant GetAverageSpeed (t_pDevice pDevice);
static QVariant GetRemaining (t_pDevice pDevice);
static QVariant GetFifoStatus (t_pDevice pDevice);
inline void SetCurrentWritePos (quint64 Pos)
{
SemCurrentWritePos.lockForWrite ();
CurrentWritePos = Pos;
SemCurrentWritePos.unlock ();
}
inline void IncCurrentWritePos (int Inc)
{
SemCurrentWritePos.lockForWrite ();
CurrentWritePos += Inc; //lint !e737 Loss of sign
SemCurrentWritePos.unlock ();
}
inline quint64 GetCurrentWritePos (void)
{
quint64 Pos;
SemCurrentWritePos.lockForRead ();
Pos = CurrentWritePos;
SemCurrentWritePos.unlock ();
return Pos;
}
inline void SetCurrentVerifyPosSrc (quint64 Pos)
{
SemCurrentVerifyPosSrc.lockForWrite ();
CurrentVerifyPosSrc = Pos;
SemCurrentVerifyPosSrc.unlock ();
}
inline void IncCurrentVerifyPosSrc (int Inc)
{
SemCurrentVerifyPosSrc.lockForWrite ();
CurrentVerifyPosSrc += Inc; //lint !e737 Loss of sign
SemCurrentVerifyPosSrc.unlock ();
}
inline void SetCurrentVerifyPosDst (quint64 Pos)
{
SemCurrentVerifyPosDst.lockForWrite ();
CurrentVerifyPosDst = Pos;
SemCurrentVerifyPosDst.unlock ();
}
inline void IncCurrentVerifyPosDst (int Inc)
{
SemCurrentVerifyPosDst.lockForWrite ();
CurrentVerifyPosDst += Inc; //lint !e737 Loss of sign
SemCurrentVerifyPosDst.unlock ();
}
inline quint64 GetCurrentVerifyPos (void)
{
quint64 PosSrc;
quint64 PosDst;
SemCurrentVerifyPosSrc.lockForRead ();
PosSrc = CurrentVerifyPosSrc;
SemCurrentVerifyPosSrc.unlock ();
SemCurrentVerifyPosDst.lockForRead ();
PosDst = CurrentVerifyPosDst;
SemCurrentVerifyPosDst.unlock ();
if ( Acquisition.VerifySrc && Acquisition.VerifyDst) return GETMIN (PosSrc, PosDst);
else if ( Acquisition.VerifySrc && !Acquisition.VerifyDst) return PosSrc;
else if (!Acquisition.VerifySrc && Acquisition.VerifyDst) return PosDst;
else return 0;
}
inline void AddBadSector (quint64 Sector)
{
SemBadSectors.lock ();
if (State == Acquire)
BadSectors .append(Sector);
else BadSectorsVerify.append(Sector);
SemBadSectors.unlock ();
}
APIRET GetBadSectors (QList<quint64> &BadSectorsCopy, bool GetVerify)
{
SemBadSectors.lock ();
if (GetVerify)
BadSectorsCopy = BadSectorsVerify;
else BadSectorsCopy = BadSectors;
SemBadSectors.unlock ();
return NO_ERROR;
}
quint64 GetBadSectorCount (bool GetVerify)
{
quint64 Count;
SemBadSectors.lock ();
if (GetVerify)
Count = BadSectorsVerify.count(); //lint !e732 Loss of sign
else Count = BadSectors .count(); //lint !e732 Loss of sign
SemBadSectors.unlock ();
return Count;
}
APIRET ClearBadSectors (void)
{
SemBadSectors.lock ();
BadSectorsVerify.clear();
BadSectors .clear();
SemBadSectors.unlock ();
return NO_ERROR;
}
APIRET GetMessage (QString &MessageCopy)
{
SemMessage.lock ();
MessageCopy = Message;
SemMessage.unlock ();
return NO_ERROR;
}
APIRET SetMessage (const QString &NewMessage)
{
SemMessage.lock ();
Message = NewMessage;
SemMessage.unlock ();
return NO_ERROR;
}
bool HasHashThread (void) const;
bool HasCompressionThreads (void) const;
const char *StateStr (void);
private:
void Initialise (void);
void InitialiseDeviceSpecific (const QString &SerialNumber, const QString &LinuxDevice, const QString &Model,
quint64 SectorSize, quint64 SectorSizePhys, quint64 Size);
public: QString SerialNumber;
QString Model;
QString LinuxDevice; // for instance /dev/hda
bool Local; // it's a local device (cannot be acquired)
quint64 SectorSize;
quint64 SectorSizePhys;
quint64 Size;
bool SpecialDevice; // Special device that has been added manually to the device table
bool Removable;
t_MediaInfo MediaInfo;
t_State State;
private: QString Message; // Used by the threads to communicate messages displayed in spreadsheet field "state"
public: t_AddStateInfo AddStateInfo;
bool AbortRequest;
int AbortCount; // Little easter egg ;-)
t_AbortReason AbortReason;
bool DeleteAfterAbort;
t_Acquisition Acquisition;
t_Info Info; // Must only be used if Aqcuisition.InfoFilename is valid!
int FileDescSrc;
quint64 CurrentReadPos; // Accessed from different threads, but never at the same time. During acquisition, it is exclusively accessed by the read threads. Using a mutex would be nicer, but could decrease performance.
private: quint64 CurrentVerifyPosSrc; // Accessed concurrently, use appropriate functions
private: quint64 CurrentVerifyPosDst; // Accessed concurrently, use appropriate functions
private: quint64 CurrentWritePos; // Accessed concurrently, use appropriate functions
private: QList<quint64> BadSectors; // Accessed concurrently, use appropriate functions
private: QList<quint64> BadSectorsVerify; // Accessed concurrently, use appropriate functions
public: bool FallbackMode; // Set if an error occurs while reading a large block. If set, sectors are read individually until the next large block boundary.
QDateTime StartTimestamp;
QDateTime StartTimestampVerify;
QDateTime StopTimestamp;
public: t_ThreadRead *pThreadRead;
t_ThreadHash *pThreadHash;
t_ThreadWrite *pThreadWrite;
QList<t_ThreadCompress *> ThreadCompressList;
public: t_pFifoMemory pFifoMemory;
t_pFifo pFifoRead; // Pointers to the Fifos used by the different
t_pFifo pFifoHashIn; // threads. Some of them point to the same Fifos,
t_pFifo pFifoHashOut; // for instance pFifoRead and pFifoHashIn.
t_pFifo pFifoWrite;
t_pFifoCompressIn pFifoCompressIn;
t_pFifoCompressOut pFifoCompressOut;
int FifoMaxBlocks;
unsigned int FifoBlockSize; // The pure size as it would be required by for the data
unsigned int FifoAllocBlockSize; // The block size as it is used for real allocation
t_HashMD5Digest MD5Digest;
t_HashMD5Digest MD5DigestVerifySrc;
t_HashMD5Digest MD5DigestVerifyDst;
t_HashSHA256Digest SHA256Digest;
t_HashSHA256Digest SHA256DigestVerifySrc;
t_HashSHA256Digest SHA256DigestVerifyDst;
t_ImageFileHashList ImageFileHashList;
public: quint64 PrevPos; // Some variables for
QTime PrevTimestamp; // the current speed
double PrevSpeed; // calculation.
bool Checked; // Helper variables for matching algorithm ...
bool AddedNow; // ... in SlotScanFinished, not used elsewhere.
private: QReadWriteLock SemCurrentWritePos;
private: QReadWriteLock SemCurrentVerifyPosSrc;
private: QReadWriteLock SemCurrentVerifyPosDst;
private: QMutex SemBadSectors;
private: QMutex SemMessage;
};
class t_DeviceList: public QList<t_pDevice>
{
public:
t_DeviceList (void);
~t_DeviceList ();
t_pDevice AppendNew (const QString &SerialNumber, const PedDevice *pPedDev);
t_pDevice AppendNew (const QString &SerialNumber, const QString &LinuxDevice, const QString &Model,
quint64 SectorSize, quint64 SectorSizePhys, quint64 Size=0);
APIRET MatchDevice (t_pcDevice pDevCmp, t_pDevice &pDevMatch);
bool UsedAsCloneDestination (t_pcDevice pDevChk);
};
typedef t_DeviceList *t_pDeviceList;
Q_DECLARE_METATYPE(t_pDeviceList); //lint !e19 Useless declaration
// ------------------------------------
// Error codes
// ------------------------------------
enum
{
ERROR_DEVICE_SERNR_MATCH_MODEL_MISMATCH = ERROR_BASE_DEVICE + 1,
ERROR_DEVICE_SERNR_MATCH_LENGTH_MISMATCH,
ERROR_DEVICE_BAD_STATE,
ERROR_DEVICE_BAD_ABORTREASON,
ERROR_DEVICE_NOT_CLEAN,
ERROR_DEVICE_INVALID_MEDIAINFOSTATE
};
#endif
|