[Forensics-changes] [SCM] debian-forensics/guymager branch, debian, updated. debian/0.6.5-1-9-g9129a0b

Michael Prokop mika at debian.org
Fri May 4 14:35:59 UTC 2012


The following commit has been merged in the debian branch:
commit 371bbc0ec5eefdb6173e4252ee021c7f35c14ed6
Author: Michael Prokop <mika at debian.org>
Date:   Fri May 4 15:01:38 2012 +0200

    Merging upstream version 0.6.7.

diff --git a/aewf.cpp b/aewf.cpp
index 5b9bb7c..c22b4ef 100644
--- a/aewf.cpp
+++ b/aewf.cpp
@@ -9,7 +9,7 @@
 //  Module:         Multithreaded AEWF (AEWF = Advanced EWF)
 // ****************************************************************************
 
-// Copyright 2008, 2009, 2010, 2011 Guy Voncken
+// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 //
 // This file is part of guymager.
 //
@@ -52,11 +52,13 @@
 // Qt inconsistently defines its little/big endian functions, see QTBUG-21208 on bugreports.qt.nokia.com
 // The following lines implement conversin for uchar and avoid the problems. 
 
-template <typename T> T qbswap(T source);
-template <> inline uchar qbswap<uchar>(uchar source)
-{
-   return source;
-}
+#if (QT_VERSION < 0x040800)
+   template <typename T> T qbswap(T source);
+   template <> inline uchar qbswap<uchar>(uchar source)
+   {
+      return source;
+   }
+#endif
 
 // ------------------
 //  AEWF definitions
diff --git a/common.h b/common.h
index e596541..6c87503 100644
--- a/common.h
+++ b/common.h
@@ -9,7 +9,7 @@
 //  Module:         Standard include file
 // ****************************************************************************
 
-// Copyright 2008, 2009, 2010, 2011 Guy Voncken
+// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 //
 // This file is part of guymager.
 //
@@ -34,8 +34,8 @@
 #ifndef __COMMON_H__
 #define __COMMON_H__
 
-#define USE_MD5_FROM_OPENSSL
-#define USE_SHA256_FROM_OPENSSL
+//#define USE_MD5_FROM_OPENSSL
+//#define USE_SHA256_FROM_OPENSSL
 
 // GNU C lib definitions
 // ---------------------
diff --git a/config.cpp b/config.cpp
index 6774dad..4297a65 100644
--- a/config.cpp
+++ b/config.cpp
@@ -9,7 +9,7 @@
 //  Module:         Application configuration data
 // ****************************************************************************
 
-// Copyright 2008, 2009, 2010, 2011 Guy Voncken
+// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 //
 // This file is part of guymager.
 //
@@ -29,7 +29,7 @@
 #include "common.h"
 
 #include <limits.h>
-#include "proc/sysinfo.h"  // Required in order to get smp_num_cpus for finding out the number of CPUs in the system
+//#include "proc/sysinfo.h"  // Required in order to get smp_num_cpus for finding out the number of CPUs in the system
 
 #include <qcolor.h>
 #include <qfont.h>
@@ -41,6 +41,7 @@
 #include "file.h"
 
 #include "qtutil.h"
+#include "util.h"
 #include "config.h"
 
 // ------------------------------------
@@ -58,7 +59,7 @@ static const char * CFG_SECTION_GUYMAGER = "GUYMAGER";
 
 static const unsigned char CONFIG_DUMMY_FILL = 0xAA;
 
-static const int CFG_MAX_COMPRESSIONTHREADS = 16;
+static const uint CFG_MAX_COMPRESSIONTHREADS = 16;
 
 // ------------------------------------
 //          Type definitions
@@ -345,6 +346,7 @@ static t_ToolCfgParamDesc CfgParamDescArr[] =
    {CFGASSIGN_BOTH_MULTIPLE, NULL       , {"ScanInterval"                  , CFGTYPE_INTEGER, ELT(ScanInterval                  ),                0,       1, 8640000, NULL                            }, CFG_FILLUP_FORLINT},
    {CFGASSIGN_BOTH_MULTIPLE, NULL       , {"CommandGetSerialNumber"        , CFGTYPE_STRING , ELT_SIZ(CommandGetSerialNumber    ),                         0,       0, NULL                            }, CFG_FILLUP_FORLINT},
    {CFGASSIGN_BOTH_MULTIPLE, NULL       , {"CommandGetAddStateInfo"        , CFGTYPE_STRING , ELT_SIZ(CommandGetAddStateInfo    ),                         0,       0, NULL                            }, CFG_FILLUP_FORLINT},
+   {CFGASSIGN_BOTH_MULTIPLE, NULL       , {"QueryDeviceMediaInfo"          , CFGTYPE_SET    , ELT(QueryDeviceMediaInfo          ),                0,       0,       0, INIARR(SetArrBoolean)           }, CFG_FILLUP_FORLINT},
    {CFGASSIGN_BOTH_MULTIPLE, NULL       , {"DirectIO"                      , CFGTYPE_SET    , ELT(DirectIO                      ),                0,       0,       0, INIARR(SetArrBoolean)           }, CFG_FILLUP_FORLINT},
    {CFGASSIGN_BOTH_MULTIPLE, NULL       , {"FifoBlockSizeDD"               , CFGTYPE_INTEGER, ELT(FifoBlockSizeDD               ),                0,       0,99999999, NULL                            }, CFG_FILLUP_FORLINT},
    {CFGASSIGN_BOTH_MULTIPLE, NULL       , {"FifoBlockSizeEWF"              , CFGTYPE_INTEGER, ELT(FifoBlockSizeEWF              ),                0,       0,99999999, NULL                            }, CFG_FILLUP_FORLINT},
@@ -594,16 +596,19 @@ APIRET CfgIniLang (t_pToolCfgParamDesc pCfgParamDesc, t_pchar *ppErrorText)
 
 APIRET CfgIniCPUs (t_pToolCfgParamDesc pCfgParamDesc, t_pchar *ppErrorText)
 {
-   t_pcchar pParamName;
+   t_pcchar     pParamName;
+   unsigned int  CPUs;
 
    *ppErrorText = NULL;
    pParamName = pCfgParamDesc->DataDesc.pName;
 
    if (CONFIG (CompressionThreads) == CONFIG_COMPRESSIONTHREADS_AUTO)
    {
-      LOG_INFO ("Parameter %s set to AUTO; %ld CPUs detected", pParamName, smp_num_cpus)
-      CONFIG (CompressionThreads) = smp_num_cpus;
-      if (smp_num_cpus > CFG_MAX_COMPRESSIONTHREADS)
+//      CPUs = smp_num_cpus;
+      CPUs = UtilGetNumberOfCPUs();
+      LOG_INFO ("Parameter %s set to AUTO; %u CPUs detected", pParamName, CPUs)
+      CONFIG (CompressionThreads) = CPUs;
+      if (CPUs > CFG_MAX_COMPRESSIONTHREADS)
       {
          CONFIG (CompressionThreads) = CFG_MAX_COMPRESSIONTHREADS;
          LOG_INFO ("Maximum value for %s is %d", pParamName, CFG_MAX_COMPRESSIONTHREADS)
@@ -616,17 +621,22 @@ APIRET CfgIniCPUs (t_pToolCfgParamDesc pCfgParamDesc, t_pchar *ppErrorText)
 
 APIRET CfgIniMem (t_pToolCfgParamDesc pCfgParamDesc, t_pchar *ppErrorText)
 {
-   t_pcchar pParamName;
+   t_pcchar           pParamName;
+   unsigned long long  Bytes;
 
    *ppErrorText = NULL;
    pParamName = pCfgParamDesc->DataDesc.pName;
 
-   meminfo();
+//   meminfo();
+//   Bytes = kb_main_total * 1024;
+
+   Bytes = UtilGetInstalledRAM ();
+
    if (CONFIG (FifoMaxMem) == 0)
    {
-      CONFIG (FifoMaxMem) = GETMAX (1, (int)(kb_main_total / (8*1024)));   // Use one eighth of the available mem, convert KB to MB
-      CONFIG (FifoMaxMem) = GETMIN (CONFIG (FifoMaxMem), 64);              // Stay below 64MB
-      LOG_INFO ("Parameter %s set to 0 (auto); %lu MB of RAM detected.", pParamName, kb_main_total/1024)
+      CONFIG (FifoMaxMem) = GETMAX (1, (int)(Bytes / (8*1024*1024)));   // Use one eighth of the available mem, convert to MB
+      CONFIG (FifoMaxMem) = GETMIN (CONFIG (FifoMaxMem), 64);       // Stay below 64MB
+      LOG_INFO ("Parameter %s set to 0 (auto); %0.1f MB of RAM detected.", pParamName, Bytes/(1024.0*1024.0));
       LOG_INFO ("Setting %s to %d (i.e. using %d MB per acquisition as FIFO memory)", pParamName, CONFIG (FifoMaxMem), CONFIG (FifoMaxMem))
    }
 
diff --git a/config.h b/config.h
index 15c5365..c883212 100644
--- a/config.h
+++ b/config.h
@@ -7,7 +7,7 @@
 //                  Section Nouvelles Technologies
 // ****************************************************************************
 
-// Copyright 2008, 2009, 2010, 2011 Guy Voncken
+// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 //
 // This file is part of guymager.
 //
@@ -134,6 +134,7 @@ typedef struct
    int                  ScanInterval;
    char                 CommandGetSerialNumber[CFG_MAX_PATH_LEN+1];
    char                 CommandGetAddStateInfo[CFG_MAX_PATH_LEN+1];
+   int                  QueryDeviceMediaInfo;
    int                  DirectIO;
 
    int                  DefaultFormat;
diff --git a/dlgacquire_private.h b/dlgacquire_private.h
old mode 100755
new mode 100644
diff --git a/guymager.cfg b/guymager.cfg
index 2f27232..87dfc95 100644
--- a/guymager.cfg
+++ b/guymager.cfg
@@ -441,10 +441,9 @@ REM                         (/dev/hda or /dev/sdc for instance). Examples:
 REM                            CommandGetSerialNumber = 'bash -c "smartctl -i %dev | grep -i serial | awk ''{print $3 $4 $5 $6 $7 $8 $9}'' "'
 REM                            CommandGetSerialNumber = 'bash -c "hdparm -I %dev | grep -i ''Serial Number'' | awk ''{print $3 $4 $5 $6 $7 $8 $9}'' "'
 REM
-REM CommandGetAddStateInfo  contains the command to be executed in order to gather additional state information. See 
-REM                         CommandGetSerialNumber in order to see how to use the %dev placeholder. By default, the command is 
-REM                         empty and no additional information is read nor displayed. If set, the command executed is expected 
-REM                         to return its information in three separate lines (separated by \n):
+REM CommandGetAddStateInfo  contains the command to be executed in order to gather additional state information. By default, CommandGetAddStateInfo
+REM                         simply is an empty string and no additional information is read nor displayed. If set, the command executed
+REM                         is expected to return its information in three separate lines (separated by \n):
 REM                            1st line: Information text. This text is displayed in the device specific screen area of Guymager 
 REM                                      (bottom area of the main window).
 REM                            2nd line: A value of 0 tells Guymager that the device cannot be acquired. Guymager forbids the
@@ -454,6 +453,10 @@ REM                            3rd line: An integer number indicating the color
 REM                                      refers to the colors named AdditionalStateX in the configuration table Colors (see 
 REM                                      above), where X corresponds to the color returned by the command. If this parameter 
 REM                                      is missing, the default color (wite) is used.
+REM                         The command may include the two placeholders %dev and %local which will be replaced accordingly. See
+REM                         the description of CommandGetSerialNumber above for the use of %dev. %local will be replaced by 1
+REM                         if the %dev refers to a local device and 0 otherwise.
+REM
 REM                         If you plan to use this feature, you may do a first test with the configuration setting
 REM                             CommandGetAddStateInfo='bash -c "/usr/share/guymager/stateinfo.sh %dev"'
 REM                         where the file /usr/share/guymager/stateinfo.sh is executable and contains the lines
@@ -464,6 +467,11 @@ REM
 REM ScanInterval            Speficies how often an automatic device scan (for detecting newly connected devices)
 REM                         should launched. Unit: Seconds. Keep in mind, that the device scan can be launched as well manually.
 REM
+REM QueryDeviceMediaInfo    Guymager has the possibility to gather extended media info about the connected devices. The media info
+REM                         mainly includes HPA/DCO settings. Some non-standard devices do not expect the corresponding ATA
+REM                         commands and may even need to be resetted when trying to query media info. In such cases,
+REM                         QueryDeviceMediaInfo may be switched off. By default, it is on.
+REM
 REM DirectIO                Decides whether Guymager reads data in direct IO mode or not. Normally, direct mode should be a little
 REM                         faster, but it was observed that reading from SSDSs may be much slower in direct mode. The default
 REM                         setting therefore is "off".
@@ -473,6 +481,7 @@ DeviceScanMethod       = UDisks
 CommandGetSerialNumber = 'bash -c "smartctl -i %dev | grep -i serial | awk ''{print $3 $4 $5 $6 $7 $8 $9}'' "'
 CommandGetAddStateInfo = ''
 ScanInterval           = 6000
+QueryDeviceMediaInfo   = on
 DirectIO               = off
 
 REM Other settings
diff --git a/guymager.desktop b/guymager.desktop
index b9e2688..1520743 100644
--- a/guymager.desktop
+++ b/guymager.desktop
@@ -10,6 +10,7 @@ GenericName=Imager
 Comment=Fast forensic imager
 Icon=guymager_128.png
 TryExec=guymager
+#Exec=su-to-root -X -c guymager
 Exec=gksudo guymager
 Terminal=false
 # Categorie entry according to version 1.0 of
diff --git a/guymager.pro b/guymager.pro
index d4b9628..db83cf8 100644
--- a/guymager.pro
+++ b/guymager.pro
@@ -9,7 +9,7 @@
 #  Qt project file
 # ****************************************************************************
 
-# Copyright 2008, 2009, 2010, 2011 Guy Voncken
+# Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 #
 # This file is part of guymager.
 #
@@ -72,7 +72,6 @@ QMAKE_PRE_LINK += && $(CXX) -c $(CXXFLAGS) compileinfo.cpp
 DummyResult = $$system(echo DummyCompileInfoPunktO > compileinfo.o)
 OBJECTS += compileinfo.o
 
-
 SOURCES += aaff.cpp
 SOURCES += aewf.cpp
 SOURCES += config.cpp
@@ -92,10 +91,10 @@ SOURCES += infofield.cpp
 SOURCES += itemdelegate.cpp
 SOURCES += main.cpp
 SOURCES += mainwindow.cpp
-SOURCES += md5.c
+SOURCES += md5.cpp
 SOURCES += media.cpp
 SOURCES += qtutil.cpp
-#SOURCES += sha256.cpp
+SOURCES += sha256.cpp
 SOURCES += table.cpp
 SOURCES += thread.cpp
 SOURCES += threadcompress.cpp
@@ -135,40 +134,18 @@ QMAKE_CFLAGS_RELEASE   += -ggdb
 QMAKE_LFLAGS_DEBUG     += -ggdb -rdynamic    # -rdynamic is necessary in order to have the backtrace handler in toolsignal show all information
 QMAKE_LFLAGS_RELEASE   += -ggdb -rdynamic    # -rdynamic is necessary in order to have the backtrace handler in toolsignal show all information
 
-# -----------------------------------------------------------------------------------------------------------------
-# sha256.cpp, which contains part of manually optimised assembler code, runs faster when compiling with -O1 option.
-# As qmake does not allow to specify individual compiler options for files, we add an "extra compiler" statement
-# here in order to compile the file correctly. At the same time, grep removes out the silly "matching constraint"
-# warning spit out by g++.
-# The pipe to cat at the end of the compile gives us an exit code 0, as grep may return values <> 0 depending
-# whether there is an output or not. The disadvantage is, that compile errrors cannot be detected by make (Tests
-# have been made with the PIPESTATUS variable, but that didn't work).
-# -----------------------------------------------------------------------------------------------------------------
-FAST_ASM_FILES    = sha256.cpp
-FAST_ASM_CXXFLAGS = $$QMAKE_CXXFLAGS_RELEASE $$QMAKE_CXXFLAGS_WARN_ON
-FAST_ASM_CXXFLAGS -= -O0
-FAST_ASM_CXXFLAGS -= -O2
-FAST_ASM_CXXFLAGS -= -O3
-FAST_ASM_CXXFLAGS += -O1
-fastasm.name = Compile file containing inline assembler statements with -O1 option for faster code
-fastasm.input = FAST_ASM_FILES
-fastasm.output = ${QMAKE_FILE_BASE}.o
-fastasm.commands = g++ -c $$FAST_ASM_CXXFLAGS ${QMAKE_FILE_IN} -o  ${QMAKE_FILE_BASE}.o 2>&1 | grep -vE \"matching constraint does not allow a register|In function |At global scope:\"  | cat
-QMAKE_EXTRA_COMPILERS += fastasm
-
-LIBS += -lproc
 #LIBS += -lewf
 #LIBS += -lguytools
+#LIBS += /usr/local/lib/libewf.a
 LIBS += /usr/lib/libewf.a
 LIBS += /usr/lib/libguytools.a
 LIBS += -lz
 LIBS += -ldl
 
-#xou may use any of the 3 following line for the libssl hash functions
-#LIBS += -lssl  # See also macro definitions in common.h
+# You may use any of the 3 following lines for the libssl hash functions
+#LIBS += -lssl     # See also macro definitions in common.h
 #LIBS += -lcrypto  # See also macro definitions in common.h
-LIBS += /usr/lib/libcrypto.a
-
+#LIBS += /usr/lib/libcrypto.a
 
 TRANSLATIONS  = guymager_en.ts
 TRANSLATIONS += guymager_de.ts
diff --git a/guymager_128.xpm b/guymager_128.xpm
new file mode 100644
index 0000000..0106e20
--- /dev/null
+++ b/guymager_128.xpm
@@ -0,0 +1,399 @@
+/* XPM */
+static char * guymager_128_xpm[] = {
+"32 32 364 2",
+"  	c None",
+". 	c #BBBBBB",
+"+ 	c #B2B2B2",
+"@ 	c #A7A7A7",
+"# 	c #C1C1C1",
+"$ 	c #B4B4B4",
+"% 	c #BEBEBE",
+"& 	c #C3C3C3",
+"* 	c #252525",
+"= 	c #DADAD9",
+"- 	c #E0E0DE",
+"; 	c #C2C2C2",
+"> 	c #C5C5C5",
+", 	c #D1D1D1",
+"' 	c #B6B6B6",
+") 	c #B8B8B8",
+"! 	c #DAD3D9",
+"~ 	c #D9D7D9",
+"{ 	c #505050",
+"] 	c #49494A",
+"^ 	c #313231",
+"/ 	c #D3D3D3",
+"( 	c #E3E3E2",
+"_ 	c #C9C9C9",
+": 	c #C9C9CA",
+"< 	c #DCDCDC",
+"[ 	c #D6D6D6",
+"} 	c #C6C6C6",
+"| 	c #D2D2D2",
+"1 	c #D3D4D4",
+"2 	c #C9C6D5",
+"3 	c #E1D4DF",
+"4 	c #DFDEE0",
+"5 	c #E1DFE1",
+"6 	c #E2E1E2",
+"7 	c #6B6C6B",
+"8 	c #4B4B4B",
+"9 	c #4D4D4D",
+"0 	c #797B79",
+"a 	c #ADADAE",
+"b 	c #A9A9A9",
+"c 	c #D0D0D0",
+"d 	c #E2E2E2",
+"e 	c #D4D4D4",
+"f 	c #D9D9D9",
+"g 	c #CACACA",
+"h 	c #C3C3CB",
+"i 	c #E2D4E2",
+"j 	c #E1E0E0",
+"k 	c #E2E0E2",
+"l 	c #E3E2E3",
+"m 	c #E8E8E8",
+"n 	c #5D5E5E",
+"o 	c #484949",
+"p 	c #C6C8C8",
+"q 	c #CBCACE",
+"r 	c #98999A",
+"s 	c #7D7E7D",
+"t 	c #AFAFAF",
+"u 	c #DBDBDB",
+"v 	c #D7D7D7",
+"w 	c #CECECE",
+"x 	c #D8D8D8",
+"y 	c #D1CAD5",
+"z 	c #DFDEDF",
+"A 	c #E4E3E4",
+"B 	c #E4E4E4",
+"C 	c #C8C8C8",
+"D 	c #383938",
+"E 	c #8F9090",
+"F 	c #C8C8CB",
+"G 	c #373736",
+"H 	c #6B6C6C",
+"I 	c #676867",
+"J 	c #BDBDBD",
+"K 	c #DFDFDF",
+"L 	c #DADADA",
+"M 	c #C4C4C4",
+"N 	c #CDCECD",
+"O 	c #DEDEDE",
+"P 	c #E6E6E6",
+"Q 	c #6D6E6D",
+"R 	c #404140",
+"S 	c #828282",
+"T 	c #A5A6A7",
+"U 	c #292929",
+"V 	c #CFCFCF",
+"W 	c #D5D5D5",
+"X 	c #9F9F9F",
+"Y 	c #E1E1E1",
+"Z 	c #E3E4E2",
+"` 	c #FFFFFF",
+" .	c #484948",
+"..	c #1F1F1F",
+"+.	c #BABCBD",
+"@.	c #CFD1D2",
+"#.	c #DBDDDE",
+"$.	c #DADBDD",
+"%.	c #D3D5D6",
+"&.	c #CACBCD",
+"*.	c #C6C8C9",
+"=.	c #C4C7CA",
+"-.	c #C7C9CA",
+";.	c #D5D6D8",
+">.	c #949698",
+",.	c #BEBFBF",
+"'.	c #E8DED9",
+").	c #DEDCDC",
+"!.	c #D8D8DA",
+"~.	c #EFF1F1",
+"{.	c #EFF2F0",
+"].	c #F6F8F8",
+"^.	c #292A2A",
+"/.	c #AF9075",
+"(.	c #AF9279",
+"_.	c #AF9177",
+":.	c #B2947A",
+"<.	c #B3957B",
+"[.	c #AE9075",
+"}.	c #A98B70",
+"|.	c #A5886F",
+"1.	c #A78B73",
+"2.	c #B19476",
+"3.	c #B09178",
+"4.	c #AC8E75",
+"5.	c #A58971",
+"6.	c #A38871",
+"7.	c #AD9174",
+"8.	c #A98B72",
+"9.	c #AE8D71",
+"0.	c #AE8E72",
+"a.	c #AC8A6E",
+"b.	c #B8977C",
+"c.	c #5D4E3E",
+"d.	c #BE9B7E",
+"e.	c #BF9D7F",
+"f.	c #BF9C7F",
+"g.	c #BE9C7F",
+"h.	c #C19D80",
+"i.	c #C49E82",
+"j.	c #C19C7F",
+"k.	c #BE9B7D",
+"l.	c #C29F81",
+"m.	c #B59375",
+"n.	c #BC9979",
+"o.	c #BB9777",
+"p.	c #C0987A",
+"q.	c #918B5F",
+"r.	c #4E7838",
+"s.	c #37722B",
+"t.	c #37712A",
+"u.	c #4A7736",
+"v.	c #8D8A5D",
+"w.	c #BF997A",
+"x.	c #BC9879",
+"y.	c #BB9878",
+"z.	c #C09C7C",
+"A.	c #AC896B",
+"B.	c #B99373",
+"C.	c #B89372",
+"D.	c #B89271",
+"E.	c #BD9473",
+"F.	c #58793C",
+"G.	c #07640E",
+"H.	c #0F6613",
+"I.	c #0A6410",
+"J.	c #0B6511",
+"K.	c #07630E",
+"L.	c #73804C",
+"M.	c #B99372",
+"N.	c #BD9775",
+"O.	c #A38061",
+"P.	c #B6906D",
+"Q.	c #B58E6B",
+"R.	c #B58F6B",
+"S.	c #908557",
+"T.	c #07640F",
+"U.	c #0E6512",
+"V.	c #386F28",
+"W.	c #8A8354",
+"X.	c #838150",
+"Y.	c #1E691B",
+"Z.	c #1E691A",
+"`.	c #3D702A",
+" +	c #BB8F6D",
+".+	c #B68E6B",
+"++	c #B68F6D",
+"@+	c #B9926F",
+"#+	c #9E7E61",
+"$+	c #B38B67",
+"%+	c #B48B67",
+"&+	c #B38A66",
+"*+	c #B58A67",
+"=+	c #4C7331",
+"-+	c #116614",
+";+	c #BA8A68",
+">+	c #B48965",
+",+	c #BC8B69",
+"'+	c #C58D6F",
+")+	c #C28C6D",
+"!+	c #B18864",
+"~+	c #B28864",
+"{+	c #B28965",
+"]+	c #B89371",
+"^+	c #967659",
+"/+	c #B08560",
+"(+	c #AF855F",
+"_+	c #B0855F",
+":+	c #B08661",
+"<+	c #B38460",
+"[+	c #336C23",
+"}+	c #306C22",
+"|+	c #B58561",
+"1+	c #8A7D4C",
+"2+	c #00620B",
+"3+	c #04630D",
+"4+	c #006108",
+"5+	c #BA8763",
+"6+	c #B0845E",
+"7+	c #B08660",
+"8+	c #B18661",
+"9+	c #B08A69",
+"0+	c #8F6F52",
+"a+	c #AD815A",
+"b+	c #AE815A",
+"c+	c #AD8159",
+"d+	c #B07F59",
+"e+	c #3A6C25",
+"f+	c #26691D",
+"g+	c #B4825D",
+"h+	c #897A49",
+"i+	c #00630C",
+"j+	c #0A6510",
+"k+	c #05640E",
+"l+	c #B6815C",
+"m+	c #AC7F58",
+"n+	c #A78160",
+"o+	c #8B6B4F",
+"p+	c #AA7C53",
+"q+	c #AA7C54",
+"r+	c #AB7D54",
+"s+	c #AA7B52",
+"t+	c #5F7033",
+"u+	c #096510",
+"v+	c #94784A",
+"w+	c #B27E57",
+"x+	c #BD7F5C",
+"y+	c #587031",
+"z+	c #05640F",
+"A+	c #B47D56",
+"B+	c #AA7B53",
+"C+	c #AA7C52",
+"D+	c #A97B52",
+"E+	c #9F7958",
+"F+	c #876649",
+"G+	c #A8784E",
+"H+	c #A8774D",
+"I+	c #A7784E",
+"J+	c #A5774D",
+"K+	c #106613",
+"L+	c #2D691E",
+"M+	c #1C6718",
+"N+	c #0A6511",
+"O+	c #04640F",
+"P+	c #B17951",
+"Q+	c #A8794E",
+"R+	c #977150",
+"S+	c #816043",
+"T+	c #A57449",
+"U+	c #A47449",
+"V+	c #A47349",
+"W+	c #907141",
+"X+	c #216719",
+"Y+	c #076510",
+"Z+	c #096511",
+"`+	c #386921",
+" @	c #977244",
+".@	c #A67549",
+"+@	c #A67449",
+"@@	c #8E6849",
+"#@	c #78593E",
+"$@	c #A07146",
+"%@	c #9E6F46",
+"&@	c #9E6F45",
+"*@	c #A46F48",
+"=@	c #926E41",
+"-@	c #806D3B",
+";@	c #846D3C",
+">@	c #9F7046",
+",@	c #A26F47",
+"'@	c #9F7147",
+")@	c #9E7046",
+"!@	c #856244",
+"~@	c #644831",
+"{@	c #8D6139",
+"]@	c #91643C",
+"^@	c #95683F",
+"/@	c #986A41",
+"(@	c #9B6C43",
+"_@	c #9C6D45",
+":@	c #9D6F45",
+"<@	c #9E6E45",
+"[@	c #A17147",
+"}@	c #A07047",
+"|@	c #A17248",
+"1@	c #A07046",
+"2@	c #92643D",
+"3@	c #8D613A",
+"4@	c #73553A",
+"5@	c #694A2F",
+"6@	c #906239",
+"7@	c #95673D",
+"8@	c #9C6D42",
+"9@	c #A16F46",
+"0@	c #A27147",
+"a@	c #A37349",
+"b@	c #A37348",
+"c@	c #A37248",
+"d@	c #A47348",
+"e@	c #9C6C42",
+"f@	c #91633B",
+"g@	c #785639",
+"h@	c #7D5839",
+"i@	c #A17045",
+"j@	c #A27248",
+"k@	c #A6754A",
+"l@	c #926A47",
+"m@	c #886240",
+"n@	c #A7754A",
+"o@	c #A6764A",
+"p@	c #A47549",
+"q@	c #A27347",
+"r@	c #A17047",
+"s@	c #A07147",
+"t@	c #A27247",
+"u@	c #AB784C",
+"v@	c #AA794D",
+"w@	c #A37750",
+"x@	c #986D47",
+"y@	c #AC7A4D",
+"z@	c #AD7A4E",
+"A@	c #AB794D",
+"B@	c #A7774B",
+"C@	c #A47448",
+"D@	c #A8774B",
+"E@	c #A9774C",
+"F@	c #A7764A",
+"G@	c #A6754B",
+"H@	c #AA784C",
+"I@	c #AE7B4E",
+"J@	c #B28257",
+"K@	c #AA7A4F",
+"L@	c #B47F51",
+"M@	c #B48052",
+"N@	c #B37F52",
+"O@	c #B37F51",
+"P@	c #B38052",
+"Q@	c #B27F51",
+"R@	c #B38051",
+"S@	c #BC895C",
+"T@	c #976D47",
+"U@	c #966A44",
+"V@	c #9B714D",
+"W@	c #4E3722",
+"                                                                ",
+"                                                                ",
+"                    . + @                                       ",
+"                # . $ % &               *                       ",
+"            = - ; > , ' , )   ! ~       { ] ^                   ",
+"        / ( _ : < > [ } | 1 2 3 4 5 6 7 8 9 0 a                 ",
+"      b ' # c / d e f < g } h i j k l m n o p q r s             ",
+"        t , e m / < u u v w x y z A B d C D E F G H I           ",
+"        > J d K u L f x x v M N   [ d O u P Q R S T U           ",
+"          V d W f x x | / / ; ,   X Y u x Z ` W  .U ..          ",
+"          +. at .#.$.%. at .&.*.=.-.;.>.,.'.).!.~.{.].` ^.            ",
+"          /.(._.:.<.[.}.|.1.2.2.3.4.5.6.7.8.9.0.a.b.c.          ",
+"          d.e.e.e.e.f.f.f.g.h.i.i.j.k.k.k.k.k.f.e.l.            ",
+"          m.n.n.n.n.n.o.p.q.r.s.t.u.v.w.x.y.o.x.n.z.            ",
+"          A.B.B.B.C.D.E.F.G.H.I.J.H.K.L.M.D.D.B.B.N.            ",
+"          O.P.P.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+++++P. at +            ",
+"          #+$+%+%+&+*+=+H.-+;+>+,+'+'+)+!+~+{+%+$+]+            ",
+"          ^+/+(+_+:+<+[+H.}+|+1+2+3+3+4+5+6+7+:+8+9+            ",
+"          0+a+b+c+b+d+e+H.f+g+h+i+j+H.k+l+m+m+m+a+n+            ",
+"          o+p+q+q+r+s+t+U.u+v+w+x+y+H.z+A+B+C+D+q+E+            ",
+"          F+G+G+G+H+I+J+K+H.J.L+M+N+H.O+P+G+I+I+Q+R+            ",
+"          S+T+U+U+U+U+V+W+X+Y+N+Z+Y+`+ @. at V+T+.@+@@@            ",
+"          #@$@%@%@&@%@%@&@*@=@-@;@>@,@&@'@&@)@'@>@!@            ",
+"          ~@{@]@^@/@(@_@:@)@%@<@[@[@[@}@|@|@1 at 2@3 at 4@            ",
+"          5 at 6@7 at 8@9 at 0@a at b@b at c@c at b@b at c@d at V+U+a@e at f@g@            ",
+"          h at i@0 at b@b at c@b at a@b at j@j at c@b at j@c at b@a at a@k at +@l@            ",
+"          m at n@k at o@p at q@r@$@1 at 1@$@s@>@>@1 at 1@t at T+u@v at w@            ",
+"          x at y@z at A@B at k@C at d@k at D@D at D@E at E@D at F@G at H@I at I@J@            ",
+"          K at L@M at M@N at O@P at O@Q at O@M at O@M at M@R at Q@O at P@M at L@S@            ",
+"          T at U@U at U@U at U@U at U@U at U@U at U@U at U@U at U@U at U@U at U@V at W@          ",
+"                                                                ",
+"                                                                "};
diff --git a/hash.cpp b/hash.cpp
index b9fcfad..de65159 100644
--- a/hash.cpp
+++ b/hash.cpp
@@ -9,7 +9,7 @@
 //  Module:         Hash wrapper functions for uniform hash interface
 // ****************************************************************************
 
-// Copyright 2008, 2009, 2010, 2011 Guy Voncken
+// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 //
 // This file is part of guymager.
 //
@@ -54,7 +54,7 @@ APIRET HashMD5Init (t_pHashContextMD5 pContext)
    #ifdef USE_MD5_FROM_OPENSSL
       (void) MD5_Init (pContext);    // strange, man page says that MD5_Init returns void, but header file says it's int
    #else
-      md5_init (pContext);
+      MD5Init (pContext);
    #endif
 
    return NO_ERROR;
@@ -65,7 +65,7 @@ APIRET HashMD5Append (t_pHashContextMD5 pContext, const void *pData, int DataLen
    #ifdef USE_MD5_FROM_OPENSSL
       (void) MD5_Update (pContext, pData, (unsigned long) DataLen); // Same remark as for MD5_Init
    #else
-      md5_append (pContext, (md5_byte_t *)pData, DataLen);
+      MD5Append (pContext, pData, DataLen);
    #endif
 
    return NO_ERROR;
@@ -76,7 +76,7 @@ APIRET HashMD5Digest (t_pHashContextMD5 pContext, t_pHashMD5Digest pDigest)
    #ifdef USE_MD5_FROM_OPENSSL
       (void) MD5_Final (&pDigest->Buff[0], pContext); // Same remark as for MD5_Init
    #else
-      md5_finish (pContext, (md5_byte_t *)&pDigest->Buff[0]);
+      MD5Finish (pContext, &pDigest->Buff[0]);
    #endif
 
    return NO_ERROR;
@@ -110,7 +110,7 @@ APIRET HashSHA256Init (t_pHashContextSHA256 pContext)
    #ifdef USE_SHA256_FROM_OPENSSL
       (void) SHA256_Init (pContext);
    #else
-      sha256_starts (pContext);
+      SHA256Init (pContext);
    #endif
    return NO_ERROR;
 }
@@ -120,7 +120,7 @@ APIRET HashSHA256Append (t_pHashContextSHA256 pContext, void *pData, int DataLen
    #ifdef USE_SHA256_FROM_OPENSSL
       (void) SHA256_Update (pContext, pData, (unsigned long) DataLen);
    #else
-      sha256_update (pContext, (unsigned char *)pData, DataLen);
+      SHA256Append (pContext, (unsigned char *)pData, DataLen);
    #endif
    return NO_ERROR;
 }
@@ -130,7 +130,7 @@ APIRET HashSHA256Digest (t_pHashContextSHA256 pContext, t_pHashSHA256Digest pDig
    #ifdef USE_SHA256_FROM_OPENSSL
       (void) SHA256_Final (&pDigest->Buff[0], pContext);
    #else
-      sha256_finish (pContext, (unsigned char *)pDigest);
+      SHA256Finish (pContext, (unsigned char *)pDigest);
    #endif
    return NO_ERROR;
 }
diff --git a/hash.h b/hash.h
index 077ace1..1a68316 100644
--- a/hash.h
+++ b/hash.h
@@ -9,7 +9,7 @@
 //  Module:         Hash wrapper functions for uniform hash interface
 // ****************************************************************************
 
-// Copyright 2008, 2009, 2010, 2011 Guy Voncken
+// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 //
 // This file is part of guymager.
 //
@@ -38,7 +38,7 @@
    typedef MD5_CTX t_HashContextMD5;
 #else
    #include "md5.h"
-   typedef md5_state_t t_HashContextMD5;
+   typedef t_MD5Context t_HashContextMD5;
 #endif
 
 #ifdef USE_SHA256_FROM_OPENSSL
@@ -46,7 +46,7 @@
    typedef SHA256_CTX t_HashContextSHA256;
 #else
    #include "sha256.h"
-   typedef sha256_context  t_HashContextSHA256;
+   typedef t_SHA256Context  t_HashContextSHA256;
 #endif
 
 typedef t_HashContextMD5    *t_pHashContextMD5;
diff --git a/main.cpp b/main.cpp
index 0d122c0..31d80cb 100644
--- a/main.cpp
+++ b/main.cpp
@@ -33,7 +33,7 @@
 #include <signal.h>
 #include <locale.h>
 #include <pwd.h>
-#include "proc/sysinfo.h"  // Required in order to get the amount of memory installed
+// #include "proc/sysinfo.h"  // Required in order to get the amount of memory installed
 
 #include <QApplication>
 #include <QtGui>
@@ -274,8 +274,10 @@ static APIRET MainGo (int argc, char *argv[], bool *pAutoExit)
    pLibEwfVersionInstalled = (const char *) libewf_get_version();
    LOG_INFO ("Libguytools version installed on this PC: %s", pLibGuyToolsVersionInstalled)
    LOG_INFO ("Libewf      version installed on this PC: %s", pLibEwfVersionInstalled)
-   meminfo();
-   LOG_INFO ("Total amount of memory installed: %lu KB", kb_main_total)
+
+
+   unsigned long long Bytes = UtilGetInstalledRAM ();
+   LOG_INFO ("Total amount of memory installed: %0.1f MB", Bytes/(1024.0*1024.0))
    
 //   pLibEwfVersionCompiled = LIBEWF_VERSION_STRING;
 //
diff --git a/md5.c b/md5.c
deleted file mode 100644
index 1c9606e..0000000
--- a/md5.c
+++ /dev/null
@@ -1,398 +0,0 @@
-// This file has been copied 1:1 from the source of the Debian fdupes package into Guymager.
-// Only have been added this comment and the following include, no other changes.
-
-#include <string.h>
-
-
-/*
-  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost at aladdin.com
-
- */
-/*$Id: md5.c $ */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321.
-  It is derived directly from the text of the RFC and not from the
-  reference implementation.
-
-  The original and principal author of md5.c is L. Peter Deutsch
-  <ghost at aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
-  1999-05-03 lpd Original version.
- */
-
-#include "md5.h"
-
-#ifdef TEST
-/*
- * Compile with -DTEST to create a self-contained executable test program.
- * The test program should print out the same values as given in section
- * A.5 of RFC 1321, reproduced below.
- */
-#include <string.h>
-main()
-{
-    static const char *const test[7] = {
-	"", /*d41d8cd98f00b204e9800998ecf8427e*/
-	"a", /*0cc175b9c0f1b6a831c399e269772661*/
-	"abc", /*900150983cd24fb0d6963f7d28e17f72*/
-	"message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/
-	"abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
-				/*d174ab98d277d9f5a5611c2c9f419d9f*/
-	"12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/
-    };
-    int i;
-
-    for (i = 0; i < 7; ++i) {
-	md5_state_t state;
-	md5_byte_t digest[16];
-	int di;
-
-	md5_init(&state);
-	md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
-	md5_finish(&state, digest);
-	printf("MD5 (\"%s\") = ", test[i]);
-	for (di = 0; di < 16; ++di)
-	    printf("%02x", digest[di]);
-	printf("\n");
-    }
-    return 0;
-}
-#endif /* TEST */
-
-
-/*
- * For reference, here is the program that computed the T values.
- */
-#if 0
-#include <math.h>
-main()
-{
-    int i;
-    for (i = 1; i <= 64; ++i) {
-	unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
-	printf("#define T%d 0x%08lx\n", i, v);
-    }
-    return 0;
-}
-#endif
-/*
- * End of T computation program.
- */
-#define T1 0xd76aa478
-#define T2 0xe8c7b756
-#define T3 0x242070db
-#define T4 0xc1bdceee
-#define T5 0xf57c0faf
-#define T6 0x4787c62a
-#define T7 0xa8304613
-#define T8 0xfd469501
-#define T9 0x698098d8
-#define T10 0x8b44f7af
-#define T11 0xffff5bb1
-#define T12 0x895cd7be
-#define T13 0x6b901122
-#define T14 0xfd987193
-#define T15 0xa679438e
-#define T16 0x49b40821
-#define T17 0xf61e2562
-#define T18 0xc040b340
-#define T19 0x265e5a51
-#define T20 0xe9b6c7aa
-#define T21 0xd62f105d
-#define T22 0x02441453
-#define T23 0xd8a1e681
-#define T24 0xe7d3fbc8
-#define T25 0x21e1cde6
-#define T26 0xc33707d6
-#define T27 0xf4d50d87
-#define T28 0x455a14ed
-#define T29 0xa9e3e905
-#define T30 0xfcefa3f8
-#define T31 0x676f02d9
-#define T32 0x8d2a4c8a
-#define T33 0xfffa3942
-#define T34 0x8771f681
-#define T35 0x6d9d6122
-#define T36 0xfde5380c
-#define T37 0xa4beea44
-#define T38 0x4bdecfa9
-#define T39 0xf6bb4b60
-#define T40 0xbebfbc70
-#define T41 0x289b7ec6
-#define T42 0xeaa127fa
-#define T43 0xd4ef3085
-#define T44 0x04881d05
-#define T45 0xd9d4d039
-#define T46 0xe6db99e5
-#define T47 0x1fa27cf8
-#define T48 0xc4ac5665
-#define T49 0xf4292244
-#define T50 0x432aff97
-#define T51 0xab9423a7
-#define T52 0xfc93a039
-#define T53 0x655b59c3
-#define T54 0x8f0ccc92
-#define T55 0xffeff47d
-#define T56 0x85845dd1
-#define T57 0x6fa87e4f
-#define T58 0xfe2ce6e0
-#define T59 0xa3014314
-#define T60 0x4e0811a1
-#define T61 0xf7537e82
-#define T62 0xbd3af235
-#define T63 0x2ad7d2bb
-#define T64 0xeb86d391
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
-    md5_word_t
-	a = pms->abcd[0], b = pms->abcd[1],
-	c = pms->abcd[2], d = pms->abcd[3];
-    md5_word_t t;
-
-#ifndef ARCH_IS_BIG_ENDIAN
-# define ARCH_IS_BIG_ENDIAN 1	/* slower, default implementation */
-#endif
-#if ARCH_IS_BIG_ENDIAN
-
-    /*
-     * On big-endian machines, we must arrange the bytes in the right
-     * order.  (This also works on machines of unknown byte order.)
-     */
-    md5_word_t X[16];
-    const md5_byte_t *xp = data;
-    int i;
-
-    for (i = 0; i < 16; ++i, xp += 4)
-	X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
-
-#else  /* !ARCH_IS_BIG_ENDIAN */
-
-    /*
-     * On little-endian machines, we can process properly aligned data
-     * without copying it.
-     */
-    md5_word_t xbuf[16];
-    const md5_word_t *X;
-
-    if (!((data - (const md5_byte_t *)0) & 3)) {
-	/* data are properly aligned */
-	X = (const md5_word_t *)data;
-    } else {
-	/* not aligned */
-	memcpy(xbuf, data, 64);
-	X = xbuf;
-    }
-#endif
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
-    /* Round 1. */
-    /* Let [abcd k s i] denote the operation
-       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + F(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  7,  T1);
-    SET(d, a, b, c,  1, 12,  T2);
-    SET(c, d, a, b,  2, 17,  T3);
-    SET(b, c, d, a,  3, 22,  T4);
-    SET(a, b, c, d,  4,  7,  T5);
-    SET(d, a, b, c,  5, 12,  T6);
-    SET(c, d, a, b,  6, 17,  T7);
-    SET(b, c, d, a,  7, 22,  T8);
-    SET(a, b, c, d,  8,  7,  T9);
-    SET(d, a, b, c,  9, 12, T10);
-    SET(c, d, a, b, 10, 17, T11);
-    SET(b, c, d, a, 11, 22, T12);
-    SET(a, b, c, d, 12,  7, T13);
-    SET(d, a, b, c, 13, 12, T14);
-    SET(c, d, a, b, 14, 17, T15);
-    SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
-     /* Round 2. */
-     /* Let [abcd k s i] denote the operation
-          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + G(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  1,  5, T17);
-    SET(d, a, b, c,  6,  9, T18);
-    SET(c, d, a, b, 11, 14, T19);
-    SET(b, c, d, a,  0, 20, T20);
-    SET(a, b, c, d,  5,  5, T21);
-    SET(d, a, b, c, 10,  9, T22);
-    SET(c, d, a, b, 15, 14, T23);
-    SET(b, c, d, a,  4, 20, T24);
-    SET(a, b, c, d,  9,  5, T25);
-    SET(d, a, b, c, 14,  9, T26);
-    SET(c, d, a, b,  3, 14, T27);
-    SET(b, c, d, a,  8, 20, T28);
-    SET(a, b, c, d, 13,  5, T29);
-    SET(d, a, b, c,  2,  9, T30);
-    SET(c, d, a, b,  7, 14, T31);
-    SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
-     /* Round 3. */
-     /* Let [abcd k s t] denote the operation
-          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + H(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  5,  4, T33);
-    SET(d, a, b, c,  8, 11, T34);
-    SET(c, d, a, b, 11, 16, T35);
-    SET(b, c, d, a, 14, 23, T36);
-    SET(a, b, c, d,  1,  4, T37);
-    SET(d, a, b, c,  4, 11, T38);
-    SET(c, d, a, b,  7, 16, T39);
-    SET(b, c, d, a, 10, 23, T40);
-    SET(a, b, c, d, 13,  4, T41);
-    SET(d, a, b, c,  0, 11, T42);
-    SET(c, d, a, b,  3, 16, T43);
-    SET(b, c, d, a,  6, 23, T44);
-    SET(a, b, c, d,  9,  4, T45);
-    SET(d, a, b, c, 12, 11, T46);
-    SET(c, d, a, b, 15, 16, T47);
-    SET(b, c, d, a,  2, 23, T48);
-#undef SET
-
-     /* Round 4. */
-     /* Let [abcd k s t] denote the operation
-          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + I(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  6, T49);
-    SET(d, a, b, c,  7, 10, T50);
-    SET(c, d, a, b, 14, 15, T51);
-    SET(b, c, d, a,  5, 21, T52);
-    SET(a, b, c, d, 12,  6, T53);
-    SET(d, a, b, c,  3, 10, T54);
-    SET(c, d, a, b, 10, 15, T55);
-    SET(b, c, d, a,  1, 21, T56);
-    SET(a, b, c, d,  8,  6, T57);
-    SET(d, a, b, c, 15, 10, T58);
-    SET(c, d, a, b,  6, 15, T59);
-    SET(b, c, d, a, 13, 21, T60);
-    SET(a, b, c, d,  4,  6, T61);
-    SET(d, a, b, c, 11, 10, T62);
-    SET(c, d, a, b,  2, 15, T63);
-    SET(b, c, d, a,  9, 21, T64);
-#undef SET
-
-     /* Then perform the following additions. (That is increment each
-        of the four registers by the value it had before this block
-        was started.) */
-    pms->abcd[0] += a;
-    pms->abcd[1] += b;
-    pms->abcd[2] += c;
-    pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
-    pms->count[0] = pms->count[1] = 0;
-    pms->abcd[0] = 0x67452301;
-    pms->abcd[1] = 0xefcdab89;
-    pms->abcd[2] = 0x98badcfe;
-    pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
-    const md5_byte_t *p = data;
-    int left = nbytes;
-    int offset = (pms->count[0] >> 3) & 63;
-    md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
-    if (nbytes <= 0)
-	return;
-
-    /* Update the message length. */
-    pms->count[1] += nbytes >> 29;
-    pms->count[0] += nbits;
-    if (pms->count[0] < nbits)
-	pms->count[1]++;
-
-    /* Process an initial partial block. */
-    if (offset) {
-	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
-	memcpy(pms->buf + offset, p, copy);
-	if (offset + copy < 64)
-	    return;
-	p += copy;
-	left -= copy;
-	md5_process(pms, pms->buf);
-    }
-
-    /* Process full blocks. */
-    for (; left >= 64; p += 64, left -= 64)
-	md5_process(pms, p);
-
-    /* Process a final partial block. */
-    if (left)
-	memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
-    static const md5_byte_t pad[64] = {
-	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-    };
-    md5_byte_t data[8];
-    int i;
-
-    /* Save the length before padding. */
-    for (i = 0; i < 8; ++i)
-	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
-    /* Pad to 56 bytes mod 64. */
-    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
-    /* Append the length. */
-    md5_append(pms, data, 8);
-    for (i = 0; i < 16; ++i)
-	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
diff --git a/md5.cpp b/md5.cpp
new file mode 100644
index 0000000..5d71ac6
--- /dev/null
+++ b/md5.cpp
@@ -0,0 +1,512 @@
+// ****************************************************************************
+//  Project:        GUYMAGER
+// ****************************************************************************
+//  Programmer:     Guy Voncken
+//                  Police Grand-Ducale
+//                  Service de Police Judiciaire
+//                  Section Nouvelles Technologies
+// ****************************************************************************
+//  Module:         MD5 calculation
+// ****************************************************************************
+
+// Copyright 2008, 2009, 2010, 2011, 2012 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/>.
+
+// This module is based on the source code of standard Linux' md5sum command
+// (see Debian package coreutils, for example). The core functions have been
+// mainly copy/pasted; they have been written by David Madore and Scott G.
+// Miller and are copyrighted by the Free Software Foundation, Inc.
+
+
+#include <stddef.h>
+#include <string.h>
+
+#include "md5.h"
+
+// ----------------------
+//  Macros and constants
+// ----------------------
+
+static const unsigned char MD5PadBuf[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#ifdef WORDS_BIGENDIAN
+   #define SWAP(n)                                                        \
+      (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+   #define SWAP(n) (n)
+#endif
+
+// -----------
+//  Functions
+// -----------
+
+void MD5Init (t_MD5Context *pContext)
+{
+   pContext->A = 0x67452301;
+   pContext->B = 0xefcdab89;
+   pContext->C = 0x98badcfe;
+   pContext->D = 0x10325476;
+
+   pContext->total[0] = pContext->total[1] = 0;
+   pContext->buflen = 0;
+}
+
+static inline void set_uint32 (char *cp, uint32_t v)
+{
+   memcpy (cp, &v, sizeof v);
+}
+
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+static void MD5ProcessBlock (t_pMD5Context pContext, const void *buffer, size_t len) __attribute__((optimize("-O3")));
+static void MD5ProcessBlock (t_pMD5Context pContext, const void *buffer, size_t len)
+{
+   uint32_t        correct_words[16];
+   size_t          nwords = len / sizeof (uint32_t);
+   const uint32_t *words  = (uint32_t *)buffer;
+   const uint32_t *endp   = words + nwords;
+   uint32_t        A = pContext->A;
+   uint32_t        B = pContext->B;
+   uint32_t        C = pContext->C;
+   uint32_t        D = pContext->D;
+
+   // Increment byte count
+   pContext->total[0] += len;
+   if (pContext->total[0] < len)
+      ++pContext->total[1];
+
+   while (words < endp)
+   {
+      uint32_t *cwp = correct_words;
+      uint32_t A_save = A;
+      uint32_t B_save = B;
+      uint32_t C_save = C;
+      uint32_t D_save = D;
+
+      // We perhaps have to change the byte order before the computation.  To reduce the
+      // work for the next steps we store the swapped words in the array correct_words.
+
+      #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+      #define OP(a, b, c, d, s, T)                            \
+         do                                                   \
+         {                                                    \
+            a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
+            ++words;                                          \
+            CYCLIC (a, s);                                    \
+            a += b;                                           \
+         }                                                    \
+         while (0);
+
+      // Round 1
+      OP (A, B, C, D,  7, 0xd76aa478)
+      OP (D, A, B, C, 12, 0xe8c7b756)
+      OP (C, D, A, B, 17, 0x242070db)
+      OP (B, C, D, A, 22, 0xc1bdceee)
+      OP (A, B, C, D,  7, 0xf57c0faf)
+      OP (D, A, B, C, 12, 0x4787c62a)
+      OP (C, D, A, B, 17, 0xa8304613)
+      OP (B, C, D, A, 22, 0xfd469501)
+      OP (A, B, C, D,  7, 0x698098d8)
+      OP (D, A, B, C, 12, 0x8b44f7af)
+      OP (C, D, A, B, 17, 0xffff5bb1)
+      OP (B, C, D, A, 22, 0x895cd7be)
+      OP (A, B, C, D,  7, 0x6b901122)
+      OP (D, A, B, C, 12, 0xfd987193)
+      OP (C, D, A, B, 17, 0xa679438e)
+      OP (B, C, D, A, 22, 0x49b40821)
+
+      #undef OP
+      #define OP(f, a, b, c, d, k, s, T)             \
+         do                                          \
+         {                                           \
+            a += f (b, c, d) + correct_words[k] + T; \
+            CYCLIC (a, s);                           \
+            a += b;                                  \
+         }                                           \
+         while (0);
+
+      // Round 2
+      OP (FG, A, B, C, D,  1,  5, 0xf61e2562)
+      OP (FG, D, A, B, C,  6,  9, 0xc040b340)
+      OP (FG, C, D, A, B, 11, 14, 0x265e5a51)
+      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa)
+      OP (FG, A, B, C, D,  5,  5, 0xd62f105d)
+      OP (FG, D, A, B, C, 10,  9, 0x02441453)
+      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681)
+      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8)
+      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6)
+      OP (FG, D, A, B, C, 14,  9, 0xc33707d6)
+      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87)
+      OP (FG, B, C, D, A,  8, 20, 0x455a14ed)
+      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905)
+      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8)
+      OP (FG, C, D, A, B,  7, 14, 0x676f02d9)
+      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a)
+
+      // Round 3
+      OP (FH, A, B, C, D,  5,  4, 0xfffa3942)
+      OP (FH, D, A, B, C,  8, 11, 0x8771f681)
+      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122)
+      OP (FH, B, C, D, A, 14, 23, 0xfde5380c)
+      OP (FH, A, B, C, D,  1,  4, 0xa4beea44)
+      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9)
+      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60)
+      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70)
+      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6)
+      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa)
+      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085)
+      OP (FH, B, C, D, A,  6, 23, 0x04881d05)
+      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039)
+      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5)
+      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8)
+      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665)
+
+      // Round 4
+      OP (FI, A, B, C, D,  0,  6, 0xf4292244)
+      OP (FI, D, A, B, C,  7, 10, 0x432aff97)
+      OP (FI, C, D, A, B, 14, 15, 0xab9423a7)
+      OP (FI, B, C, D, A,  5, 21, 0xfc93a039)
+      OP (FI, A, B, C, D, 12,  6, 0x655b59c3)
+      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92)
+      OP (FI, C, D, A, B, 10, 15, 0xffeff47d)
+      OP (FI, B, C, D, A,  1, 21, 0x85845dd1)
+      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f)
+      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0)
+      OP (FI, C, D, A, B,  6, 15, 0xa3014314)
+      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1)
+      OP (FI, A, B, C, D,  4,  6, 0xf7537e82)
+      OP (FI, D, A, B, C, 11, 10, 0xbd3af235)
+      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb)
+      OP (FI, B, C, D, A,  9, 21, 0xeb86d391)
+
+      A += A_save;
+      B += B_save;
+      C += C_save;
+      D += D_save;
+   }
+
+   pContext->A = A;
+   pContext->B = B;
+   pContext->C = C;
+   pContext->D = D;
+}
+
+// The following code had been written for test purposes by myself (Guy). It contains the core MD5 calculation
+// in assembler. It has been tested and runs correctly, but it turned out to run slower than md5sum or other
+// g++ optimised code.
+// 1:0 für g++  :-)
+
+#ifdef MD5_USE_ASSEMBLER_CODE
+   static void MD5Process (t_pMD5Context pContext, const t_uchar *pData) // pData points to block of 64 bytes
+   {
+      // F(r2,r3,r4) = (((r3 ^ r4) & r2) ^ r4)
+      // r1 = ROTATE_LEFT(r1 + F(r2,r3,r4) + *X++ + Ti, s) + r2
+      #define OP_ROUND_1(r1,r2,r3,r4,Ofs,Shift,T) \
+         "movl " #r4 ",%%esi;" \
+         "xorl " #r3 ",%%esi;" \
+         "andl " #r2 ",%%esi;" \
+         "xorl " #r4 ",%%esi;" \
+         "leal " #T "(" #r1 ",%%esi,1)," #r1 ";"                   \
+         "addl " #Ofs "(%%rdi)," #r1 ";" \
+         "roll $" #Shift "," #r1 ";" \
+         "addl " #r2 "," #r1 ";" \
+
+      // G(r2,r3,r4) = (((r2 ^ r3) & r4) ^ r3)
+      // r1 = ROTATE_LEFT(r1 + G(r2,r3,r4) + X[k] + Ti, s) + r2
+      #define OP_ROUND_2(r1,r2,r3,r4,Ofs,Shift,T) \
+         "movl " #r3 ",%%esi;" \
+         "xorl " #r2 ",%%esi;" \
+         "andl " #r4 ",%%esi;" \
+         "xorl " #r3 ",%%esi;" \
+         "leal " #T "(" #r1 ",%%esi,1)," #r1 ";"                   \
+         "addl " #Ofs "(%%rdi)," #r1 ";" \
+         "roll $" #Shift "," #r1 ";" \
+         "addl " #r2 "," #r1 ";" \
+
+      //  H(r2,r3,r4) = (r2 ^ r3 ^ r4)
+      //  r1 = ROTATE_LEFT(r1 + H(r2,r3,r4) + X[k] + Ti, s) + r2
+      #define OP_ROUND_3(r1,r2,r3,r4,Ofs,Shift,T) \
+         "movl " #r2 ",%%esi;" \
+         "xorl " #r3 ",%%esi;" \
+         "xorl " #r4 ",%%esi;" \
+         "leal " #T "(" #r1 ",%%esi,1)," #r1 ";"                   \
+         "addl " #Ofs "(%%rdi)," #r1 ";" \
+         "roll $" #Shift "," #r1 ";" \
+         "addl " #r2 "," #r1 ";" \
+
+      //  I(r2,r3,r4) = ((r2 | ~r4) ^ r3)
+      //  r1 = ROTATE_LEFT(r1 + I(r2,r3,r4) + X[k] + Ti, s) + r2
+      #define OP_ROUND_4(r1,r2,r3,r4,Ofs,Shift,T) \
+         "movl " #r4 ",%%esi;" \
+         "not %%esi;" \
+         "orl  " #r2 ",%%esi;" \
+         "xorl " #r3 ",%%esi;" \
+         "leal " #T "(" #r1 ",%%esi,1)," #r1 ";"                   \
+         "addl " #Ofs "(%%rdi)," #r1 ";" \
+         "roll $" #Shift "," #r1 ";" \
+         "addl " #r2 "," #r1 ";" \
+
+      __asm__
+      (                                                                          \
+         OP_ROUND_1(%4,%5,%6,%7,  0,  7, -0x28955b88)
+         OP_ROUND_1(%7,%4,%5,%6,  4, 12, -0x173848aa)
+         OP_ROUND_1(%6,%7,%4,%5,  8, 17,  0x242070db)
+         OP_ROUND_1(%5,%6,%7,%4, 12, 22, -0x3e423112)
+         OP_ROUND_1(%4,%5,%6,%7, 16,  7, -0x0a83f051)
+         OP_ROUND_1(%7,%4,%5,%6, 20, 12,  0x4787c62a)
+         OP_ROUND_1(%6,%7,%4,%5, 24, 17, -0x57cfb9ed)
+         OP_ROUND_1(%5,%6,%7,%4, 28, 22, -0x02b96aff)
+         OP_ROUND_1(%4,%5,%6,%7, 32,  7,  0x698098d8)
+         OP_ROUND_1(%7,%4,%5,%6, 36, 12, -0x74bb0851)
+         OP_ROUND_1(%6,%7,%4,%5, 40, 17, -0x0000a44f)
+         OP_ROUND_1(%5,%6,%7,%4, 44, 22, -0x76a32842)
+         OP_ROUND_1(%4,%5,%6,%7, 48,  7,  0x6b901122)
+         OP_ROUND_1(%7,%4,%5,%6, 52, 12, -0x02678e6d)
+         OP_ROUND_1(%6,%7,%4,%5, 56, 17, -0x5986bc72)
+         OP_ROUND_1(%5,%6,%7,%4, 60, 22,  0x49b40821)
+
+         OP_ROUND_2(%4,%5,%6,%7,  4,  5, -0x09e1da9e)
+         OP_ROUND_2(%7,%4,%5,%6, 24,  9, -0x3fbf4cc0)
+         OP_ROUND_2(%6,%7,%4,%5, 44, 14,  0x265e5a51)
+         OP_ROUND_2(%5,%6,%7,%4,  0, 20, -0x16493856)
+         OP_ROUND_2(%4,%5,%6,%7, 20,  5, -0x29d0efa3)
+         OP_ROUND_2(%7,%4,%5,%6, 40,  9,  0x02441453)
+         OP_ROUND_2(%6,%7,%4,%5, 60, 14, -0x275e197f)
+         OP_ROUND_2(%5,%6,%7,%4, 16, 20, -0x182c0438)
+         OP_ROUND_2(%4,%5,%6,%7, 36,  5,  0x21e1cde6)
+         OP_ROUND_2(%7,%4,%5,%6, 56,  9, -0x3cc8f82a)
+         OP_ROUND_2(%6,%7,%4,%5, 12, 14, -0x0b2af279)
+         OP_ROUND_2(%5,%6,%7,%4, 32, 20,  0x455a14ed)
+         OP_ROUND_2(%4,%5,%6,%7, 52,  5, -0x561c16fb)
+         OP_ROUND_2(%7,%4,%5,%6,  8,  9, -0x03105c08)
+         OP_ROUND_2(%6,%7,%4,%5, 28, 14,  0x676f02d9)
+         OP_ROUND_2(%5,%6,%7,%4, 48, 20, -0x72d5b376)
+
+         OP_ROUND_3(%4,%5,%6,%7, 20,  4, -0x0005c6be)
+         OP_ROUND_3(%7,%4,%5,%6, 32, 11, -0x788e097f)
+         OP_ROUND_3(%6,%7,%4,%5, 44, 16,  0x6d9d6122)
+         OP_ROUND_3(%5,%6,%7,%4, 56, 23, -0x021ac7f4)
+         OP_ROUND_3(%4,%5,%6,%7,  4,  4, -0x5b4115bc)
+         OP_ROUND_3(%7,%4,%5,%6, 16, 11,  0x4bdecfa9)
+         OP_ROUND_3(%6,%7,%4,%5, 28, 16, -0x0944b4a0)
+         OP_ROUND_3(%5,%6,%7,%4, 40, 23, -0x41404390)
+         OP_ROUND_3(%4,%5,%6,%7, 52,  4,  0x289b7ec6)
+         OP_ROUND_3(%7,%4,%5,%6,  0, 11, -0x155ed806)
+         OP_ROUND_3(%6,%7,%4,%5, 12, 16, -0x2b10cf7b)
+         OP_ROUND_3(%5,%6,%7,%4, 24, 23,  0x04881d05)
+         OP_ROUND_3(%4,%5,%6,%7, 36,  4, -0x262b2fc7)
+         OP_ROUND_3(%7,%4,%5,%6, 48, 11, -0x1924661b)
+         OP_ROUND_3(%6,%7,%4,%5, 60, 16,  0x1fa27cf8)
+         OP_ROUND_3(%5,%6,%7,%4,  8, 23, -0x3b53a99b)
+
+         OP_ROUND_4(%4,%5,%6,%7,  0,  6, -0x0bd6ddbc)
+         OP_ROUND_4(%7,%4,%5,%6, 28, 10,  0x432aff97)
+         OP_ROUND_4(%6,%7,%4,%5, 56, 15, -0x546bdc59)
+         OP_ROUND_4(%5,%6,%7,%4, 20, 21, -0x036c5fc7)
+         OP_ROUND_4(%4,%5,%6,%7, 48,  6,  0x655b59c3)
+         OP_ROUND_4(%7,%4,%5,%6, 12, 10, -0x70f3336e)
+         OP_ROUND_4(%6,%7,%4,%5, 40, 15, -0x00100b83)
+         OP_ROUND_4(%5,%6,%7,%4,  4, 21, -0x7a7ba22f)
+         OP_ROUND_4(%4,%5,%6,%7, 32,  6,  0x6fa87e4f)
+         OP_ROUND_4(%7,%4,%5,%6, 60, 10, -0x01d31920)
+         OP_ROUND_4(%6,%7,%4,%5, 24, 15, -0x5cfebcec)
+         OP_ROUND_4(%5,%6,%7,%4, 52, 21,  0x4e0811a1)
+         OP_ROUND_4(%4,%5,%6,%7, 16,  6, -0x08ac817e)
+         OP_ROUND_4(%7,%4,%5,%6, 44, 10, -0x42c50dcb)
+         OP_ROUND_4(%6,%7,%4,%5,  8, 15,  0x2ad7d2bb)
+         OP_ROUND_4(%5,%6,%7,%4, 36, 21, -0x14792c6f)
+
+         "addl %4,%0;"
+         "addl %5,%1;"
+         "addl %6,%2;"
+         "addl %7,%3;"
+         :"=m"(pContext->a), "=m"(pContext->b), "=m"(pContext->c), "=m"(pContext->d) \
+         : "r"(pContext->a),  "r"(pContext->b),  "r"(pContext->c),  "r"(pContext->d), "D"(pData)       \
+         : "%esi", "%cc"
+      );
+}
+#endif
+
+void MD5Append (t_pMD5Context pContext, const void *pBuffer, size_t Len)
+{
+   // When we already have some bits in our internal buffer concatenate both inputs first.
+   if (pContext->buflen != 0)
+   {
+      size_t left_over = pContext->buflen;
+      size_t add       = 128 - left_over > Len ? Len : 128 - left_over;
+
+      memcpy (&((char *) pContext->buffer)[left_over], pBuffer, add);
+      pContext->buflen += add;
+
+      if (pContext->buflen > 64)
+      {
+         MD5ProcessBlock (pContext, pContext->buffer, pContext->buflen & ~63);
+
+         pContext->buflen &= 63;
+         memcpy (pContext->buffer,
+                 &((char *) pContext->buffer)[(left_over + add) & ~63],
+                 pContext->buflen);
+      }
+
+      pBuffer = (const char *) pBuffer + add;
+      Len    -= add;
+   }
+
+   // Process available complete blocks
+   if (Len >= 64)
+   {
+      #if !_STRING_ARCH_unaligned
+         #define alignof(type)  offsetof (struct { char c; type x; }, x)
+         #define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
+
+         if (UNALIGNED_P (pBuffer))
+         {
+            while (Len > 64)
+            {
+               MD5ProcessBlock (pContext, memcpy (pContext->buffer, pBuffer, 64), 64);
+               pBuffer = (const char *) pBuffer + 64;
+               Len -= 64;
+             }
+         }
+         else
+      #endif
+         {
+            MD5ProcessBlock (pContext, pBuffer, Len & ~63);
+            pBuffer = (const char *) pBuffer + (Len & ~63);
+            Len &= 63;
+         }
+   }
+
+   // Move remaining bytes in internal buffer
+   if (Len > 0)
+   {
+      size_t left_over = pContext->buflen;
+
+      memcpy (&((char *) pContext->buffer)[left_over], pBuffer, Len);
+      left_over += Len;
+      if (left_over >= 64)
+      {
+         MD5ProcessBlock (pContext, pContext->buffer, 64);
+         left_over -= 64;
+         memcpy (pContext->buffer, &pContext->buffer[16], left_over);
+      }
+      pContext->buflen = left_over;
+   }
+}
+
+void MD5Finish (t_pMD5Context pContext, void *pDigest)
+{
+   // Take yet unprocessed bytes into account
+   uint32_t bytes = pContext->buflen;
+   size_t   size  = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
+
+   // Count remaining bytes
+   pContext->total[0] += bytes;
+   if (pContext->total[0] < bytes)
+      ++pContext->total[1];
+
+   // Put the file length (in bits) at the end of the buffer
+   pContext->buffer[size - 2] = SWAP  (pContext->total[0] << 3);
+   pContext->buffer[size - 1] = SWAP ((pContext->total[1] << 3) | (pContext->total[0] >> 29));
+   memcpy (&((char *) pContext->buffer)[bytes], MD5PadBuf, (size - 2) * 4 - bytes);
+
+   // Process last bytes
+   MD5ProcessBlock (pContext, pContext->buffer, size * 4);
+
+   // Read digest
+   char *r = (char *)pDigest;
+   set_uint32 (r + 0 * sizeof pContext->A, SWAP (pContext->A));
+   set_uint32 (r + 1 * sizeof pContext->B, SWAP (pContext->B));
+   set_uint32 (r + 2 * sizeof pContext->C, SWAP (pContext->C));
+   set_uint32 (r + 3 * sizeof pContext->D, SWAP (pContext->D));
+}
+
+#ifdef TEST
+   #include <string.h>
+   #include <stdlib.h>
+   #include <stdio.h>
+
+   static const char *const TestVectorArr[] =
+   {
+      ""                                                              ,                   // d41d8cd98f00b204e9800998ecf8427e
+      "a"                                                             ,                   // 0cc175b9c0f1b6a831c399e269772661
+      "abc"                                                           ,                   // 900150983cd24fb0d6963f7d28e17f72
+      "message digest"                                                ,                   // f96b697d7cb7938d525a2f31aaf161d0
+      "abcdefghijklmnopqrstuvwxyz"                                    ,                   // c3fcd3d76192e4007dfb496cca67e13b
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",                   // d174ab98d277d9f5a5611c2c9f419d9f
+      "12345678901234567890123456789012345678901234567890123456789012345678901234567890", // 57edf4a22be3c955ac49da2e2107b67a
+      NULL
+   };
+
+   int main (int argc, char *argv[])
+   {
+      FILE          *f;
+      int            i, j;
+      char           output[65];
+      t_MD5Context   Context;
+      unsigned char  Buf[65536];
+      unsigned char  Digest[16];
+      const char   *pVector;
+
+      if( argc < 2 )
+      {
+         printf( "MD5 test:\n" );
+
+         int i=0;
+
+         pVector = TestVectorArr[i];
+         while (pVector)
+         {
+            int di;
+
+            MD5Init   (&Context);
+            MD5Append (&Context, pVector, strlen(pVector));
+            MD5Finish (&Context, Digest);
+            printf("MD5 (%-80s) = ", pVector);
+            for (di = 0; di < 16; ++di)
+               printf("%02x", Digest[di]);
+            printf("\n");
+            i++;
+            pVector = TestVectorArr[i];
+         }
+      }
+      else
+      {
+         if( ! ( f = fopen( argv[1], "rb" ) ) )
+         {
+             perror( "fopen" );
+             return( 1 );
+         }
+
+         MD5Init (&Context);
+         while ((i = fread (Buf, 1, sizeof(Buf), f)) > 0)
+            MD5Append(&Context, Buf, i);
+
+         MD5Finish(&Context, Digest);
+         for (j = 0; j < sizeof(Digest); j++)
+            printf ("%02x", Digest[j]);
+
+         printf ("  %s\n", argv[1]);
+      }
+      return (0);
+   }
+#endif /* TEST */
diff --git a/md5.h b/md5.h
index 504dee3..c5918dc 100644
--- a/md5.h
+++ b/md5.h
@@ -1,101 +1,58 @@
-// This file has been copied 1:1 from the source of the Debian fdupes package into Guymager.
-// Only have been added these 2 comment lines, no other changes.
-
-/*
-  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost at aladdin.com
-
- */
-/*$Id: md5.h $ */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321.
-  It is derived directly from the text of the RFC and not from the
-  reference implementation.
-
-  The original and principal author of md5.h is L. Peter Deutsch
-  <ghost at aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
-	added conditionalization for C++ compilation from Martin
-	Purschke <purschke at bnl.gov>.
-  1999-05-03 lpd Original version.
- */
-
-#ifndef md5_INCLUDED
-#  define md5_INCLUDED
-
-/*
- * This code has some adaptations for the Ghostscript environment, but it
- * will compile and run correctly in any environment with 8-bit chars and
- * 32-bit ints.  Specifically, it assumes that if the following are
- * defined, they have the same meaning as in Ghostscript: P1, P2, P3,
- * ARCH_IS_BIG_ENDIAN.
- */
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
-    md5_word_t count[2];	/* message length in bits, lsw first */
-    md5_word_t abcd[4];		/* digest buffer */
-    md5_byte_t buf[64];		/* accumulate block */
-} md5_state_t;
-
-#ifdef __cplusplus
-extern "C"
+// ****************************************************************************
+//  Project:        GUYMAGER
+// ****************************************************************************
+//  Programmer:     Guy Voncken
+//                  Police Grand-Ducale
+//                  Service de Police Judiciaire
+//                  Section Nouvelles Technologies
+// ****************************************************************************
+//  Module:         MD5 calculation
+// ****************************************************************************
+
+// Copyright 2008, 2009, 2010, 2011, 2012 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/>.
+
+// The core functions of this module are based on the functions found in
+// standard Linux' md5sum command, contained in package coreutils on Debian.
+
+#ifndef __MD5_H__
+#define __MD5_H__
+
+#define MD5_DIGEST_SIZE 16
+#define MD5_BLOCK_SIZE  64
+
+typedef unsigned int uint32_t;
+
+typedef struct
 {
-#endif
-
-/* Initialize the algorithm. */
-#ifdef P1
-void md5_init(P1(md5_state_t *pms));
-#else
-void md5_init(md5_state_t *pms);
-#endif
+  uint32_t A;
+  uint32_t B;
+  uint32_t C;
+  uint32_t D;
+
+  uint32_t total[2];
+  uint32_t buflen;
+  uint32_t buffer[32];
+} t_MD5Context, *t_pMD5Context;
+
+// Always make sure that these functions are compiled with O3 optimisation or
+// else, performance is about 5 times worse! See also MD5ProcessBlock in md5.cpp.
+void MD5Init   (t_pMD5Context pContext)                                   __attribute__((optimize("-O3")));
+void MD5Append (t_pMD5Context pContext, const void *pBuffer, size_t Len)  __attribute__((optimize("-O3")));
+void MD5Finish (t_pMD5Context pContext, void *pDigest)                    __attribute__((optimize("-O3")));
 
-/* Append a string to the message. */
-#ifdef P3
-void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes));
-#else
-void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
 #endif
-
-/* Finish the message and return the digest. */
-#ifdef P2
-void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16]));
-#else
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
-#endif
-
-#ifdef __cplusplus
-}  /* end extern "C" */
-#endif
-
-#endif /* md5_INCLUDED */
-
-
-
-
diff --git a/media.cpp b/media.cpp
index ab77529..732489c 100644
--- a/media.cpp
+++ b/media.cpp
@@ -11,6 +11,23 @@
 //                  copied from Mark Lord's famous hdparm.
 // ****************************************************************************
 
+// Copyright 2008, 2009, 2010, 2011, 2012 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/>.
+
 #include <stdlib.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -754,6 +771,7 @@ APIRET t_MediaInfo::QueryDevice (const char *pLinuxDevice)
    InitUnknown();
 
    pMediaDriveCmdATA   = (t_pMediaDriveCmd) malloc (sizeof(t_MediaDriveCmd));
+   memset (pMediaDriveCmdATA, 0, sizeof(t_MediaDriveCmd));
 
    File = open (pLinuxDevice, O_RDONLY);
    if (File < 0)
diff --git a/sha256.cpp b/sha256.cpp
index b463050..4df41be 100644
--- a/sha256.cpp
+++ b/sha256.cpp
@@ -1,45 +1,61 @@
-// sha256 calculation on i386 and amd64 processors.
-/*
- *  FIPS-180-2 compliant SHA-256 implementation
- *
- *  Copyright (C) 2001-2003  Christophe Devine
- *  Copyright (C) 2010,2011  Guy Voncken <vogu00 at gmail.com>
- *
- *  This program 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.
- *
- *  This program 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 this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
+// ****************************************************************************
+//  Project:        GUYMAGER
+// ****************************************************************************
+//  Programmer:     Guy Voncken
+//                  Police Grand-Ducale
+//                  Service de Police Judiciaire
+//                  Section Nouvelles Technologies
+// ****************************************************************************
+//  Module:         MD5 calculation
+// ****************************************************************************
+
+// Copyright 2008, 2009, 2010, 2011, 2012 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/>.
 
-// This file has initially been downloaded from
-//     www.spale.com/download/scrypt/scrypt1.0/sha256.c
+
+// This module was initially based on the file
+//    www.spale.com/download/scrypt/scrypt1.0/sha256.c
+// copyrighted by Christophe Devine, with assembler i386/amd64-optimisation
+// and big endian debugging added by Guy Voncken. That optimised code
+// was faster than the Linux' standard tool sha256sum. You find it in
+// this module under SHA256_OLD macro.
 //
-// The following optimisation and debugging work has been done by Guy Voncken:
-//     - The CPU intensive parts have been rewritten in assembler for better
-//       performance on i386 and amd64 machines.
-//     - The code has been corrected for big endian machines. The corrections
-//       have been tested on a PowerPC machine.
+// In later tests it was observed that sha256sum (or gcc) must have been
+// improved; sha256sum was the fastet now. That's why this module nowadays
+// is based on sha256sum's code (see Debian package coreutils, for example).
+// The core functions have been mainly copy/pasted; they have been written
+// by David Madore and Scott G. Miller and are copyrighted by the Free
+// Software Foundation, Inc.
 
 
-#include <string.h>
-#include <netinet/in.h>
+//#define SHA256_OLD
 
+#include <stddef.h>
 #include "sha256.h"
 
+#ifdef SHA256_OLD
+
+#include <string.h>
+#include <netinet/in.h>
+
 #if defined(__i386__) || defined (__amd64__)
    #define SHA256_USE_OPTIMISED_ASSEMBLER_CODE
 #endif
 
-
 // Guy: The original GET_UINT32 and PUT_UINT32 macros are
 //   - too slow
 //   - not working on powerpc
@@ -69,24 +85,22 @@
 #define PUT_UINT32(n,b,i)                       \
    *((uint32 *)&(b)[i]) = ntohl((n));
 
-void sha256_starts( sha256_context *ctx )
+void SHA256Init (t_pSHA256Context pContext)
 {
-    ctx->total[0] = 0;
-    ctx->total[1] = 0;
-
-    ctx->state[0] = 0x6A09E667;
-    ctx->state[1] = 0xBB67AE85;
-    ctx->state[2] = 0x3C6EF372;
-    ctx->state[3] = 0xA54FF53A;
-    ctx->state[4] = 0x510E527F;
-    ctx->state[5] = 0x9B05688C;
-    ctx->state[6] = 0x1F83D9AB;
-    ctx->state[7] = 0x5BE0CD19;
+    pContext->total[0] = 0;
+    pContext->total[1] = 0;
+
+    pContext->state[0] = 0x6A09E667;
+    pContext->state[1] = 0xBB67AE85;
+    pContext->state[2] = 0x3C6EF372;
+    pContext->state[3] = 0xA54FF53A;
+    pContext->state[4] = 0x510E527F;
+    pContext->state[5] = 0x9B05688C;
+    pContext->state[6] = 0x1F83D9AB;
+    pContext->state[7] = 0x5BE0CD19;
 }
 
-
 #ifdef SHA256_USE_OPTIMISED_ASSEMBLER_CODE
-
    #define P(a,b,c,d,e,f,g,h,x,K)                                                                       \
        __asm__  __volatile__ (                                                                          \
                 /* ------------------------------------------------------------------------------- */   \
@@ -145,7 +159,6 @@ void sha256_starts( sha256_context *ctx )
                                                                                                 \
             :"%eax", "%ebx", "%ecx", "%edx", "%cc", "memory")
 
-
    #if defined(__i386__)
       #define PR(a,b,c,d,e,f,g,h,i,K)                                         \
           __asm__  __volatile__ (                                             \
@@ -235,9 +248,7 @@ void sha256_starts( sha256_context *ctx )
                /*   2       3       4       5       6       7       8       9       10       0       1 */   \
                                                                                                             \
                :"%eax", "%ebx", "%ecx", "%edx", "%cc", "memory")
-
    #elif defined(__amd64__)
-
       #define PR(a,b,c,d,e,f,g,h,i,K)                                         \
           __asm__  __volatile__ (                                             \
                                                                               \
@@ -359,10 +370,9 @@ void sha256_starts( sha256_context *ctx )
    #define PR(a,b,c,d,e,f,g,h,i,K)                 \
       P(a,b,c,d,e,f,g,h,R(i),K)
 
-
 #endif
 
-void sha256_process( sha256_context *ctx, uint8 data[64] )
+static void SHA256Process(t_pSHA256Context pContext, uint8 data[64] )
 {
     #ifndef SHA256_USE_OPTIMISED_ASSEMBLER_CODE
        uint32 temp1, temp2;
@@ -388,14 +398,14 @@ void sha256_process( sha256_context *ctx, uint8 data[64] )
     GET_UINT32( W[14], data, 56 );
     GET_UINT32( W[15], data, 60 );
 
-    A = ctx->state[0];
-    B = ctx->state[1];
-    C = ctx->state[2];
-    D = ctx->state[3];
-    E = ctx->state[4];
-    F = ctx->state[5];
-    G = ctx->state[6];
-    H = ctx->state[7];
+    A = pContext->state[0];
+    B = pContext->state[1];
+    C = pContext->state[2];
+    D = pContext->state[3];
+    E = pContext->state[4];
+    F = pContext->state[5];
+    G = pContext->state[6];
+    H = pContext->state[7];
 
     P( A, B, C, D, E, F, G, H, W[ 0],  0x428A2F98 );
     P( H, A, B, C, D, E, F, G, W[ 1],  0x71374491 );
@@ -462,36 +472,36 @@ void sha256_process( sha256_context *ctx, uint8 data[64] )
     PR(C, D, E, F, G, H, A, B,   62 , -0x41065C09 );
     PR(B, C, D, E, F, G, H, A,   63 , -0x398E870E );
 
-    ctx->state[0] += A;
-    ctx->state[1] += B;
-    ctx->state[2] += C;
-    ctx->state[3] += D;
-    ctx->state[4] += E;
-    ctx->state[5] += F;
-    ctx->state[6] += G;
-    ctx->state[7] += H;
+    pContext->state[0] += A;
+    pContext->state[1] += B;
+    pContext->state[2] += C;
+    pContext->state[3] += D;
+    pContext->state[4] += E;
+    pContext->state[5] += F;
+    pContext->state[6] += G;
+    pContext->state[7] += H;
 }
 
-void sha256_update( sha256_context *ctx, uint8 *input, uint32 length )
+void SHA256Append (t_pSHA256Context pContext, uint8 *input, uint32 length )
 {
     uint32 left, fill;
 
     if( ! length ) return;
 
-    left = ctx->total[0] & 0x3F;
+    left = pContext->total[0] & 0x3F;
     fill = 64 - left;
 
-    ctx->total[0] += length;
-    ctx->total[0] &= 0xFFFFFFFF;
+    pContext->total[0] += length;
+    pContext->total[0] &= 0xFFFFFFFF;
 
-    if( ctx->total[0] < length )
-        ctx->total[1]++;
+    if( pContext->total[0] < length )
+        pContext->total[1]++;
 
     if( left && length >= fill )
     {
-        memcpy( (void *) (ctx->buffer + left),
+        memcpy( (void *) (pContext->buffer + left),
                 (void *) input, fill );
-        sha256_process( ctx, ctx->buffer );
+        SHA256Process (pContext, pContext->buffer);
         length -= fill;
         input  += fill;
         left = 0;
@@ -499,19 +509,19 @@ void sha256_update( sha256_context *ctx, uint8 *input, uint32 length )
 
     while( length >= 64 )
     {
-        sha256_process( ctx, input );
+        SHA256Process (pContext, input );
         length -= 64;
         input  += 64;
     }
 
     if( length )
     {
-        memcpy( (void *) (ctx->buffer + left),
+        memcpy( (void *) (pContext->buffer + left),
                 (void *) input, length );
     }
 }
 
-static uint8 sha256_padding[64] =
+static uint8 SHA256Padding[64] =
 {
  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -519,35 +529,329 @@ static uint8 sha256_padding[64] =
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
-void sha256_finish( sha256_context *ctx, uint8 digest[32] )
+void SHA256Finish (t_pSHA256Context pContext, uint8 digest[32])
 {
     uint32 last, padn;
     uint32 high, low;
     uint8 msglen[8];
 
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
+    high = ( pContext->total[0] >> 29 )
+         | ( pContext->total[1] <<  3 );
+    low  = ( pContext->total[0] <<  3 );
 
     PUT_UINT32( high, msglen, 0 );
     PUT_UINT32( low,  msglen, 4 );
 
-    last = ctx->total[0] & 0x3F;
+    last = pContext->total[0] & 0x3F;
     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
 
-    sha256_update( ctx, sha256_padding, padn );
-    sha256_update( ctx, msglen, 8 );
-
-    PUT_UINT32( ctx->state[0], digest,  0 );
-    PUT_UINT32( ctx->state[1], digest,  4 );
-    PUT_UINT32( ctx->state[2], digest,  8 );
-    PUT_UINT32( ctx->state[3], digest, 12 );
-    PUT_UINT32( ctx->state[4], digest, 16 );
-    PUT_UINT32( ctx->state[5], digest, 20 );
-    PUT_UINT32( ctx->state[6], digest, 24 );
-    PUT_UINT32( ctx->state[7], digest, 28 );
+    SHA256Append (pContext, SHA256Padding, padn);
+    SHA256Append (pContext, msglen, 8);
+
+    PUT_UINT32(pContext->state[0], digest,  0);
+    PUT_UINT32(pContext->state[1], digest,  4);
+    PUT_UINT32(pContext->state[2], digest,  8);
+    PUT_UINT32(pContext->state[3], digest, 12);
+    PUT_UINT32(pContext->state[4], digest, 16);
+    PUT_UINT32(pContext->state[5], digest, 20);
+    PUT_UINT32(pContext->state[6], digest, 24);
+    PUT_UINT32(pContext->state[7], digest, 28);
+}
+
+#else  // SHA256_OLD
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef WORDS_BIGENDIAN
+   #define SWAP(n) (n)
+#else
+   #define SWAP(n) (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#endif
+
+#define BLOCKSIZE 32768
+#if BLOCKSIZE % 64 != 0
+  #error "invalid BLOCKSIZE"
+#endif
+
+static const unsigned char SHA256PadBuf[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+void SHA256Init (t_pSHA256Context pContext)
+{
+   pContext->state[0] = 0x6a09e667UL;
+   pContext->state[1] = 0xbb67ae85UL;
+   pContext->state[2] = 0x3c6ef372UL;
+   pContext->state[3] = 0xa54ff53aUL;
+   pContext->state[4] = 0x510e527fUL;
+   pContext->state[5] = 0x9b05688cUL;
+   pContext->state[6] = 0x1f83d9abUL;
+   pContext->state[7] = 0x5be0cd19UL;
+
+   pContext->total[0] = pContext->total[1] = 0;
+   pContext->buflen   = 0;
+}
+
+static inline void set_uint32 (char *cp, uint32 v)
+{
+   memcpy (cp, &v, sizeof v);
+}
+
+// SHA256 round constants
+#define K(I) sha256_round_constants[I]
+static const uint32 sha256_round_constants[64] =
+{
+   0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+   0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+   0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+   0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+   0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+   0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+   0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+   0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+   0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+   0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+   0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+   0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+   0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+   0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+   0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+   0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
+};
+
+// Round functions
+#define F2(A,B,C) ( ( A & B ) | ( C & ( A | B ) ) )
+#define F1(E,F,G) ( G ^ ( E & ( F ^ G ) ) )
+
+static void SHA256ProcessBlock (t_pSHA256Context pContext, const void *buffer, size_t len) __attribute__((optimize("-O3")));
+static void SHA256ProcessBlock (t_pSHA256Context pContext, const void *buffer, size_t len)
+{
+   size_t        nwords = len / sizeof (uint32);
+   const uint32 *words  = (uint32 *)buffer;
+   const uint32 *endp   = words + nwords;
+   uint32 a = pContext->state[0];
+   uint32 b = pContext->state[1];
+   uint32 c = pContext->state[2];
+   uint32 d = pContext->state[3];
+   uint32 e = pContext->state[4];
+   uint32 f = pContext->state[5];
+   uint32 g = pContext->state[6];
+   uint32 h = pContext->state[7];
+   uint32 x[16];
+
+   pContext->total[0] += len;
+   if (pContext->total[0] < len)
+      ++pContext->total[1];
+
+   #define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+   #define S0(x)     (rol(x,25) ^ rol(x,14) ^ (x>> 3))
+   #define S1(x)     (rol(x,15) ^ rol(x,13) ^ (x>>10))
+   #define SS0(x)    (rol(x,30) ^ rol(x,19) ^ rol(x,10))
+   #define SS1(x)    (rol(x,26) ^ rol(x,21) ^ rol(x, 7))
+
+   #define M(I) ( tm =   S1(x[(I- 2)&0x0f]) + x[(I-7)&0x0f] \
+                       + S0(x[(I-15)&0x0f]) + x[ I   &0x0f] \
+                  , x[I&0x0f] = tm )
+
+   #define R(A,B,C,D,E,F,G,H,K,M)  \
+      do                           \
+      {                            \
+         t0  = SS0(A) + F2(A,B,C); \
+         t1  = H + SS1(E)          \
+             + F1(E,F,G)           \
+             + K                   \
+             + M;                  \
+          D += t1;                 \
+          H  = t0 + t1;            \
+      } while(0)
+
+   while (words < endp)
+   {
+      uint32 tm;
+      uint32 t0, t1;
+      int t;
+
+      for (t = 0; t < 16; t++)
+      {
+         x[t] = SWAP (*words);
+         words++;
+      }
+
+      R( a, b, c, d, e, f, g, h, K( 0), x[ 0] );
+      R( h, a, b, c, d, e, f, g, K( 1), x[ 1] );
+      R( g, h, a, b, c, d, e, f, K( 2), x[ 2] );
+      R( f, g, h, a, b, c, d, e, K( 3), x[ 3] );
+      R( e, f, g, h, a, b, c, d, K( 4), x[ 4] );
+      R( d, e, f, g, h, a, b, c, K( 5), x[ 5] );
+      R( c, d, e, f, g, h, a, b, K( 6), x[ 6] );
+      R( b, c, d, e, f, g, h, a, K( 7), x[ 7] );
+      R( a, b, c, d, e, f, g, h, K( 8), x[ 8] );
+      R( h, a, b, c, d, e, f, g, K( 9), x[ 9] );
+      R( g, h, a, b, c, d, e, f, K(10), x[10] );
+      R( f, g, h, a, b, c, d, e, K(11), x[11] );
+      R( e, f, g, h, a, b, c, d, K(12), x[12] );
+      R( d, e, f, g, h, a, b, c, K(13), x[13] );
+      R( c, d, e, f, g, h, a, b, K(14), x[14] );
+      R( b, c, d, e, f, g, h, a, K(15), x[15] );
+      R( a, b, c, d, e, f, g, h, K(16), M(16) );
+      R( h, a, b, c, d, e, f, g, K(17), M(17) );
+      R( g, h, a, b, c, d, e, f, K(18), M(18) );
+      R( f, g, h, a, b, c, d, e, K(19), M(19) );
+      R( e, f, g, h, a, b, c, d, K(20), M(20) );
+      R( d, e, f, g, h, a, b, c, K(21), M(21) );
+      R( c, d, e, f, g, h, a, b, K(22), M(22) );
+      R( b, c, d, e, f, g, h, a, K(23), M(23) );
+      R( a, b, c, d, e, f, g, h, K(24), M(24) );
+      R( h, a, b, c, d, e, f, g, K(25), M(25) );
+      R( g, h, a, b, c, d, e, f, K(26), M(26) );
+      R( f, g, h, a, b, c, d, e, K(27), M(27) );
+      R( e, f, g, h, a, b, c, d, K(28), M(28) );
+      R( d, e, f, g, h, a, b, c, K(29), M(29) );
+      R( c, d, e, f, g, h, a, b, K(30), M(30) );
+      R( b, c, d, e, f, g, h, a, K(31), M(31) );
+      R( a, b, c, d, e, f, g, h, K(32), M(32) );
+      R( h, a, b, c, d, e, f, g, K(33), M(33) );
+      R( g, h, a, b, c, d, e, f, K(34), M(34) );
+      R( f, g, h, a, b, c, d, e, K(35), M(35) );
+      R( e, f, g, h, a, b, c, d, K(36), M(36) );
+      R( d, e, f, g, h, a, b, c, K(37), M(37) );
+      R( c, d, e, f, g, h, a, b, K(38), M(38) );
+      R( b, c, d, e, f, g, h, a, K(39), M(39) );
+      R( a, b, c, d, e, f, g, h, K(40), M(40) );
+      R( h, a, b, c, d, e, f, g, K(41), M(41) );
+      R( g, h, a, b, c, d, e, f, K(42), M(42) );
+      R( f, g, h, a, b, c, d, e, K(43), M(43) );
+      R( e, f, g, h, a, b, c, d, K(44), M(44) );
+      R( d, e, f, g, h, a, b, c, K(45), M(45) );
+      R( c, d, e, f, g, h, a, b, K(46), M(46) );
+      R( b, c, d, e, f, g, h, a, K(47), M(47) );
+      R( a, b, c, d, e, f, g, h, K(48), M(48) );
+      R( h, a, b, c, d, e, f, g, K(49), M(49) );
+      R( g, h, a, b, c, d, e, f, K(50), M(50) );
+      R( f, g, h, a, b, c, d, e, K(51), M(51) );
+      R( e, f, g, h, a, b, c, d, K(52), M(52) );
+      R( d, e, f, g, h, a, b, c, K(53), M(53) );
+      R( c, d, e, f, g, h, a, b, K(54), M(54) );
+      R( b, c, d, e, f, g, h, a, K(55), M(55) );
+      R( a, b, c, d, e, f, g, h, K(56), M(56) );
+      R( h, a, b, c, d, e, f, g, K(57), M(57) );
+      R( g, h, a, b, c, d, e, f, K(58), M(58) );
+      R( f, g, h, a, b, c, d, e, K(59), M(59) );
+      R( e, f, g, h, a, b, c, d, K(60), M(60) );
+      R( d, e, f, g, h, a, b, c, K(61), M(61) );
+      R( c, d, e, f, g, h, a, b, K(62), M(62) );
+      R( b, c, d, e, f, g, h, a, K(63), M(63) );
+
+      a = pContext->state[0] += a;
+      b = pContext->state[1] += b;
+      c = pContext->state[2] += c;
+      d = pContext->state[3] += d;
+      e = pContext->state[4] += e;
+      f = pContext->state[5] += f;
+      g = pContext->state[6] += g;
+      h = pContext->state[7] += h;
+   }
 }
 
+void SHA256Finish (t_pSHA256Context pContext, void *pDigest)
+{
+   // Take yet unprocessed bytes into account
+   size_t bytes = pContext->buflen;
+   size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
+
+   // Count remaining bytes
+   pContext->total[0] += bytes;
+   if (pContext->total[0] < bytes)
+      ++pContext->total[1];
+
+   set_uint32 ((char *) &pContext->buffer[size - 2], SWAP ((pContext->total[1] << 3) | (pContext->total[0] >> 29)));
+   set_uint32 ((char *) &pContext->buffer[size - 1], SWAP (pContext->total[0] << 3));
+
+   memcpy (&((char *) pContext->buffer)[bytes], SHA256PadBuf, (size - 2) * 4 - bytes);
+
+   // Process last bytes
+   SHA256ProcessBlock (pContext, pContext->buffer, size * 4);
+
+   // Get digest
+   int   i;
+   char *r = (char*)pDigest;
+
+   for (i = 0; i < 8; i++)
+      set_uint32 (r + i * sizeof pContext->state[0], SWAP (pContext->state[i]));
+}
+
+
+void SHA256Append (t_pSHA256Context pContext, const void *buffer, size_t len)
+{
+   // When we already have some bits in our internal buffer concatenate both inputs first
+   if (pContext->buflen != 0)
+   {
+      size_t left_over = pContext->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&((char *) pContext->buffer)[left_over], buffer, add);
+      pContext->buflen += add;
+
+      if (pContext->buflen > 64)
+      {
+         SHA256ProcessBlock (pContext, pContext->buffer, pContext->buflen & ~63);
+
+         pContext->buflen &= 63;
+         memcpy (pContext->buffer,
+                 &((char *) pContext->buffer)[(left_over + add) & ~63],
+                 pContext->buflen);
+      }
+      buffer = (const char *) buffer + add;
+      len -= add;
+   }
+
+   // Process available complete blocks
+   if (len >= 64)
+   {
+      #if !_STRING_ARCH_unaligned
+         #define alignof(type) offsetof (struct { char c; type x; }, x)
+         #define UNALIGNED_P(p) (((size_t) p) % alignof (uint32) != 0)
+         if (UNALIGNED_P (buffer))
+         {
+            while (len > 64)
+            {
+               SHA256ProcessBlock (pContext, memcpy (pContext->buffer, buffer, 64), 64);
+               buffer = (const char *) buffer + 64;
+               len -= 64;
+            }
+         }
+         else
+      #endif
+         {
+            SHA256ProcessBlock (pContext, buffer, len & ~63);
+            buffer = (const char *) buffer + (len & ~63);
+            len &= 63;
+         }
+   }
+
+   // Move remaining bytes in internal buffer
+   if (len > 0)
+   {
+      size_t left_over = pContext->buflen;
+
+      memcpy (&((char *) pContext->buffer)[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 64)
+      {
+         SHA256ProcessBlock (pContext, pContext->buffer, 64);
+         left_over -= 64;
+         memcpy (pContext->buffer, &pContext->buffer[16], left_over);
+      }
+      pContext->buflen = left_over;
+   }
+}
+
+
+#endif // SHA256_OLD
+
 #ifdef TEST
 
 #include <stdlib.h>
@@ -576,82 +880,64 @@ static const char *val[] =
 
 int main( int argc, char *argv[] )
 {
-    FILE *f;
-    int i, j;
-    char output[65];
-    sha256_context ctx;
-    unsigned char buf[65536];
-    unsigned char sha256sum[32];
-
-    if( argc < 2 )
-    {
-        printf( "\n SHA-256 Validation Tests:\n\n" );
-
-        for( i = 0; i < 3; i++ )
-        {
-            printf( " Test %d ", i + 1 );
-
-            sha256_starts( &ctx );
-
-            if( i < 2 )
-            {
-                sha256_update( &ctx, (uint8 *) msg[i],
-                               strlen( msg[i] ) );
-            }
-            else
-            {
-                memset( buf, 'a', 1000 );
-
-                for( j = 0; j < 1000; j++ )
-                {
-                    sha256_update( &ctx, (uint8 *) buf, 1000 );
-                }
-            }
-
-            sha256_finish( &ctx, sha256sum );
-
-            for( j = 0; j < 32; j++ )
-            {
-                sprintf( output + j * 2, "%02x", sha256sum[j] );
-            }
-
-            if( memcmp( output, val[i], 64 ) )
-            {
-                printf( "failed!\n" );
-                return( 1 );
-            }
-
-            printf( "passed.\n" );
-        }
-
-        printf( "\n" );
-    }
-    else
-    {
-        if( ! ( f = fopen( argv[1], "rb" ) ) )
-        {
-            perror( "fopen" );
+   FILE            *f;
+   int             i, j;
+   char            output[65];
+   t_SHA256Context Context;
+   unsigned char   buf[65536];
+   unsigned char   sha256sum[32];
+
+   if( argc < 2 )
+   {
+      printf( "\n SHA-256 Validation Tests:\n\n" );
+
+      for( i = 0; i < 3; i++ )
+      {
+         printf( " Test %d ", i + 1 );
+         SHA256Init (&Context);
+         if( i < 2 )
+         {
+            SHA256Append (&Context, (uint8 *) msg[i], strlen( msg[i] ) );
+         }
+         else
+         {
+            memset( buf, 'a', 1000 );
+            for (j = 0; j < 1000; j++)
+               SHA256Append (&Context, (uint8 *) buf, 1000 );
+         }
+
+         SHA256Finish (&Context, sha256sum);
+         for (j = 0; j < 32; j++)
+            sprintf( output + j * 2, "%02x", sha256sum[j] );
+
+         if (memcmp( output, val[i], 64 ))
+         {
+            printf( "failed!\n" );
             return( 1 );
-        }
-
-        sha256_starts( &ctx );
-
-        while( ( i = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
-        {
-            sha256_update( &ctx, buf, i );
-        }
-
-        sha256_finish( &ctx, sha256sum );
-
-        for( j = 0; j < 32; j++ )
-        {
-            printf( "%02x", sha256sum[j] );
-        }
-
-        printf( "  %s\n", argv[1] );
-    }
-
-    return( 0 );
+         }
+         printf( "passed.\n" );
+      }
+      printf( "\n" );
+   }
+   else
+   {
+      if (!(f = fopen( argv[1], "rb")))
+      {
+         perror( "fopen" );
+         return( 1 );
+     }
+
+     SHA256Init (&Context);
+     while ((i = fread(buf, 1, sizeof(buf), f)) > 0)
+        SHA256Append (&Context, buf, i );
+     SHA256Finish (&Context, sha256sum);
+
+     for (j = 0; j<32; j++)
+        printf( "%02x", sha256sum[j] );
+
+     printf( "  %s\n", argv[1] );
+   }
+   return (0);
 }
 
 #endif
diff --git a/sha256.h b/sha256.h
index dfb90d9..27cf39a 100644
--- a/sha256.h
+++ b/sha256.h
@@ -1,27 +1,40 @@
 // This file has been copied 1:1 from www.spale.com/download/scrypt/scrypt1.0/sha256.c
 // Besides these 2 comment lines and the correction of uint32 (see below) nothing has been changed.
 
-#ifndef _SHA256_H
-#define _SHA256_H
+#ifndef __SHA256_H__
+#define __SHA256_H__
 
-#ifndef uint8
-#define uint8  unsigned char
-#endif
+typedef unsigned int  uint32;
+typedef unsigned char uint8;
 
-#ifndef uint32
-#define uint32 unsigned int // Hier stand "long int", was für amd64 an sich falsch ist (siehe auch Bemerkung zu SHR in sha256.cpp)
-#endif
+#define SHA256_DIGEST_SIZE 32
 
-typedef struct
-{
-    uint32 total[2];
-    uint32 state[8];
-    uint8 buffer[64];
-} sha256_context;
+#ifdef SHA256_OLD
+   typedef struct
+   {
+      uint32 total[2];
+      uint32 state[8];
+      uint8 buffer[64];
+   } t_SHA256Context, *t_pSHA256Context;
 
-void sha256_starts( sha256_context *ctx );
-void sha256_update( sha256_context *ctx, uint8 *input, uint32 length );
-void sha256_finish( sha256_context *ctx, uint8 digest[32] );
+   void SHA256Init   (t_pSHA256Context pContext);
+   void SHA256Append (t_pSHA256Context pContext, uint8 *input, uint32 length );
+   void SHA256Finish (t_pSHA256Context pContext, uint8 digest[32] );
+#else
+   typedef struct
+   {
+      uint32 state[8];
+      uint32 total[2];
+      size_t buflen;
+      uint32 buffer[32];
+   } t_SHA256Context, *t_pSHA256Context;
 
-#endif /* sha256.h */
+   // Always make sure that these functions are compiled with O3 optimisation or
+   // else, performance is about 5 times worse! See also SHA256ProcessBlock in sha256.cpp.
+   void SHA256Init   (t_pSHA256Context pContext)                                 __attribute__((optimize("-O3")));
+   void SHA256Append (t_pSHA256Context pContext, const void *buffer, size_t len) __attribute__((optimize("-O3")));
+   void SHA256Finish (t_pSHA256Context pContext, void *pDigest)                  __attribute__((optimize("-O3")));
+#endif
+
+#endif
 
diff --git a/threadscan.cpp b/threadscan.cpp
index ee47889..8874c95 100644
--- a/threadscan.cpp
+++ b/threadscan.cpp
@@ -9,7 +9,7 @@
 //  Module:         Thread for scanning the connected devices
 // ****************************************************************************
 
-// Copyright 2008, 2009, 2010, 2011 Guy Voncken
+// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 //
 // This file is part of guymager.
 //
@@ -70,20 +70,14 @@ t_ThreadScanWorker::t_ThreadScanWorker (t_ThreadScan *pThreadScan)
 //  Utility functions used by workers
 // -----------------------------------
 
-static APIRET ThreadScanMarkLocalDevices (const t_pDeviceList pDeviceList)
+static APIRET ThreadScanSetLocal (t_pDevice pDevice)
 {
    QStringList *pLocalDevices;
-   t_pDevice    pDevice;
-   int           i;
 
    CHK_EXIT (CfgGetLocalDevices (&pLocalDevices))
-   for (i=0; i<pDeviceList->count(); i++)
-   {
-      pDevice = pDeviceList->at (i);
-      pDevice->Local = pLocalDevices->contains (pDevice->SerialNumber) ||
-                       pLocalDevices->contains (pDevice->LinuxDevice ) ||
-                       pLocalDevices->contains (pDevice->Model       );
-   }
+   pDevice->Local = pLocalDevices->contains (pDevice->SerialNumber) ||
+                    pLocalDevices->contains (pDevice->LinuxDevice ) ||
+                    pLocalDevices->contains (pDevice->Model       );
    return NO_ERROR;
 }
 
@@ -97,8 +91,8 @@ static APIRET ThreadScanGetAddStateInfo (t_pDevice pDevice)
    Command = CONFIG (CommandGetAddStateInfo);
    if (!Command.isEmpty())
    {
-      Command.replace ("%dev", pDevice->LinuxDevice, Qt::CaseInsensitive);
-   
+      Command.replace ("%dev"  , pDevice->LinuxDevice    , Qt::CaseInsensitive);
+      Command.replace ("%local", pDevice->Local ? "1":"0", Qt::CaseInsensitive);
       rc = QtUtilProcessCommand (Command, StateInfo);
       if (rc == ERROR_QTUTIL_COMMAND_TIMEOUT)
       {
@@ -303,10 +297,10 @@ void t_ThreadScanWorkerParted::SlotRescan (void)
       pDevice = pDeviceList->AppendNew (SerialNumber, pPedDev);
       if (pDevice->LinuxDevice.startsWith ("/dev/fd",  Qt::CaseSensitive)) // Not a good way for checking this, but I don't know how to extract the information from
          pDevice->Removable = true;                                        // PedDevice. BTW, this won't work with other removable devices, for instance memory sticks.
+      CHK_EXIT (ThreadScanSetLocal        (pDevice));
       CHK_EXIT (ThreadScanGetAddStateInfo (pDevice));
    }
    pOwn->pFnLibPartedFreeAll ();
-   CHK_EXIT (ThreadScanMarkLocalDevices (pDeviceList))
 
    emit (SignalScanFinished (pDeviceList));
    CHK_EXIT (poThreadScan->SetDebugMessage ("Leaving SlotRescan (parted)"))
@@ -553,11 +547,12 @@ void t_ThreadScanWorkerHAL::SlotRescan (void)
                                            DEVICE_DEFAULT_SECTOR_SIZE, DEVICE_DEFAULT_SECTOR_SIZE, Size.toULongLong());
          pDevice->Removable = Removable.toBool();
 
-         CHK_EXIT (pDevice->MediaInfo.QueryDevice(QSTR_TO_PSZ(LinuxDevice.toString())))
+         if (CONFIG(QueryDeviceMediaInfo))
+            CHK_EXIT (pDevice->MediaInfo.QueryDevice(QSTR_TO_PSZ(LinuxDevice.toString())))
+         CHK_EXIT (ThreadScanSetLocal        (pDevice));
          CHK_EXIT (ThreadScanGetAddStateInfo (pDevice));
       }
    }
-   CHK_EXIT (ThreadScanMarkLocalDevices (pDeviceList))
    LOG_INFO ("Device scan finished")
 
    CHK_EXIT (poThreadScan->SetDebugMessage ("Leaving SlotRescan (HAL)"))
@@ -816,11 +811,12 @@ void t_ThreadScanWorkerDevKit::SlotRescan (void)
          pDevice = pDeviceList->AppendNew (SerialNumber.toString(), LinuxDevice.toString(), Model,
                                            BlockSize.toULongLong(), BlockSize.toULongLong(), Size.toULongLong());
          pDevice->Removable = Removable.toBool();
-         CHK_EXIT (pDevice->MediaInfo.QueryDevice(QSTR_TO_PSZ(LinuxDevice.toString())))
+         if (CONFIG(QueryDeviceMediaInfo))
+            CHK_EXIT (pDevice->MediaInfo.QueryDevice(QSTR_TO_PSZ(LinuxDevice.toString())))
+         CHK_EXIT (ThreadScanSetLocal        (pDevice));
          CHK_EXIT (ThreadScanGetAddStateInfo (pDevice));
       }
    }
-   CHK_EXIT (ThreadScanMarkLocalDevices (pDeviceList))
    LOG_INFO ("Device scan finished")
 
    CHK_EXIT (poThreadScan->SetDebugMessage ("Leaving SlotRescan (DevKit)"))
diff --git a/threadwrite.cpp b/threadwrite.cpp
index 11917fb..156d237 100644
--- a/threadwrite.cpp
+++ b/threadwrite.cpp
@@ -9,7 +9,7 @@
 //  Module:         Thread for writing data.
 // ****************************************************************************
 
-// Copyright 2008, 2009, 2010, 2011 Guy Voncken
+// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
 //
 // This file is part of guymager.
 //
@@ -216,6 +216,9 @@ class t_OutputFileDD: public t_OutputFile
                LOG_ERROR ("[%s] Opening %s failed, errno=%d '%s'", QSTR_TO_PSZ (poDevice->LinuxDevice), QSTR_TO_PSZ (oFilename), errno, ToolErrorTranslateErrno (errno))
                return ERROR_THREADWRITE_OPEN_FAILED;
             }
+            if (poDevice->Acquisition.Clone) // The file size query from above would not need to be done in that
+               FileSize = poDevice->Size;    // case, however we do it anyway as it is a small access test as well.
+
             oRemainingFileSize = (t_uint64) FileSize;
             if (CONFIG(CalcImageFileMD5))
                CHK (HashMD5Init (&oCurrentHashContextMD5))
diff --git a/util.cpp b/util.cpp
index 2dd893e..3c2f041 100644
--- a/util.cpp
+++ b/util.cpp
@@ -109,6 +109,42 @@ unsigned int UtilGetMaxZcompressedBufferSize (unsigned int UncompressedBufferSiz
 }
 
 
+unsigned long long UtilGetInstalledRAM (void)
+{
+   unsigned long long Bytes;
+   int                Pages, PageSize;
+
+   Pages    = sysconf(_SC_PHYS_PAGES);
+   PageSize = sysconf(_SC_PAGESIZE);
+
+   if ((Pages < 0) || (PageSize < 0))
+   {
+      LOG_ERROR ("Amount of instlled RAM could not be determined, assume 256MB");
+      Bytes = 256*1024*1024;
+   }
+   else
+   {
+      Bytes = (unsigned long long) sysconf(_SC_PHYS_PAGES) * 
+              (unsigned long long) sysconf(_SC_PAGESIZE  );
+   }
+
+   return Bytes;
+}
+
+unsigned int UtilGetNumberOfCPUs (void)
+{
+   int ret;
+
+   ret = sysconf( _SC_NPROCESSORS_ONLN );
+   if (ret<0)
+   {
+      LOG_ERROR ("Number of CPUs could not be determined, assume 1 CPU");
+      ret = 1;
+   }
+   return (unsigned int) ret;
+}
+
+
 APIRET UtilInit (void)
 {   
    int MaxFifoBockSize;
diff --git a/util.h b/util.h
index a2d7f71..ddc197d 100644
--- a/util.h
+++ b/util.h
@@ -32,13 +32,15 @@
 void *UtilMemAlloc (size_t Size, const char *pFile, int Line);
 void  UtilMemFree  (void *pMem , const char *pFile, int Line);
 
+#define UTIL_MEM_ALLOC(Size) UtilMemAlloc (Size, __FILE__, __LINE__)
+#define UTIL_MEM_FREE(pMem)  UtilMemFree  (pMem, __FILE__, __LINE__)
+
 int          UtilCalcDecimals (t_uint64 Value);
 bool         UtilIsZero       (unsigned char *pData, unsigned int DataLen);
 unsigned int UtilGetMaxZcompressedBufferSize (unsigned int UncompressedBufferSize);
 
-#define UTIL_MEM_ALLOC(Size) UtilMemAlloc (Size, __FILE__, __LINE__)
-#define UTIL_MEM_FREE(pMem)  UtilMemFree  (pMem, __FILE__, __LINE__)
-
+unsigned long long UtilGetInstalledRAM (void); // Number of bytes
+unsigned int       UtilGetNumberOfCPUs (void);
 
 APIRET UtilInit   (void);
 APIRET UtilDeInit (void);

-- 
debian-forensics/guymager



More information about the forensics-changes mailing list