mirror of
https://github.com/martijnvanbrummelen/nwipe.git
synced 2026-02-22 06:52:12 +00:00
Compare commits
241 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb595e139c | ||
|
|
08f68f14d9 | ||
|
|
f17845c54b | ||
|
|
230e7f524a | ||
|
|
de077211e6 | ||
|
|
07a7c0ab0c | ||
|
|
2fae6ea5f5 | ||
|
|
d6f7238cb3 | ||
|
|
c007d0f2ab | ||
|
|
161054269c | ||
|
|
dd7ffab816 | ||
|
|
9edebde20d | ||
|
|
807eed0ffc | ||
|
|
78f3a26795 | ||
|
|
dbe7103fe9 | ||
|
|
eef25e829e | ||
|
|
43bfb3a08e | ||
|
|
fd6cca7010 | ||
|
|
1220eca2ef | ||
|
|
32321f49fa | ||
|
|
cca93f845d | ||
|
|
789aa134a0 | ||
|
|
c24e248055 | ||
|
|
3f78d76bac | ||
|
|
626ca3826c | ||
|
|
f61b593093 | ||
|
|
7f39d81548 | ||
|
|
d0a53f57be | ||
|
|
811c36b65a | ||
|
|
2ff23eb02c | ||
|
|
7a4709da55 | ||
|
|
9ee5193673 | ||
|
|
9270eda8d0 | ||
|
|
470672bc3a | ||
|
|
d14c3da26b | ||
|
|
4bf06d136c | ||
|
|
2abe4975f2 | ||
|
|
2a30ae92af | ||
|
|
e77164f710 | ||
|
|
e463b10d28 | ||
|
|
4747ce65c6 | ||
|
|
28a9c70abc | ||
|
|
2ac6ebe7ea | ||
|
|
a70fa15bac | ||
|
|
398b03a11a | ||
|
|
63c64b91e4 | ||
|
|
edfd982037 | ||
|
|
cad05c685a | ||
|
|
499ad925ae | ||
|
|
2c17e32189 | ||
|
|
68561873ba | ||
|
|
a30f92425c | ||
|
|
cb7d3d1664 | ||
|
|
869804f6c1 | ||
|
|
61cca3141e | ||
|
|
07b83f053b | ||
|
|
fd3bbd8523 | ||
|
|
1b37bcef84 | ||
|
|
f3179cf748 | ||
|
|
fba63312ad | ||
|
|
1b9a376186 | ||
|
|
eaa7603aaf | ||
|
|
26ae763379 | ||
|
|
95021ef0c3 | ||
|
|
8ce7b077bf | ||
|
|
603716e990 | ||
|
|
7fb2a77c7a | ||
|
|
28068ebf97 | ||
|
|
539a023fd7 | ||
|
|
04dae6da32 | ||
|
|
dcef86fb0b | ||
|
|
193cc8f0b2 | ||
|
|
1ee1bb1966 | ||
|
|
d9785d2b84 | ||
|
|
c02dbe42ce | ||
|
|
7ce28ce61a | ||
|
|
7d2517a120 | ||
|
|
725c79b9d0 | ||
|
|
ab9d269bb1 | ||
|
|
508a6d2a62 | ||
|
|
0bb9ee33c9 | ||
|
|
f12ee921b8 | ||
|
|
53d91f4b8b | ||
|
|
de887ea6ee | ||
|
|
b6f97454f1 | ||
|
|
6a92755cf2 | ||
|
|
68a6002ff1 | ||
|
|
47112c4de2 | ||
|
|
97efd12b93 | ||
|
|
3bc3de37ae | ||
|
|
525cf037c5 | ||
|
|
f764c39390 | ||
|
|
c6ff341f7e | ||
|
|
948368bc28 | ||
|
|
59d73107f6 | ||
|
|
8124e6b3d5 | ||
|
|
c1e943d283 | ||
|
|
8124d2d493 | ||
|
|
7c9939e228 | ||
|
|
4675a17693 | ||
|
|
bbcb4fc219 | ||
|
|
65a3a45a38 | ||
|
|
f1fe7d6bd7 | ||
|
|
50951dff03 | ||
|
|
2d730eac2e | ||
|
|
16b87cc2bd | ||
|
|
ea1c2019cd | ||
|
|
c5b4e58cee | ||
|
|
8a46658820 | ||
|
|
1e50f2fd2c | ||
|
|
60d38a80e4 | ||
|
|
c72f740587 | ||
|
|
ba4c4c51f1 | ||
|
|
86d71d0858 | ||
|
|
bb0cd2258d | ||
|
|
4c703a6922 | ||
|
|
9f92ec1b29 | ||
|
|
17a391f971 | ||
|
|
b40563ab22 | ||
|
|
7fc4325d69 | ||
|
|
c137736997 | ||
|
|
1a3e7eb23e | ||
|
|
e6034cf94e | ||
|
|
ce628e5c17 | ||
|
|
3dcc40c0e7 | ||
|
|
1582f8c224 | ||
|
|
a3fd0b71ca | ||
|
|
580429a371 | ||
|
|
b46575cd63 | ||
|
|
0d403a20a3 | ||
|
|
baefd77605 | ||
|
|
9f8aecaa52 | ||
|
|
0948596559 | ||
|
|
2630edbea1 | ||
|
|
e74ae252ef | ||
|
|
2ebea57008 | ||
|
|
247cf3031b | ||
|
|
a05784f05a | ||
|
|
6f453967f6 | ||
|
|
0649f1c606 | ||
|
|
174072db2e | ||
|
|
60385f479a | ||
|
|
49d82eebc9 | ||
|
|
d7b1fdf2ce | ||
|
|
21ef97e355 | ||
|
|
447c4eddf7 | ||
|
|
3a9ff16d29 | ||
|
|
d981159f04 | ||
|
|
3d2ba87967 | ||
|
|
e7fca73970 | ||
|
|
dfa78567e0 | ||
|
|
30997876a5 | ||
|
|
0c41d895e2 | ||
|
|
776717a729 | ||
|
|
a1e607dc02 | ||
|
|
0b720b155c | ||
|
|
4fc1806880 | ||
|
|
bbfaa0e9f7 | ||
|
|
4f5c15ffad | ||
|
|
dbde867974 | ||
|
|
a51a9b3e2a | ||
|
|
3d5fdd3f11 | ||
|
|
5051e5c7bf | ||
|
|
5d8c0cc4bf | ||
|
|
c79c8ad8f7 | ||
|
|
79cedf47fc | ||
|
|
08cba2ee5e | ||
|
|
4368092d11 | ||
|
|
ac96c51120 | ||
|
|
c4490a89d1 | ||
|
|
87d25cf752 | ||
|
|
c3cd5011a2 | ||
|
|
1b3d03faad | ||
|
|
f258872c67 | ||
|
|
d231c863f7 | ||
|
|
b35400b22a | ||
|
|
c52dfa3d8f | ||
|
|
e6a9944a7a | ||
|
|
9c0dd6a25a | ||
|
|
67ca3b260d | ||
|
|
c97d1c9166 | ||
|
|
4b6399a93f | ||
|
|
518b8b536a | ||
|
|
b79eea6c9f | ||
|
|
88cec08854 | ||
|
|
dc6d76176a | ||
|
|
3eb5a43a32 | ||
|
|
8abab96a3e | ||
|
|
7ccb68675b | ||
|
|
c7d17df7f8 | ||
|
|
ea9d76132e | ||
|
|
bba050fa71 | ||
|
|
00e2053ab4 | ||
|
|
ef84c65846 | ||
|
|
09af2bc5a6 | ||
|
|
2747ab5d4f | ||
|
|
a2d6735b89 | ||
|
|
e4ecd6a68e | ||
|
|
6f7ca938f4 | ||
|
|
ecfc252015 | ||
|
|
40f1e31225 | ||
|
|
3b952d3f92 | ||
|
|
09e41d573f | ||
|
|
8b827f9ea0 | ||
|
|
c57e04005e | ||
|
|
04c409a665 | ||
|
|
c5f9c1d6e9 | ||
|
|
d9fed5bcc6 | ||
|
|
84048ba58b | ||
|
|
f0b61a0bc1 | ||
|
|
eda930f06d | ||
|
|
2320015841 | ||
|
|
581e83e615 | ||
|
|
eef866fa54 | ||
|
|
a29cc3b543 | ||
|
|
630837b207 | ||
|
|
b5eb549c59 | ||
|
|
142a140ddf | ||
|
|
ac6f14d86d | ||
|
|
e7797bf874 | ||
|
|
40fdaf49a3 | ||
|
|
0c0e3f2930 | ||
|
|
d5286a1965 | ||
|
|
cb129ffbc2 | ||
|
|
8c7b1839f4 | ||
|
|
ac26aad3ac | ||
|
|
b41a84f5af | ||
|
|
ed478f6dc0 | ||
|
|
602b835aef | ||
|
|
c2ab19a109 | ||
|
|
9feea8b3cf | ||
|
|
1b6ba8e8a2 | ||
|
|
b6d5388759 | ||
|
|
24fd407b43 | ||
|
|
53b5c020e0 | ||
|
|
87f4b48705 | ||
|
|
099d380f3c | ||
|
|
f3ace2aa7c | ||
|
|
f6483ca055 | ||
|
|
0a5dbeb5a4 | ||
|
|
cf57297953 |
4
.github/workflows/ci_formatting.yml
vendored
4
.github/workflows/ci_formatting.yml
vendored
@@ -8,11 +8,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
- name: updating available system dependencies
|
||||
run: sudo apt-get update
|
||||
- name: installing system dependencies
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode clang-format-7
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev libconfig-dev libconfig++-dev dmidecode clang-format
|
||||
- name: creating autoconf files
|
||||
run: ./autogen.sh
|
||||
- name: configuring
|
||||
|
||||
21
.github/workflows/ci_ubuntu_18.04.yml
vendored
21
.github/workflows/ci_ubuntu_18.04.yml
vendored
@@ -1,21 +0,0 @@
|
||||
name: ci_ubuntu_18.04
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: updating available system dependencies
|
||||
run: sudo apt-get update
|
||||
- name: installing system dependencies
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode
|
||||
- name: creating autoconf files
|
||||
run: ./autogen.sh
|
||||
- name: configuring
|
||||
run: ./configure CFLAGS='-O0 -g -Wall -Wextra'
|
||||
- name: compiling
|
||||
run: make
|
||||
4
.github/workflows/ci_ubuntu_latest.yml
vendored
4
.github/workflows/ci_ubuntu_latest.yml
vendored
@@ -8,11 +8,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
- name: updating available system dependencies
|
||||
run: sudo apt-get update
|
||||
- name: installing system dependencies
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev libconfig-dev libconfig++-dev dmidecode
|
||||
- name: creating autoconf files
|
||||
run: ./autogen.sh
|
||||
- name: configuring
|
||||
|
||||
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,6 +1,38 @@
|
||||
RELEASE NOTES
|
||||
=============
|
||||
|
||||
v0.36
|
||||
-----------------------
|
||||
- Added the abbreviation MMC for mmcblk devices such as SD and microSD cards and some low budget laptops. #526
|
||||
- Fixed some serial numbers that were displaying garbage. #527
|
||||
- Fixed auto power off and nowait when the screen has been blanked by the user. #529
|
||||
- Fixed nwipe not auto exiting on completion when in non gui mode. #531
|
||||
- Fixed smart page titles so they have a consistent format with page 1 in the PDF report. #532
|
||||
- Fixed some of the config help messages that displayed incorrect information. #533
|
||||
- Inserted a space between temperature and model. #534
|
||||
- Fixed incorrect footer on return to organisation/customer preview screen. #535
|
||||
- Made footer completion message more informative. #538
|
||||
- Fixed hidden sector detection for devices with logical/physical size of 4096/4096. #543 #546
|
||||
- Fixed some strcpy compiler warnings. #548
|
||||
|
||||
|
||||
v0.35
|
||||
-----------------------
|
||||
- Nwipe will now optionally create a multi-page PDF certificate that shows details of a specific discs erasure. The first page forms the certificate of erasure and subsequent pages show the drives smart data. Two related options have been added to nwipe's command line options -P, --PDFreportpath=PATH Path to write PDF reports to. Default is "." If set to "noPDF" no PDF reports are written. From the drive selection screen you can now press 'c' for config. This takes you to the configuration screen where you can select various PDF certificate related options such as enabling PDF, entering customer or company data for entry onto the certificate and enabling a preview of customer/company info prior to the drive selection screen starting.
|
||||
- Nwipe now supports HPA/DCO detection, aka hidden sector detection. This is where the drive has been configured to report a smaller size to the operating system (O.S.) than it actually is. The HPA/DCO status is reported on the main drive selection screen as [HS? N/A] for drive that does not support HPA/DCO such as NvMe. [HS? YES] for a drive that is reporting a size smaller than it actually is, i.e has hidden sectors and [HS? NO] where the drive is reporting it's actual size correctly to the O.S. And finally [HS? ???] where nwipe cannot determine the HPA/DCO status as the drive is not responding to the ATA commands used to detect HPA/DCO. This might be because the drive does not support HPA/DCO or the interface adapter does not support ATA passthrough as is the case with a lot of the USB adapters on the market, but not all USB adapters. Nwipe does not currently allow removal of the HPA/DCO so you will still need to use hdparm to reset the drive so it reports its correct size before using nwipe to wipe the drive. HPA/DCO reset may be added in the next version. Thanks to @mdcato for the help testing the code and HPA/DCO results as displayed in the report.
|
||||
- This bug only applies to ones wipe and one or zero's verification. A very rare occurrence of a incorrect percentage on completion. The actual wipe was completed correctly it was just that the percentage calculation was wrong. #459
|
||||
- Nwipe now supports a configuration file /etc/nwipe/nwipe.conf. Currently it supports settings related to the PDF certificate but more options will be added in the future.
|
||||
- If you are running nwipe within the KDE konsole terminal and you resize the window by pulling on the corners, occasionally nwipe will exit with the error message: "GUI.c,nwipe_gui_select(), loop runaway, did you close the terminal without exiting nwipe? Initiating shutdown now" The loop runaway detection has been made less sensitive, i.e 32 iterations per second of the GUI update can now be completed before a loop runaway is detected. previously it was 8. In practise when sizing the konsole window, anywhere between 1 and 17 iterations will occur.#467
|
||||
- Nwipe now provides better temperature support for SAS drives. Thanks to @ggruber for all the code and testing he contributed.
|
||||
- Disc sizes are now shown differently to provide more information about their size. For instance a 1.2TB drive was shown as 1TB, now it is shown as 1200GB. Thanks to @ggruber for his code contribution.
|
||||
- Interface/bustype type was reported as UNK fo SAS drives, now reported correctly as SAS. Thanks to @ggruber for his code contribution.
|
||||
- Interface/bustype type has been enhanced to show SAS-SSD when a SSD drive is present. Thanks to @ggruber for his code contribution.
|
||||
- Nwipe's temperature retrieval code has been placed in it's own thread. This was done because it was found that any delays in obtaining the temperature resulted in a momentary freeze in the GUI wipe screen updating it's stats. This wasn't noticable if you were erasing a small number of drives but become apparent when wiping ten or twenty drives simultaneously.
|
||||
v0.34
|
||||
-----------------------
|
||||
- Fix a compiler warning -Wformat-zero-length string
|
||||
|
||||
|
||||
v0.33
|
||||
-----------------------
|
||||
- Fixes a slight screen corruption on 80 column display. When highlighting the verify ones option the first two digits of DoD 5220.20-M disappear. This patch fixes that issue.@PartialVolume #348
|
||||
|
||||
38
README.md
38
README.md
@@ -1,16 +1,22 @@
|
||||
# nwipe
|
||||

|
||||

|
||||
[](https://github.com/martijnvanbrummelen/nwipe/releases/)
|
||||
|
||||
nwipe is a fork of the dwipe command originally used by Darik's Boot and Nuke (DBAN). nwipe was created out of a need to run the DBAN dwipe command outside of DBAN, in order to allow its use with any host distribution, thus giving better hardware support.
|
||||
|
||||
nwipe is a program that will securely erase the entire contents of disks. It can wipe a single drive or multiple disks simultaneously. It can operate as both a command line tool without a GUI or with a ncurses GUI as shown in the example below:
|
||||
|
||||
> **Warning**
|
||||
> For some of nwipes features such as smart data in the PDF certificate, HPA/DCO detection and other uses, nwipe utilises smartmontools and hdparm. Therefore both hdparm & smartmontools are a mandatory requirement if you want all of nwipes features to be fully available. If you do not install smartmontools and hdparm, nwipe will provide a warning in the log that these programs cannot be found but will still run but many important features may not work as they should do.
|
||||
|
||||

|
||||
|
||||
<i>GIF showing six drives being simultaneously erased. It skips to the completion of all six wipes and shows five drives that were successfully erased and one drive that failed due to an I/O error. The drive that failed would then normally be physically destroyed. The five drives that were successfully wiped with zero errors or failures can then be redeployed.</i>
|
||||
<i>The video above shows six drives being simultaneously erased. It skips to the completion of all six wipes and shows five drives that were successfully erased and one drive that failed due to an I/O error. The drive that failed would then normally be physically destroyed. The five drives that were successfully wiped with zero errors or failures can then be redeployed.</i>
|
||||
|
||||

|
||||
<i>The snapshot above shows nwipe's three page PDF certificate, drive identifiable information such as serial numbers have been anonymised using the nwipe command line option -q</i>
|
||||
|
||||
## Erasure methods
|
||||
The user can select from a variety of recognised secure erase methods which include:
|
||||
|
||||
* Fill With Zeros - Fills the device with zeros (0x00), one round only.
|
||||
@@ -43,6 +49,11 @@ For a development setup, see the [Hacking section](#hacking) below. For a bootab
|
||||
* ncurses
|
||||
* pthreads
|
||||
* parted
|
||||
* libconfig
|
||||
|
||||
`nwipe` also requires the following program to be installed, it will abort with a warning if not found:
|
||||
|
||||
* hdparm (as of current master and v0.35+)
|
||||
|
||||
and optionally, but recommended, the following programs:
|
||||
|
||||
@@ -62,9 +73,12 @@ sudo apt install \
|
||||
libncurses5-dev \
|
||||
autotools-dev \
|
||||
libparted-dev \
|
||||
libconfig-dev \
|
||||
libconfig++-dev \
|
||||
dmidecode \
|
||||
coreutils \
|
||||
smartmontools
|
||||
smartmontools \
|
||||
hdparm
|
||||
```
|
||||
|
||||
### Fedora prerequisites
|
||||
@@ -76,19 +90,25 @@ dnf groupinstall "Development Tools"
|
||||
dnf groupinstall "C Development Tools and Libraries"
|
||||
yum install ncurses-devel
|
||||
yum install parted-devel
|
||||
yum install libconfig-devel
|
||||
yum install libconfig++-devel
|
||||
yum install dmidecode
|
||||
yum install coreutils
|
||||
yum install smartmontools
|
||||
yum install hdparm
|
||||
```
|
||||
Note. The following programs are optionally installed although recommended. 1. dmidecode 2. readlink 3. smartmontools.
|
||||
|
||||
#### dmidecode
|
||||
#### hdparm [REQUIRED]
|
||||
hdparm provides some of the information regarding disk size in sectors as related to the host protected area (HPA) and device configuration overlay (DCO). We do however have our own function that directly access the DCO to obtain the 'real max sectors' so reliance on hdparm may be removed at a future date.
|
||||
|
||||
#### dmidecode [RECOMMENDED]
|
||||
dmidecode provides SMBIOS/DMI host data to stdout or the log file. If you don't install it you won't see the SMBIOS/DMI host data at the beginning of nwipes log.
|
||||
|
||||
#### coreutils (provides readlink)
|
||||
#### coreutils (provides readlink) [RECOMMENDED]
|
||||
readlink determines the bus type, i.e. ATA, USB etc. Without it the --nousb option won't work and bus type information will be missing from nwipes selection and wipe windows. The coreutils package is often automatically installed as default in most if not all distros.
|
||||
|
||||
#### smartmontools
|
||||
#### smartmontools [REQUIRED]
|
||||
smartmontools obtains serial number information for supported USB to IDE/SATA adapters. Without it, drives plugged into USB ports will not show serial number information.
|
||||
|
||||
If you want a quick and easy way to keep your copy of nwipe running the latest master release of nwipe see the [automating the download and compilation](#automating-the-download-and-compilation-process-for-debian-based-distros) section.
|
||||
@@ -160,15 +180,14 @@ cd ~/nwipe_master/nwipe/src
|
||||
|
||||
Note the ./, that means only look in the current directory for nwipe. if you forgot to type ./ the computer would run the older repository version of nwipe.
|
||||
|
||||
Once you have copied the script below into a file called buildnwipe, you need to give the file execute permissions `chmod +x buildnwipe` before you can run it. [Download script](
|
||||
https://drive.google.com/file/d/1BsQDlMqtEycAgfk9FpG1sxv3jFz5dzNO/view?usp=sharing)
|
||||
Once you have copied the script below into a file called buildnwipe, you need to give the file execute permissions `chmod +x buildnwipe` before you can run it.
|
||||
```
|
||||
#!/bin/bash
|
||||
cd "$HOME"
|
||||
nwipe_directory="nwipe_master"
|
||||
mkdir $nwipe_directory
|
||||
cd $nwipe_directory
|
||||
sudo apt install build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode readlink smartmontools git
|
||||
sudo apt install build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev libconfig-dev libconfig++-dev dmidecode readlink smartmontools git
|
||||
rm -rf nwipe
|
||||
git clone https://github.com/martijnvanbrummelen/nwipe.git
|
||||
cd "nwipe"
|
||||
@@ -192,6 +211,7 @@ And in addition checkout the following distros that all include nwipe:
|
||||
- [partedmagic](https://partedmagic.com)
|
||||
- [SystemRescueCD](https://www.system-rescue.org)
|
||||
- [gparted live](https://sourceforge.net/projects/gparted/files/gparted-live-testing/1.2.0-2/)
|
||||
- [grml](https://grml.org/)
|
||||
|
||||
Know of other distros that include nwipe? Then please let us know or issue a PR on this README.md. Thanks.
|
||||
|
||||
|
||||
28
configure.ac
28
configure.ac
@@ -1,10 +1,11 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.64])
|
||||
AC_INIT([nwipe], [0.33], [git@brumit.nl])
|
||||
AC_PREREQ([2.63])
|
||||
AC_INIT([nwipe],[0.36],[git@brumit.nl])
|
||||
AM_INIT_AUTOMAKE(foreign subdir-objects)
|
||||
AC_OUTPUT(Makefile src/Makefile man/Makefile)
|
||||
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile])
|
||||
AC_OUTPUT
|
||||
AC_CONFIG_SRCDIR([src/nwipe.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
@@ -49,13 +50,30 @@ PKG_CHECK_MODULES(
|
||||
)]
|
||||
)
|
||||
|
||||
PKG_CHECK_MODULES(
|
||||
[LIBCONFIG],
|
||||
[libconfig],
|
||||
[
|
||||
CFLAGS="${CFLAGS} ${LIBCONFIG_CFLAGS}"
|
||||
LIBS="${LIBS} ${LIBCONFIG_LIBS}"
|
||||
],
|
||||
[AC_CHECK_LIB([libconfig], [main], [
|
||||
LIBS="-llibconfig $LIBS"
|
||||
AC_CHECK_HEADERS(libconfig.h,, [
|
||||
AC_CHECK_HEADERS(libconfig.h, [
|
||||
AC_DEFINE([LIBCONFIG_IN_SUBDIR], [libconfig/], [Look for libconfig headers in subdir])
|
||||
], [AC_MSG_ERROR([libconfig headers not found])])
|
||||
])
|
||||
], [AC_MSG_ERROR([libconfig library not found])])]
|
||||
)
|
||||
|
||||
AC_CHECK_LIB([intl], [libintl_dgettext]) # needed to statically link libparted, but not given in its pkgconfig file
|
||||
AC_CHECK_LIB([uuid], [uuid_generate]) # needed to statically link libparted, but not given in its pkgconfig file
|
||||
PKG_CHECK_MODULES([PARTED], [libparted])
|
||||
PKG_CHECK_MODULES([PARTED], [libparted], [libconfig])
|
||||
AC_CHECK_LIB([pthread], [main], ,[AC_MSG_ERROR([pthread development library not found])])
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([fcntl.h inttypes.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/file.h sys/ioctl.h unistd.h])
|
||||
AC_CHECK_HEADERS([libconfig.h fcntl.h inttypes.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/file.h sys/ioctl.h unistd.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH NWIPE "1" "March 2022" "nwipe version 0.33" "User Commands"
|
||||
.TH NWIPE "20" "February 2024" "nwipe version 0.36" "User Commands"
|
||||
.SH NAME
|
||||
nwipe \- securely erase disks
|
||||
.SH SYNOPSIS
|
||||
@@ -35,7 +35,7 @@ devices immediately. If devices have been specified, starts wiping only
|
||||
those specified devices immediately.
|
||||
.TP
|
||||
\fB\-\-autopoweroff\fR
|
||||
Power off system on completion of wipe delayed for for one minute. During
|
||||
Power off system on completion of wipe delayed for one minute. During
|
||||
this one minute delay you can abort the shutdown by typing sudo shutdown -c
|
||||
.TP
|
||||
\fB\-\-sync\fR=\fINUM\fR
|
||||
@@ -111,6 +111,11 @@ is5enh \- HMG IS5 enhanced
|
||||
\fB\-l\fR, \fB\-\-logfile\fR=\fIFILE\fR
|
||||
Filename to log to. Default is STDOUT
|
||||
.TP
|
||||
\fB\-P\fR, \fB\-\-PDFreportpath\fR=\fIDIR\fR
|
||||
Directory to write the PDF nwipe reports/certificates to.
|
||||
Defaults to ".".
|
||||
If \fIDIR\fR is set to \fInoPDF\fR no report PDF files are written.
|
||||
.TP
|
||||
\fB\-p\fR, \fB\-\-prng\fR=\fIMETHOD\fR
|
||||
PRNG option (mersenne|twister|isaac|isaac64)
|
||||
.TP
|
||||
|
||||
@@ -6,5 +6,5 @@ AM_LDFLAGS =
|
||||
# this lists the binaries to produce, the (non-PHONY, binary) targets in
|
||||
# the previous manual Makefile
|
||||
bin_PROGRAMS = nwipe
|
||||
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c
|
||||
nwipe_LDADD = $(PARTED_LIBS)
|
||||
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.c
|
||||
nwipe_LDADD = $(PARTED_LIBS) $(LIBCONFIG)
|
||||
|
||||
4057
src/PDFGen/pdfgen.c
Normal file
4057
src/PDFGen/pdfgen.c
Normal file
File diff suppressed because it is too large
Load Diff
773
src/PDFGen/pdfgen.h
Normal file
773
src/PDFGen/pdfgen.h
Normal file
@@ -0,0 +1,773 @@
|
||||
/**
|
||||
* Simple engine for creating PDF files.
|
||||
* It supports text, shapes, images etc...
|
||||
* Capable of handling millions of objects without too much performance
|
||||
* penalty.
|
||||
* Public domain license - no warrenty implied; use at your own risk.
|
||||
* @file pdfgen.h
|
||||
*/
|
||||
#ifndef PDFGEN_H
|
||||
#define PDFGEN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* @defgroup subsystem Simple PDF Generation
|
||||
* Allows for quick generation of simple PDF documents.
|
||||
* This is useful for producing easily printed output from C code, where
|
||||
* advanced formatting is not required
|
||||
*
|
||||
* Note: All coordinates/sizes are in points (1/72 of an inch).
|
||||
* All coordinates are based on 0,0 being the bottom left of the page.
|
||||
* All colours are specified as a packed 32-bit value - see @ref PDF_RGB.
|
||||
* Text strings are interpreted as UTF-8 encoded, but only a small subset of
|
||||
* characters beyond 7-bit ascii are supported (see @ref pdf_add_text for
|
||||
* details).
|
||||
*
|
||||
* @par PDF library example:
|
||||
* @code
|
||||
#include "pdfgen.h"
|
||||
...
|
||||
struct pdf_info info = {
|
||||
.creator = "My software",
|
||||
.producer = "My software",
|
||||
.title = "My document",
|
||||
.author = "My name",
|
||||
.subject = "My subject",
|
||||
.date = "Today"
|
||||
};
|
||||
struct pdf_doc *pdf = pdf_create(PDF_A4_WIDTH, PDF_A4_HEIGHT, &info);
|
||||
pdf_set_font(pdf, "Times-Roman");
|
||||
pdf_append_page(pdf);
|
||||
pdf_add_text(pdf, NULL, "This is text", 12, 50, 20, PDF_BLACK);
|
||||
pdf_add_line(pdf, NULL, 50, 24, 150, 24);
|
||||
pdf_save(pdf, "output.pdf");
|
||||
pdf_destroy(pdf);
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
struct pdf_doc;
|
||||
struct pdf_object;
|
||||
|
||||
/**
|
||||
* pdf_info describes the metadata to be inserted into the
|
||||
* header of the output PDF
|
||||
*/
|
||||
struct pdf_info {
|
||||
char creator[64]; //!< Software used to create the PDF
|
||||
char producer[64]; //!< Software used to create the PDF
|
||||
char title[64]; //!< The title of the PDF (typically displayed in the
|
||||
//!< window bar when viewing)
|
||||
char author[64]; //!< Who created the PDF
|
||||
char subject[64]; //!< What is the PDF about
|
||||
char date[64]; //!< The date the PDF was created
|
||||
};
|
||||
|
||||
/**
|
||||
* Enum that declares the different image file formats we currently support.
|
||||
* Each value has a corresponding header struct used within
|
||||
* the format_specific_img_info union.
|
||||
*/
|
||||
enum {
|
||||
IMAGE_PNG,
|
||||
IMAGE_JPG,
|
||||
IMAGE_PPM,
|
||||
IMAGE_BMP,
|
||||
|
||||
IMAGE_UNKNOWN
|
||||
};
|
||||
|
||||
/**
|
||||
* Since we're casting random areas of memory to these, make sure
|
||||
* they're packed properly to match the image format requirements
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/**
|
||||
* Information about color type of PNG format
|
||||
* As defined by https://www.w3.org/TR/2003/REC-PNG-20031110/#6Colour-values
|
||||
*/
|
||||
enum /* png colortype */ {
|
||||
// Greyscale
|
||||
PNG_COLOR_GREYSCALE = 0,
|
||||
// Truecolour
|
||||
PNG_COLOR_RGB = 2,
|
||||
// Indexed-colour
|
||||
PNG_COLOR_INDEXED = 3,
|
||||
// Greyscale with alpha
|
||||
PNG_COLOR_GREYSCALE_A = 4,
|
||||
// Truecolour with alpha
|
||||
PNG_COLOR_RGBA = 6,
|
||||
|
||||
PNG_COLOR_INVALID = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* png_header describes the header information extracted from .PNG files
|
||||
*/
|
||||
struct png_header {
|
||||
uint32_t width; //!< Width in pixels
|
||||
uint32_t height; //!< Height in pixels
|
||||
uint8_t bitDepth; //!< Bit Depth
|
||||
uint8_t colorType; //!< Color type - see PNG_COLOR_xx
|
||||
uint8_t deflate; //!< Deflate setting
|
||||
uint8_t filtering; //!< Filtering
|
||||
uint8_t interlace; //!< Interlacing
|
||||
};
|
||||
|
||||
/**
|
||||
* bmp_header describes the header information extracted from .BMP files
|
||||
*/
|
||||
struct bmp_header {
|
||||
uint32_t bfSize; //!< size of BMP in bytes
|
||||
uint16_t bfReserved1; //!< ignore!
|
||||
uint16_t bfReserved2; //!< ignore!
|
||||
uint32_t bfOffBits; //!< Offset to BMP data
|
||||
uint32_t biSize; //!< Size of this header (40)
|
||||
int32_t biWidth; //!< Width in pixels
|
||||
int32_t biHeight; //!< Height in pixels
|
||||
uint16_t biPlanes; //!< Number of colour planes - must be 1
|
||||
uint16_t biBitCount; //!< Bits Per Pixel
|
||||
uint32_t biCompression; //!< Compression Method
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
* jpeg_header describes the header information extracted from .JPG files
|
||||
*/
|
||||
struct jpeg_header {
|
||||
int ncolours; //!< Number of colours
|
||||
};
|
||||
|
||||
/**
|
||||
* PPM color spaces
|
||||
*/
|
||||
enum {
|
||||
PPM_BINARY_COLOR_RGB, //!< binary ppm with RGB colors (magic number P5)
|
||||
PPM_BINARY_COLOR_GRAY, //!< binary ppm with grayscale colors (magic number
|
||||
//!< P6)
|
||||
};
|
||||
|
||||
/**
|
||||
* ppm_header describes the header information extracted from .PPM files
|
||||
*/
|
||||
struct ppm_header {
|
||||
size_t size; //!< Indicate the size of the image data
|
||||
size_t data_begin_pos; //!< position in the data where the image starts
|
||||
int color_space; //!< PPM color space
|
||||
};
|
||||
|
||||
/**
|
||||
* pdf_img_info describes the metadata for an arbitrary image
|
||||
*/
|
||||
struct pdf_img_info {
|
||||
int image_format; //!< Indicates the image format (IMAGE_PNG, ...)
|
||||
uint32_t width; //!< Width in pixels
|
||||
uint32_t height; //!< Height in pixels
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
// Doxygen doesn't like anonymous unions
|
||||
//!< Image specific details
|
||||
union {
|
||||
struct bmp_header bmp; //!< BMP header info
|
||||
struct jpeg_header jpeg; //!< JPEG header info
|
||||
struct png_header png; //!< PNG header info
|
||||
struct ppm_header ppm; //!< PPM header info
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* pdf_path_operation holds information about a path
|
||||
* drawing operation.
|
||||
* See PDF reference for detailed usage.
|
||||
*/
|
||||
struct pdf_path_operation {
|
||||
char op; /*!< Operation command. Possible operators are: m = move to, l =
|
||||
line to, c = cubic bezier curve with two control points, v =
|
||||
cubic bezier curve with one control point fixed at first
|
||||
point, y = cubic bezier curve with one control point fixed
|
||||
at second point, h = close path */
|
||||
float x1; /*!< X offset of the first point. Used with: m, l, c, v, y */
|
||||
float y1; /*!< Y offset of the first point. Used with: m, l, c, v, y */
|
||||
float x2; /*!< X offset of the second point. Used with: c, v, y */
|
||||
float y2; /*!< Y offset of the second point. Used with: c, v, y */
|
||||
float x3; /*!< X offset of the third point. Used with: c */
|
||||
float y3; /*!< Y offset of the third point. Used with: c */
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a value in inches into a number of points.
|
||||
* @param inch inches value to convert to points
|
||||
*/
|
||||
#define PDF_INCH_TO_POINT(inch) ((float)((inch)*72.0f))
|
||||
|
||||
/**
|
||||
* Convert a value in milli-meters into a number of points.
|
||||
* @param mm millimeter value to convert to points
|
||||
*/
|
||||
#define PDF_MM_TO_POINT(mm) ((float)((mm)*72.0f / 25.4f))
|
||||
|
||||
/*! Point width of a standard US-Letter page */
|
||||
#define PDF_LETTER_WIDTH PDF_INCH_TO_POINT(8.5f)
|
||||
|
||||
/*! Point height of a standard US-Letter page */
|
||||
#define PDF_LETTER_HEIGHT PDF_INCH_TO_POINT(11.0f)
|
||||
|
||||
/*! Point width of a standard A4 page */
|
||||
#define PDF_A4_WIDTH PDF_MM_TO_POINT(210.0f)
|
||||
|
||||
/*! Point height of a standard A4 page */
|
||||
#define PDF_A4_HEIGHT PDF_MM_TO_POINT(297.0f)
|
||||
|
||||
/*! Point width of a standard A3 page */
|
||||
#define PDF_A3_WIDTH PDF_MM_TO_POINT(297.0f)
|
||||
|
||||
/*! Point height of a standard A3 page */
|
||||
#define PDF_A3_HEIGHT PDF_MM_TO_POINT(420.0f)
|
||||
|
||||
/**
|
||||
* Convert three 8-bit RGB values into a single packed 32-bit
|
||||
* colour. These 32-bit colours are used by various functions
|
||||
* in PDFGen
|
||||
*/
|
||||
#define PDF_RGB(r, g, b) \
|
||||
(uint32_t)((((r)&0xff) << 16) | (((g)&0xff) << 8) | (((b)&0xff)))
|
||||
|
||||
/**
|
||||
* Convert four 8-bit ARGB values into a single packed 32-bit
|
||||
* colour. These 32-bit colours are used by various functions
|
||||
* in PDFGen. Alpha values range from 0 (opaque) to 0xff
|
||||
* (transparent)
|
||||
*/
|
||||
#define PDF_ARGB(a, r, g, b) \
|
||||
(uint32_t)(((uint32_t)((a)&0xff) << 24) | (((r)&0xff) << 16) | \
|
||||
(((g)&0xff) << 8) | (((b)&0xff)))
|
||||
|
||||
/*! Utility macro to provide bright red */
|
||||
#define PDF_RED PDF_RGB(0xff, 0, 0)
|
||||
|
||||
/*! Utility macro to provide bright green */
|
||||
#define PDF_GREEN PDF_RGB(0, 0xff, 0)
|
||||
|
||||
/*! Utility macro to provide bright blue */
|
||||
#define PDF_BLUE PDF_RGB(0, 0, 0xff)
|
||||
|
||||
/*! Utility macro to provide black */
|
||||
#define PDF_BLACK PDF_RGB(0, 0, 0)
|
||||
|
||||
/*! Utility macro to provide white */
|
||||
#define PDF_WHITE PDF_RGB(0xff, 0xff, 0xff)
|
||||
|
||||
/*!
|
||||
* Utility macro to provide a transparent colour
|
||||
* This is used in some places for 'fill' colours, where no fill is required
|
||||
*/
|
||||
#define PDF_TRANSPARENT (uint32_t)(0xffu << 24)
|
||||
|
||||
/**
|
||||
* Different alignment options for rendering text
|
||||
*/
|
||||
enum {
|
||||
PDF_ALIGN_LEFT, //!< Align text to the left
|
||||
PDF_ALIGN_RIGHT, //!< Align text to the right
|
||||
PDF_ALIGN_CENTER, //!< Align text in the center
|
||||
PDF_ALIGN_JUSTIFY, //!< Align text in the center, with padding to fill the
|
||||
//!< available space
|
||||
PDF_ALIGN_JUSTIFY_ALL, //!< Like PDF_ALIGN_JUSTIFY, except even short
|
||||
//!< lines will be fully justified
|
||||
PDF_ALIGN_NO_WRITE, //!< Fake alignment for only checking wrap height with
|
||||
//!< no writes
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new PDF object, with the given page
|
||||
* width/height
|
||||
* @param width Width of the page
|
||||
* @param height Height of the page
|
||||
* @param info Optional information to be put into the PDF header
|
||||
* @return PDF document object, or NULL on failure
|
||||
*/
|
||||
struct pdf_doc *pdf_create(float width, float height,
|
||||
const struct pdf_info *info);
|
||||
|
||||
/**
|
||||
* Destroy the pdf object, and all of its associated memory
|
||||
* @param pdf PDF document to clean up
|
||||
*/
|
||||
void pdf_destroy(struct pdf_doc *pdf);
|
||||
|
||||
/**
|
||||
* Retrieve the error message if any operation fails
|
||||
* @param pdf pdf document to retrieve error message from
|
||||
* @param errval optional pointer to an integer to be set to the error code
|
||||
* @return NULL if no error message, string description of error otherwise
|
||||
*/
|
||||
const char *pdf_get_err(const struct pdf_doc *pdf, int *errval);
|
||||
|
||||
/**
|
||||
* Acknowledge an outstanding pdf error
|
||||
* @param pdf pdf document to clear the error message from
|
||||
*/
|
||||
void pdf_clear_err(struct pdf_doc *pdf);
|
||||
|
||||
/**
|
||||
* Sets the font to use for text objects. Default value is Times-Roman if
|
||||
* this function is not called.
|
||||
* Note: The font selection should be done before text is output,
|
||||
* and will remain until pdf_set_font is called again.
|
||||
* @param pdf PDF document to update font on
|
||||
* @param font New font to use. This must be one of the standard PDF fonts:
|
||||
* Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
|
||||
* Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
|
||||
* Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic,
|
||||
* Symbol or ZapfDingbats
|
||||
* @return < 0 on failure, 0 on success
|
||||
*/
|
||||
int pdf_set_font(struct pdf_doc *pdf, const char *font);
|
||||
|
||||
/**
|
||||
* Calculate the width of a given string in the current font
|
||||
* @param pdf PDF document
|
||||
* @param font_name Name of the font to get the width of.
|
||||
* This must be one of the standard PDF fonts:
|
||||
* Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
|
||||
* Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
|
||||
* Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic,
|
||||
* Symbol or ZapfDingbats
|
||||
* @param text Text to determine width of
|
||||
* @param size Size of the text, in points
|
||||
* @param text_width area to store calculated width in
|
||||
* @return < 0 on failure, 0 on success
|
||||
*/
|
||||
int pdf_get_font_text_width(struct pdf_doc *pdf, const char *font_name,
|
||||
const char *text, float size, float *text_width);
|
||||
|
||||
/**
|
||||
* Retrieves a PDF document height
|
||||
* @param pdf PDF document to get height of
|
||||
* @return height of PDF document (in points)
|
||||
*/
|
||||
float pdf_height(const struct pdf_doc *pdf);
|
||||
|
||||
/**
|
||||
* Retrieves a PDF document width
|
||||
* @param pdf PDF document to get width of
|
||||
* @return width of PDF document (in points)
|
||||
*/
|
||||
float pdf_width(const struct pdf_doc *pdf);
|
||||
|
||||
/**
|
||||
* Retrieves page height
|
||||
* @param page Page object to get height of
|
||||
* @return height of page (in points)
|
||||
*/
|
||||
float pdf_page_height(const struct pdf_object *page);
|
||||
|
||||
/**
|
||||
* Retrieves page width
|
||||
* @param page Page object to get width of
|
||||
* @return width of page (in points)
|
||||
*/
|
||||
float pdf_page_width(const struct pdf_object *page);
|
||||
|
||||
/**
|
||||
* Add a new page to the given pdf
|
||||
* @param pdf PDF document to append page to
|
||||
* @return new page object
|
||||
*/
|
||||
struct pdf_object *pdf_append_page(struct pdf_doc *pdf);
|
||||
|
||||
/**
|
||||
* Adjust the width/height of a specific page
|
||||
* @param pdf PDF document that the page belongs to
|
||||
* @param page object returned from @ref pdf_append_page
|
||||
* @param width Width of the page in points
|
||||
* @param height Height of the page in points
|
||||
* @return < 0 on failure, 0 on success
|
||||
*/
|
||||
int pdf_page_set_size(struct pdf_doc *pdf, struct pdf_object *page,
|
||||
float width, float height);
|
||||
|
||||
/**
|
||||
* Save the given pdf document to the supplied filename.
|
||||
* @param pdf PDF document to save
|
||||
* @param filename Name of the file to store the PDF into (NULL for stdout)
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_save(struct pdf_doc *pdf, const char *filename);
|
||||
|
||||
/**
|
||||
* Save the given pdf document to the given FILE output
|
||||
* @param pdf PDF document to save
|
||||
* @param fp FILE pointer to store the data into (must be writable)
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_save_file(struct pdf_doc *pdf, FILE *fp);
|
||||
|
||||
/**
|
||||
* Add a text string to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param text String to display
|
||||
* @param size Point size of the font
|
||||
* @param xoff X location to put it in
|
||||
* @param yoff Y location to put it in
|
||||
* @param colour Colour to draw the text
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_text(struct pdf_doc *pdf, struct pdf_object *page,
|
||||
const char *text, float size, float xoff, float yoff,
|
||||
uint32_t colour);
|
||||
|
||||
/**
|
||||
* Add a text string to the document, making it wrap if it is too
|
||||
* long
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param text String to display
|
||||
* @param size Point size of the font
|
||||
* @param xoff X location to put it in
|
||||
* @param yoff Y location to put it in
|
||||
* @param colour Colour to draw the text
|
||||
* @param wrap_width Width at which to wrap the text
|
||||
* @param align Text alignment (see PDF_ALIGN_xxx)
|
||||
* @param height Store the final height of the wrapped text here (optional)
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_add_text_wrap(struct pdf_doc *pdf, struct pdf_object *page,
|
||||
const char *text, float size, float xoff, float yoff,
|
||||
uint32_t colour, float wrap_width, int align,
|
||||
float *height);
|
||||
|
||||
/**
|
||||
* Add a line to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x1 X offset of start of line
|
||||
* @param y1 Y offset of start of line
|
||||
* @param x2 X offset of end of line
|
||||
* @param y2 Y offset of end of line
|
||||
* @param width Width of the line
|
||||
* @param colour Colour to draw the line
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_line(struct pdf_doc *pdf, struct pdf_object *page, float x1,
|
||||
float y1, float x2, float y2, float width, uint32_t colour);
|
||||
|
||||
/**
|
||||
* Add a cubic bezier curve to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x1 X offset of the initial point of the curve
|
||||
* @param y1 Y offset of the initial point of the curve
|
||||
* @param x2 X offset of the final point of the curve
|
||||
* @param y2 Y offset of the final point of the curve
|
||||
* @param xq1 X offset of the first control point of the curve
|
||||
* @param yq1 Y offset of the first control point of the curve
|
||||
* @param xq2 X offset of the second control of the curve
|
||||
* @param yq2 Y offset of the second control of the curve
|
||||
* @param width Width of the curve
|
||||
* @param colour Colour to draw the curve
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_cubic_bezier(struct pdf_doc *pdf, struct pdf_object *page,
|
||||
float x1, float y1, float x2, float y2, float xq1,
|
||||
float yq1, float xq2, float yq2, float width,
|
||||
uint32_t colour);
|
||||
|
||||
/**
|
||||
* Add a quadratic bezier curve to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x1 X offset of the initial point of the curve
|
||||
* @param y1 Y offset of the initial point of the curve
|
||||
* @param x2 X offset of the final point of the curve
|
||||
* @param y2 Y offset of the final point of the curve
|
||||
* @param xq1 X offset of the control point of the curve
|
||||
* @param yq1 Y offset of the control point of the curve
|
||||
* @param width Width of the curve
|
||||
* @param colour Colour to draw the curve
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_quadratic_bezier(struct pdf_doc *pdf, struct pdf_object *page,
|
||||
float x1, float y1, float x2, float y2,
|
||||
float xq1, float yq1, float width,
|
||||
uint32_t colour);
|
||||
|
||||
/**
|
||||
* Add a custom path to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param operations Array of drawing operations
|
||||
* @param operation_count The number of operations
|
||||
* @param stroke_width Width of the stroke
|
||||
* @param stroke_colour Colour to stroke the curve
|
||||
* @param fill_colour Colour to fill the path
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_custom_path(struct pdf_doc *pdf, struct pdf_object *page,
|
||||
struct pdf_path_operation *operations,
|
||||
int operation_count, float stroke_width,
|
||||
uint32_t stroke_colour, uint32_t fill_colour);
|
||||
|
||||
/**
|
||||
* Add an ellipse to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x X offset of the center of the ellipse
|
||||
* @param y Y offset of the center of the ellipse
|
||||
* @param xradius Radius of the ellipse in the X axis
|
||||
* @param yradius Radius of the ellipse in the Y axis
|
||||
* @param width Width of the ellipse outline stroke
|
||||
* @param colour Colour to draw the ellipse outline stroke
|
||||
* @param fill_colour Colour to fill the ellipse
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_ellipse(struct pdf_doc *pdf, struct pdf_object *page, float x,
|
||||
float y, float xradius, float yradius, float width,
|
||||
uint32_t colour, uint32_t fill_colour);
|
||||
|
||||
/**
|
||||
* Add a circle to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x X offset of the center of the circle
|
||||
* @param y Y offset of the center of the circle
|
||||
* @param radius Radius of the circle
|
||||
* @param width Width of the circle outline stroke
|
||||
* @param colour Colour to draw the circle outline stroke
|
||||
* @param fill_colour Colour to fill the circle
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_circle(struct pdf_doc *pdf, struct pdf_object *page, float x,
|
||||
float y, float radius, float width, uint32_t colour,
|
||||
uint32_t fill_colour);
|
||||
|
||||
/**
|
||||
* Add an outline rectangle to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x X offset to start rectangle at
|
||||
* @param y Y offset to start rectangle at
|
||||
* @param width Width of rectangle
|
||||
* @param height Height of rectangle
|
||||
* @param border_width Width of rectangle border
|
||||
* @param colour Colour to draw the rectangle
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_rectangle(struct pdf_doc *pdf, struct pdf_object *page, float x,
|
||||
float y, float width, float height, float border_width,
|
||||
uint32_t colour);
|
||||
|
||||
/**
|
||||
* Add a filled rectangle to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x X offset to start rectangle at
|
||||
* @param y Y offset to start rectangle at
|
||||
* @param width Width of rectangle
|
||||
* @param height Height of rectangle
|
||||
* @param border_width Width of rectangle border
|
||||
* @param colour_fill Colour to fill the rectangle
|
||||
* @param colour_border Colour to draw the rectangle
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_filled_rectangle(struct pdf_doc *pdf, struct pdf_object *page,
|
||||
float x, float y, float width, float height,
|
||||
float border_width, uint32_t colour_fill,
|
||||
uint32_t colour_border);
|
||||
|
||||
/**
|
||||
* Add an outline polygon to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x array of X offsets for points comprising the polygon
|
||||
* @param y array of Y offsets for points comprising the polygon
|
||||
* @param count Number of points comprising the polygon
|
||||
* @param border_width Width of polygon border
|
||||
* @param colour Colour to draw the polygon
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_polygon(struct pdf_doc *pdf, struct pdf_object *page, float x[],
|
||||
float y[], int count, float border_width,
|
||||
uint32_t colour);
|
||||
|
||||
/**
|
||||
* Add a filled polygon to the document
|
||||
* @param pdf PDF document to add to
|
||||
* @param page Page to add object to (NULL => most recently added page)
|
||||
* @param x array of X offsets of points comprising the polygon
|
||||
* @param y array of Y offsets of points comprising the polygon
|
||||
* @param count Number of points comprising the polygon
|
||||
* @param border_width Width of polygon border
|
||||
* @param colour Colour to draw the polygon
|
||||
* @return 0 on success, < 0 on failure
|
||||
*/
|
||||
int pdf_add_filled_polygon(struct pdf_doc *pdf, struct pdf_object *page,
|
||||
float x[], float y[], int count,
|
||||
float border_width, uint32_t colour);
|
||||
|
||||
/**
|
||||
* Add a bookmark to the document
|
||||
* @param pdf PDF document to add bookmark to
|
||||
* @param page Page to jump to for bookmark
|
||||
(or NULL for the most recently added page)
|
||||
* @param parent ID of a previously created bookmark that is the parent
|
||||
of this one. -1 if this should be a top-level bookmark.
|
||||
* @param name String to associate with the bookmark
|
||||
* @return < 0 on failure, new bookmark id on success
|
||||
*/
|
||||
int pdf_add_bookmark(struct pdf_doc *pdf, struct pdf_object *page, int parent,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Add a link annotation to the document
|
||||
* @param pdf PDF document to add link to
|
||||
* @param page Page that holds the clickable rectangle
|
||||
(or NULL for the most recently added page)
|
||||
* @param x X coordinate of bottom LHS corner of clickable rectangle
|
||||
* @param y Y coordinate of bottom LHS corner of clickable rectangle
|
||||
* @param width width of clickable rectangle
|
||||
* @param height height of clickable rectangle
|
||||
* @param target_page Page to jump to for link
|
||||
* @param target_x X coordinate to position at the left of the view
|
||||
* @param target_y Y coordinate to position at the top of the view
|
||||
* @return < 0 on failure, new bookmark id on success
|
||||
*/
|
||||
int pdf_add_link(struct pdf_doc *pdf, struct pdf_object *page, float x,
|
||||
float y, float width, float height,
|
||||
struct pdf_object *target_page, float target_x,
|
||||
float target_y);
|
||||
|
||||
/**
|
||||
* List of different barcode encodings that are supported
|
||||
*/
|
||||
enum {
|
||||
PDF_BARCODE_128A, //!< Produce code-128A style barcodes
|
||||
PDF_BARCODE_39, //!< Produce code-39 style barcodes
|
||||
PDF_BARCODE_EAN13, //!< Produce EAN-13 style barcodes
|
||||
PDF_BARCODE_UPCA, //!< Produce UPC-A style barcodes
|
||||
PDF_BARCODE_EAN8, //!< Produce EAN-8 style barcodes
|
||||
PDF_BARCODE_UPCE, //!< Produce UPC-E style barcodes
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a barcode to the document
|
||||
* @param pdf PDF document to add barcode to
|
||||
* @param page Page to add barcode to (NULL => most recently added page)
|
||||
* @param code Type of barcode to add (PDF_BARCODE_xxx)
|
||||
* @param x X offset to put barcode at
|
||||
* @param y Y offset to put barcode at
|
||||
* @param width Width of barcode
|
||||
* @param height Height of barcode
|
||||
* @param string Barcode contents
|
||||
* @param colour Colour to draw barcode
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_add_barcode(struct pdf_doc *pdf, struct pdf_object *page, int code,
|
||||
float x, float y, float width, float height,
|
||||
const char *string, uint32_t colour);
|
||||
|
||||
/**
|
||||
* Add image data as an image to the document.
|
||||
* Image data must be one of: JPEG, PNG, PPM, PGM or BMP formats
|
||||
* Passing 0 for either the display width or height will
|
||||
* include the image but not render it visible.
|
||||
* Passing a negative number either the display height or width will
|
||||
* have the image be resized while keeping the original aspect ratio.
|
||||
* @param pdf PDF document to add image to
|
||||
* @param page Page to add image to (NULL => most recently added page)
|
||||
* @param x X offset to put image at
|
||||
* @param y Y offset to put image at
|
||||
* @param display_width Displayed width of image
|
||||
* @param display_height Displayed height of image
|
||||
* @param data Image data bytes
|
||||
* @param len Length of data
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_add_image_data(struct pdf_doc *pdf, struct pdf_object *page, float x,
|
||||
float y, float display_width, float display_height,
|
||||
const uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
* Add a raw 24 bit per pixel RGB buffer as an image to the document
|
||||
* Passing 0 for either the display width or height will
|
||||
* include the image but not render it visible.
|
||||
* Passing a negative number either the display height or width will
|
||||
* have the image be resized while keeping the original aspect ratio.
|
||||
* @param pdf PDF document to add image to
|
||||
* @param page Page to add image to (NULL => most recently added page)
|
||||
* @param x X offset to put image at
|
||||
* @param y Y offset to put image at
|
||||
* @param display_width Displayed width of image
|
||||
* @param display_height Displayed height of image
|
||||
* @param data RGB data to add
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_add_rgb24(struct pdf_doc *pdf, struct pdf_object *page, float x,
|
||||
float y, float display_width, float display_height,
|
||||
const uint8_t *data, uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* Add a raw 8 bit per pixel grayscale buffer as an image to the document
|
||||
* @param pdf PDF document to add image to
|
||||
* @param page Page to add image to (NULL => most recently added page)
|
||||
* @param x X offset to put image at
|
||||
* @param y Y offset to put image at
|
||||
* @param display_width Displayed width of image
|
||||
* @param display_height Displayed height of image
|
||||
* @param data grayscale pixel data to add
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_add_grayscale8(struct pdf_doc *pdf, struct pdf_object *page, float x,
|
||||
float y, float display_width, float display_height,
|
||||
const uint8_t *data, uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* Add an image file as an image to the document.
|
||||
* Passing 0 for either the display width or height will
|
||||
* include the image but not render it visible.
|
||||
* Passing a negative number either the display height or width will
|
||||
* have the image be resized while keeping the original aspect ratio.
|
||||
* Supports image formats: JPEG, PNG, PPM, PGM & BMP
|
||||
* @param pdf PDF document to add bookmark to
|
||||
* @param page Page to add image to (NULL => most recently added page)
|
||||
* @param x X offset to put image at
|
||||
* @param y Y offset to put image at
|
||||
* @param display_width Displayed width of image
|
||||
* @param display_height Displayed height of image
|
||||
* @param image_filename Filename of image file to display
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_add_image_file(struct pdf_doc *pdf, struct pdf_object *page, float x,
|
||||
float y, float display_width, float display_height,
|
||||
const char *image_filename);
|
||||
|
||||
/**
|
||||
* Parse image data to determine the image type & metadata
|
||||
* @param info structure to hold the parsed metadata
|
||||
* @param data image data to parse
|
||||
* @param length number of bytes in data
|
||||
* @param err_msg area to put any failure details
|
||||
* @param err_msg_length maximum number of bytes to store in err_msg
|
||||
* @return < 0 on failure, >= 0 on success
|
||||
*/
|
||||
int pdf_parse_image_header(struct pdf_img_info *info, const uint8_t *data,
|
||||
size_t length, char *err_msg,
|
||||
size_t err_msg_length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // PDFGEN_H
|
||||
620
src/conf.c
Normal file
620
src/conf.c
Normal file
@@ -0,0 +1,620 @@
|
||||
/*
|
||||
* conf.c: functions that handle the nwipe.conf configuration file
|
||||
* and the creation of the nwipe_customers.csv file. nwipe.conf uses
|
||||
* libconfig format, while nwipe_customers.csv uses comma separted
|
||||
* values. CSV is used so that the user can build there own customer
|
||||
* listing using spreadsheets rather than enter all the customer
|
||||
* information via the nwipe GUI interface.
|
||||
*
|
||||
* Copyright PartialVolume <https://github.com/PartialVolume>.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <libconfig.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
#include "logging.h"
|
||||
#include "method.h"
|
||||
#include "options.h"
|
||||
#include "conf.h"
|
||||
|
||||
config_t nwipe_cfg;
|
||||
config_setting_t *nwipe_conf_setting, *group_organisation, *root, *group, *previous_group, *setting;
|
||||
const char* nwipe_conf_str;
|
||||
char nwipe_config_directory[] = "/etc/nwipe";
|
||||
char nwipe_config_file[] = "/etc/nwipe/nwipe.conf";
|
||||
char nwipe_customers_file[] = "/etc/nwipe/nwipe_customers.csv";
|
||||
char nwipe_customers_file_backup[] = "/etc/nwipe/nwipe_customers.csv.backup";
|
||||
char nwipe_customers_file_backup_tmp[] = "/etc/nwipe/nwipe_customers.csv.backup.tmp";
|
||||
|
||||
/*
|
||||
* Checks for the existence of nwipe.conf and nwipe_customers.csv
|
||||
* If either one does not exist, they are created and formatted
|
||||
* with a basic configuration.
|
||||
*/
|
||||
|
||||
int nwipe_conf_init()
|
||||
{
|
||||
FILE* fp_config;
|
||||
FILE* fp_customers;
|
||||
|
||||
config_init( &nwipe_cfg );
|
||||
char nwipe_customers_initial_content[] =
|
||||
"\"Customer Name\";\"Contact Name\";\"Customer Address\";\"Contact Phone\"\n"
|
||||
"\"Not Applicable\";\"Not Applicable\";\"Not Applicable\";\"Not Applicable\"\n";
|
||||
|
||||
/* Read /etc/nwipe/nwipe.conf. If there is an error, determine whether
|
||||
* it's because it doesn't exist. If it doesn't exist create it and
|
||||
* populate it with a basic structure.
|
||||
*/
|
||||
|
||||
/* Does the /etc/nwipe/nwipe.conf file exist? If not, then create it */
|
||||
if( access( nwipe_config_file, F_OK ) == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Nwipes config file %s exists", nwipe_config_file );
|
||||
|
||||
/* Read the nwipe.conf configuration file and report any errors */
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO, "Reading nwipe's config file %s", nwipe_config_file );
|
||||
if( !config_read_file( &nwipe_cfg, nwipe_config_file ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Syntax error: %s:%d - %s\n",
|
||||
config_error_file( &nwipe_cfg ),
|
||||
config_error_line( &nwipe_cfg ),
|
||||
config_error_text( &nwipe_cfg ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "%s does not exist", nwipe_config_file );
|
||||
|
||||
/* We assume the /etc/nwipe directory doesn't exist, so try to create it */
|
||||
mkdir( nwipe_config_directory, 0755 );
|
||||
|
||||
/* create the nwipe.conf file */
|
||||
if( !( fp_config = fopen( nwipe_config_file, "w" ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to create %s", nwipe_config_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Created %s", nwipe_config_file );
|
||||
fclose( fp_config );
|
||||
}
|
||||
}
|
||||
|
||||
root = config_root_setting( &nwipe_cfg );
|
||||
|
||||
/**
|
||||
* If they don't already exist, populate nwipe.conf with groups, settings and values.
|
||||
* This will also fill in missing group or settings if they have been corrupted or
|
||||
* accidently deleted by the user. It will also update an existing nwipe.conf
|
||||
* file as new groups and settings are added to nwipe. If new settings are added
|
||||
* to nwipes conf file they MUST appear below in this list of groups and settings.
|
||||
*/
|
||||
|
||||
nwipe_conf_populate( "Organisation_Details.Business_Name", "Not Applicable (BN)" );
|
||||
nwipe_conf_populate( "Organisation_Details.Business_Address", "Not Applicable (BA)" );
|
||||
nwipe_conf_populate( "Organisation_Details.Contact_Name", "Not Applicable (BCN)" );
|
||||
nwipe_conf_populate( "Organisation_Details.Contact_Phone", "Not Applicable (BCP)" );
|
||||
nwipe_conf_populate( "Organisation_Details.Op_Tech_Name", "Not Applicable (OTN)" );
|
||||
|
||||
/**
|
||||
* Add PDF Certificate/Report settings
|
||||
*/
|
||||
nwipe_conf_populate( "PDF_Certificate.PDF_Enable", "ENABLED" );
|
||||
nwipe_conf_populate( "PDF_Certificate.PDF_Preview", "DISABLED" );
|
||||
|
||||
/**
|
||||
* The currently selected customer that will be printed on the report
|
||||
*/
|
||||
nwipe_conf_populate( "Selected_Customer.Customer_Name", "Not Applicable (CN)" );
|
||||
nwipe_conf_populate( "Selected_Customer.Customer_Address", "Not Applicable (CA)" );
|
||||
nwipe_conf_populate( "Selected_Customer.Contact_Name", "Not Applicable (CCN)" );
|
||||
nwipe_conf_populate( "Selected_Customer.Contact_Phone", "Not Applicable (CP)" );
|
||||
|
||||
/**
|
||||
* Write out the new configuration.
|
||||
*/
|
||||
if( !config_write_file( &nwipe_cfg, nwipe_config_file ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to write nwipe config to %s", nwipe_config_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Sucessfully written nwipe config to %s", nwipe_config_file );
|
||||
}
|
||||
|
||||
/* Read the nwipe.conf configuration file and report any errors */
|
||||
if( !config_read_file( &nwipe_cfg, nwipe_config_file ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Syntax error: %s:%d - %s\n",
|
||||
config_error_file( &nwipe_cfg ),
|
||||
config_error_line( &nwipe_cfg ),
|
||||
config_error_text( &nwipe_cfg ) );
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Now check nwipe_customers.csv exists, if not create it with a basic structure
|
||||
*/
|
||||
if( access( nwipe_customers_file, F_OK ) == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Nwipes customer file %s exists", nwipe_customers_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "%s does not exist", nwipe_customers_file );
|
||||
|
||||
/* We assume the /etc/nwipe directory doesn't exist, so try to create it */
|
||||
mkdir( nwipe_config_directory, 0755 );
|
||||
|
||||
/* create the nwipe_customers.csv file */
|
||||
if( !( fp_customers = fopen( nwipe_customers_file, "w" ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to create %s", nwipe_customers_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Created %s", nwipe_customers_file );
|
||||
|
||||
/* Now populate the csv header and first entry, Lines 1 and 2 */
|
||||
if( fwrite( nwipe_customers_initial_content, sizeof( nwipe_customers_initial_content ), 1, fp_customers )
|
||||
== 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Populated %s with basic config", nwipe_customers_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to write basic config to %s", nwipe_customers_file );
|
||||
}
|
||||
fclose( fp_customers );
|
||||
}
|
||||
}
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
void save_selected_customer( char** customer )
|
||||
{
|
||||
/* This function saves the user selected customer
|
||||
* to nwipe's config file /etc/nwipe/nwipe.conf
|
||||
* for later use by the PDF creation functions.
|
||||
*/
|
||||
|
||||
int idx;
|
||||
int field_count;
|
||||
int field_idx;
|
||||
|
||||
char field_1[FIELD_LENGTH];
|
||||
char field_2[FIELD_LENGTH];
|
||||
char field_3[FIELD_LENGTH];
|
||||
char field_4[FIELD_LENGTH];
|
||||
|
||||
/* zero the field strings */
|
||||
for( idx = 0; idx < FIELD_LENGTH; idx++ )
|
||||
field_1[idx] = 0;
|
||||
for( idx = 0; idx < FIELD_LENGTH; idx++ )
|
||||
field_2[idx] = 0;
|
||||
for( idx = 0; idx < FIELD_LENGTH; idx++ )
|
||||
field_3[idx] = 0;
|
||||
for( idx = 0; idx < FIELD_LENGTH; idx++ )
|
||||
field_4[idx] = 0;
|
||||
|
||||
/* Extract the field contents from the csv string
|
||||
*/
|
||||
idx = 0;
|
||||
field_idx = 0;
|
||||
field_count = 1;
|
||||
|
||||
while( *( *customer + idx ) != 0 && field_count < NUMBER_OF_FIELDS + 1 )
|
||||
{
|
||||
/* Start of a field? */
|
||||
if( *( *customer + idx ) == '\"' )
|
||||
{
|
||||
idx++;
|
||||
|
||||
while( *( *customer + idx ) != '\"' && *( *customer + idx ) != 0 )
|
||||
{
|
||||
if( field_count == 1 && field_idx < ( FIELD_LENGTH - 1 ) )
|
||||
{
|
||||
field_1[field_idx++] = *( *customer + idx );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( field_count == 2 && field_idx < ( FIELD_LENGTH - 1 ) )
|
||||
{
|
||||
field_2[field_idx++] = *( *customer + idx );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( field_count == 3 && field_idx < ( FIELD_LENGTH - 1 ) )
|
||||
{
|
||||
field_3[field_idx++] = *( *customer + idx );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( field_count == 4 && field_idx < ( FIELD_LENGTH - 1 ) )
|
||||
{
|
||||
field_4[field_idx++] = *( *customer + idx );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if( *( *customer + idx ) == '\"' )
|
||||
{
|
||||
/* Makesure the field string is terminated */
|
||||
switch( field_count )
|
||||
{
|
||||
case 1:
|
||||
field_1[field_idx] = 0;
|
||||
break;
|
||||
case 2:
|
||||
field_2[field_idx] = 0;
|
||||
break;
|
||||
case 3:
|
||||
field_3[field_idx] = 0;
|
||||
break;
|
||||
case 4:
|
||||
field_4[field_idx] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
field_count++;
|
||||
field_idx = 0;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* All 4 fields present? */
|
||||
if( field_count != NUMBER_OF_FIELDS + 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Insuffient fields in customer entry, expected %i, actual(field_count) %i, idx=%i",
|
||||
NUMBER_OF_FIELDS,
|
||||
field_count,
|
||||
idx );
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* Write the fields to nwipe's config file /etc/nwipe/nwipe.conf
|
||||
*/
|
||||
if( ( setting = config_lookup( &nwipe_cfg, "Selected_Customer.Customer_Name" ) ) )
|
||||
{
|
||||
config_setting_set_string( setting, field_1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Can't find \"Selected Customers.Customer_Name\" in %s", nwipe_config_file );
|
||||
}
|
||||
|
||||
if( ( setting = config_lookup( &nwipe_cfg, "Selected_Customer.Customer_Address" ) ) )
|
||||
{
|
||||
config_setting_set_string( setting, field_2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Can't find \"Selected Customers.Customer_Address\" in %s", nwipe_config_file );
|
||||
}
|
||||
|
||||
if( ( setting = config_lookup( &nwipe_cfg, "Selected_Customer.Contact_Name" ) ) )
|
||||
{
|
||||
config_setting_set_string( setting, field_3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Can't find \"Selected Customers.Contact_Name\" in %s", nwipe_config_file );
|
||||
}
|
||||
|
||||
if( ( setting = config_lookup( &nwipe_cfg, "Selected_Customer.Contact_Phone" ) ) )
|
||||
{
|
||||
config_setting_set_string( setting, field_4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Can't find \"Selected Customers.Contact_Phone\" in %s", nwipe_config_file );
|
||||
}
|
||||
|
||||
/* Write out the new configuration. */
|
||||
if( !config_write_file( &nwipe_cfg, nwipe_config_file ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to write user selected customer to %s", nwipe_config_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Populated %s with user selected customer", nwipe_config_file );
|
||||
}
|
||||
}
|
||||
|
||||
int nwipe_conf_update_setting( char* group_name_setting_name, char* setting_value )
|
||||
{
|
||||
/* You would call this function of you wanted to update an existing setting in nwipe.conf, i.e
|
||||
*
|
||||
* nwipe_conf_update_setting( "PDF_Certificate.PDF_Enable", "ENABLED" )
|
||||
*
|
||||
* It is NOT used for creating a new group or setting name.
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* Write the field to nwipe's config file /etc/nwipe/nwipe.conf
|
||||
*/
|
||||
if( ( setting = config_lookup( &nwipe_cfg, group_name_setting_name ) ) )
|
||||
{
|
||||
config_setting_set_string( setting, setting_value );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR, "Can't find group.setting_name %s in %s", group_name_setting_name, nwipe_config_file );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Write the new configuration to nwipe.conf
|
||||
*/
|
||||
if( !config_write_file( &nwipe_cfg, nwipe_config_file ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to write %s to %s", group_name_setting_name, nwipe_config_file );
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"Updated %s with value %s in %s",
|
||||
group_name_setting_name,
|
||||
setting_value,
|
||||
nwipe_config_file );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} // end nwipe_conf_update_setting()
|
||||
|
||||
int nwipe_conf_read_setting( char* group_name_setting_name, const char** setting_value )
|
||||
{
|
||||
/* You would call this function if you wanted to read a settings value in nwipe.conf, i.e
|
||||
*
|
||||
* const char ** pReturnString;
|
||||
* nwipe_conf_read_setting( "PDF_Certificate", "PDF_Enable", pReturnString );
|
||||
*
|
||||
*/
|
||||
|
||||
/* Separate group_name_setting_name i.e "PDF_Certificate.PDF_Enable" string
|
||||
* into two separate strings by replacing the period with a NULL.
|
||||
*/
|
||||
|
||||
int return_status;
|
||||
int length = strlen( group_name_setting_name );
|
||||
|
||||
char* group_name = malloc( length );
|
||||
char* setting_name = malloc( length );
|
||||
|
||||
int idx = 0;
|
||||
|
||||
while( group_name_setting_name[idx] != 0 && group_name_setting_name[idx] != '.' )
|
||||
{
|
||||
if( group_name_setting_name[idx] == '.' )
|
||||
{
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
memcpy( group_name, group_name_setting_name, idx );
|
||||
strcpy( setting_name, &group_name_setting_name[idx + 1] );
|
||||
|
||||
if( !( setting = config_lookup( &nwipe_cfg, group_name ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Can't find group name %s.%s in %s", group_name, setting_name, nwipe_config_file );
|
||||
return_status = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Retrieve data from nwipe.conf */
|
||||
if( CONFIG_TRUE == config_setting_lookup_string( setting, setting_name, setting_value ) )
|
||||
{
|
||||
return_status = 0; /* Success */
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR, "Can't find setting_name %s.%s in %s", group_name, setting_name, nwipe_config_file );
|
||||
return_status = -2;
|
||||
}
|
||||
}
|
||||
|
||||
free( group_name );
|
||||
free( setting_name );
|
||||
return ( return_status );
|
||||
|
||||
} // end nwipe_conf_read_setting()
|
||||
|
||||
int nwipe_conf_populate( char* path, char* value )
|
||||
{
|
||||
/* This function will check that a path containing a group or multiple groups that lead to a setting all exist,
|
||||
* if they don't exist, the group/s, settings and associated value are created.
|
||||
*
|
||||
* The path, a string consisting of one or more groups separted by a period symbol
|
||||
* '.' with the final element in the path being the setting name. For instance the path might be
|
||||
* PDF_Certificate.PDF_Enable. Where PDF_Certificate is the group name and PDF_Enable is the setting name.
|
||||
* If one or other don't exist then they will be created.
|
||||
*
|
||||
* An arbitary depth of four groups are allowed for nwipe's configuration file, although we only currently, as of
|
||||
* October 2023 use a depth of one group. The number of groups can be increased in the future if required by
|
||||
* changing the definition MAX_GROUP_DEPTH in conf.h
|
||||
*/
|
||||
|
||||
char* path_copy;
|
||||
char* path_build;
|
||||
|
||||
char* group_start[MAX_GROUP_DEPTH + 2]; // A pointer to the start of each group string
|
||||
char* setting_start;
|
||||
|
||||
int idx; // General index
|
||||
int group_count; // Counts the number of groups in the path
|
||||
|
||||
/* Initialise the pointers */
|
||||
memset( group_start, 0, MAX_GROUP_DEPTH + 2 );
|
||||
memset( &setting_start, 0, 1 );
|
||||
|
||||
/* Allocate enough memory for a copy of the path and initialise to zero */
|
||||
path_copy = calloc( strlen( path ) + 1, sizeof( char ) );
|
||||
path_build = calloc( strlen( path ) + 1, sizeof( char ) );
|
||||
|
||||
/* Duplicate the path */
|
||||
strcpy( path_copy, path );
|
||||
|
||||
/* Create individual strings by replacing the period '.' with NULL, counting the number of groups. */
|
||||
idx = 0;
|
||||
group_count = 0;
|
||||
|
||||
/* pointer to first group */
|
||||
group_start[group_count] = path_copy;
|
||||
|
||||
while( *( path_copy + idx ) != 0 )
|
||||
{
|
||||
if( group_count > MAX_GROUP_DEPTH )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Too many groups in path, specified = %i, allowed = %i ",
|
||||
group_count,
|
||||
MAX_GROUP_DEPTH );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( *( path_copy + idx ) == '.' )
|
||||
{
|
||||
*( path_copy + idx ) = 0;
|
||||
group_count++;
|
||||
group_start[group_count] = path_copy + idx + 1;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* setting_start points to a string that represents the setting to be created */
|
||||
setting_start = group_start[group_count];
|
||||
|
||||
/* Remove the last entry from group_start as that would be the setting and not a group */
|
||||
group_start[group_count] = 0;
|
||||
|
||||
if( group_count == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "No groups specified in path, i.e. no period . separator found." );
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Now determine whether the group/s in the path exist, if not create them.
|
||||
*/
|
||||
|
||||
idx = 0;
|
||||
while( group_start[idx] != 0 )
|
||||
{
|
||||
strcat( path_build, group_start[idx] );
|
||||
|
||||
if( !( group = config_lookup( &nwipe_cfg, path_build ) ) )
|
||||
{
|
||||
if( idx == 0 )
|
||||
{
|
||||
group = config_setting_add( root, path_build, CONFIG_TYPE_GROUP );
|
||||
previous_group = group;
|
||||
}
|
||||
else
|
||||
{
|
||||
group = config_setting_add( previous_group, group_start[idx], CONFIG_TYPE_GROUP );
|
||||
previous_group = group;
|
||||
}
|
||||
if( group )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Created group [%s] in %s", path_build, nwipe_config_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to create group [%s] in %s", path_build, nwipe_config_file );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
previous_group = group;
|
||||
}
|
||||
|
||||
idx++;
|
||||
|
||||
if( group_start[idx] != 0 )
|
||||
{
|
||||
strcat( path_build, "." );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* And finally determine whether the setting already exists, if not create it and assign the value to it
|
||||
*/
|
||||
|
||||
/* Does the full path exist ? i.e AAA.BBB */
|
||||
if( ( group = config_lookup( &nwipe_cfg, path_build ) ) )
|
||||
{
|
||||
/* Does the path and setting exist? AAA.BBB.SETTING_NAME */
|
||||
if( !( setting = config_lookup( &nwipe_cfg, path ) ) )
|
||||
{
|
||||
/* Add the new SETTING_NAME */
|
||||
if( ( setting = config_setting_add( group, setting_start, CONFIG_TYPE_STRING ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Created setting name %s in %s", path, nwipe_config_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR, "Failed to create setting name %s in %s", setting_start, nwipe_config_file );
|
||||
}
|
||||
|
||||
if( config_setting_set_string( setting, value ) == CONFIG_TRUE )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Set value for %s in %s to %s", path, nwipe_config_file, value );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to set value for %s in %s to %s", path, nwipe_config_file, value );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Setting already exists [%s] in %s", path, nwipe_config_file );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Couldn't find constructed path [%s] in %s", path_build, nwipe_config_file );
|
||||
}
|
||||
|
||||
free( path_copy );
|
||||
free( path_build );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nwipe_conf_close()
|
||||
{
|
||||
config_destroy( &nwipe_cfg );
|
||||
}
|
||||
55
src/conf.h
Normal file
55
src/conf.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef CONF_H_
|
||||
#define CONF_H_
|
||||
|
||||
/**
|
||||
* Initialises the libconfig code, called once at the
|
||||
* start of nwipe, prior to any attempts to access
|
||||
* nwipe's config file /etc/nwipe/nwipe.conf
|
||||
* @param none
|
||||
* @return int
|
||||
* 0 = success
|
||||
* -1 = error
|
||||
*/
|
||||
int nwipe_conf_init();
|
||||
|
||||
/**
|
||||
* Before exiting nwipe, this function should be called
|
||||
* to free up libconfig's memory usage
|
||||
* @param none
|
||||
* @return void
|
||||
*/
|
||||
void nwipe_conf_close();
|
||||
|
||||
void save_selected_customer( char** );
|
||||
|
||||
/**
|
||||
* int nwipe_conf_update_setting( char *, char * );
|
||||
* Use this function to update a setting in nwipe.conf
|
||||
* @param char * this is the group name and setting name separated by a period '.'
|
||||
* i.e "PDF_Certificate.PDF_Enable"
|
||||
* @param char * this is the setting, i.e ENABLED
|
||||
* @return int 0 = Success
|
||||
* 1 = Unable to update memory copy
|
||||
* 2 = Unable to write new configuration to /etc/nwipe/nwipe.conf
|
||||
*/
|
||||
int nwipe_conf_update_setting( char*, char* );
|
||||
|
||||
/**
|
||||
* int nwipe_conf_read_setting( char *, char *, const char ** )
|
||||
* Use this function to read a setting value in nwipe.conf
|
||||
* @param char * this is the group name
|
||||
* @param char * this is the setting name
|
||||
* @param char ** this is a pointer to the setting value
|
||||
* @return int 0 = Success
|
||||
* -1 = Unable to find the specified group name
|
||||
* -2 = Unable to find the specified setting name
|
||||
*/
|
||||
int nwipe_conf_read_setting( char*, const char** );
|
||||
|
||||
int nwipe_conf_populate( char* path, char* value );
|
||||
|
||||
#define FIELD_LENGTH 256
|
||||
#define NUMBER_OF_FIELDS 4
|
||||
#define MAX_GROUP_DEPTH 4
|
||||
|
||||
#endif /* CONF_H_ */
|
||||
@@ -24,6 +24,9 @@
|
||||
#define CONTEXT_H_
|
||||
|
||||
#include "prng.h"
|
||||
#ifndef __HDDTEMP_H__
|
||||
#include "hddtemp_scsi/hddtemp.h"
|
||||
#endif /* __HDDTEMP_H__ */
|
||||
|
||||
typedef enum nwipe_device_t_ {
|
||||
NWIPE_DEVICE_UNKNOWN = 0, // Unknown device.
|
||||
@@ -35,7 +38,8 @@ typedef enum nwipe_device_t_ {
|
||||
NWIPE_DEVICE_ATA,
|
||||
NWIPE_DEVICE_NVME,
|
||||
NWIPE_DEVICE_VIRT,
|
||||
NWIPE_DEVICE_SAS
|
||||
NWIPE_DEVICE_SAS,
|
||||
NWIPE_DEVICE_MMC
|
||||
} nwipe_device_t;
|
||||
|
||||
typedef enum nwipe_pass_t_ {
|
||||
@@ -70,18 +74,22 @@ typedef struct nwipe_speedring_t_
|
||||
} nwipe_speedring_t;
|
||||
|
||||
#define NWIPE_DEVICE_LABEL_LENGTH 200
|
||||
#define NWIPE_DEVICE_SIZE_TXT_LENGTH 7
|
||||
#define NWIPE_DEVICE_SIZE_TXT_LENGTH 8
|
||||
|
||||
// Arbitary length, so far most paths don't exceed about 25 characters
|
||||
// Arbitrary length, so far most paths don't exceed about 25 characters
|
||||
#define MAX_HWMON_PATH_LENGTH 100
|
||||
|
||||
// 20 chracters for serial number plus null Byte
|
||||
#define NWIPE_SERIALNUMBER_LENGTH 20
|
||||
|
||||
typedef struct nwipe_context_t_
|
||||
{
|
||||
/*
|
||||
* Device fields
|
||||
*/
|
||||
int device_block_size; // The soft block size reported by the device.
|
||||
int device_sector_size; // The hard sector size reported by the device.
|
||||
int device_block_size; // The soft block size reported by the device, as logical
|
||||
int device_sector_size; // The logical sector size reported by libparted
|
||||
int device_phys_sector_size; // The physical sector size reported by libparted
|
||||
int device_bus; // The device bus number.
|
||||
int device_fd; // The file descriptor of the device file being wiped.
|
||||
int device_host; // The host number.
|
||||
@@ -94,6 +102,11 @@ typedef struct nwipe_context_t_
|
||||
char device_name_without_path[100];
|
||||
char gui_device_name[100];
|
||||
unsigned long long device_size; // The device size in bytes.
|
||||
u64 device_size_in_sectors; // The device size in number of logical sectors, this may be 512 or 4096 sectors
|
||||
u64 device_size_in_512byte_sectors; // The device size in number of 512byte sectors, irrespective of logical sector
|
||||
// size reported by libata
|
||||
unsigned long long bytes_erased; // Irrespective of pass, this how much of the drive has been erased, CANNOT be
|
||||
// greater than device_size.
|
||||
char* device_size_text; // The device size in a more (human)readable format.
|
||||
char device_size_txt[NWIPE_DEVICE_SIZE_TXT_LENGTH]; // The device size in a more (human)readable format.
|
||||
char* device_model; // The model of the device.
|
||||
@@ -101,7 +114,9 @@ typedef struct nwipe_context_t_
|
||||
struct stat device_stat; // The device file state from fstat().
|
||||
nwipe_device_t device_type; // Indicates an IDE, SCSI, or Compaq SMART device in enumerated form (int)
|
||||
char device_type_str[14]; // Indicates an IDE, SCSI, USB etc as per nwipe_device_t but in ascii
|
||||
char device_serial_no[21]; // Serial number(processed, 20 characters plus null termination) of the device.
|
||||
int device_is_ssd; // 0 = no SSD, 1 = is a SSD
|
||||
char device_serial_no[NWIPE_SERIALNUMBER_LENGTH
|
||||
+ 1]; // Serial number(processed, 20 characters plus null termination) of the device.
|
||||
int device_target; // The device target.
|
||||
|
||||
u64 eta; // The estimated number of seconds until method completion.
|
||||
@@ -116,7 +131,7 @@ typedef struct nwipe_context_t_
|
||||
nwipe_entropy_t prng_seed; // The random data that is used to seed the PRNG.
|
||||
void* prng_state; // The private internal state of the PRNG.
|
||||
int result; // The process return value.
|
||||
int round_count; // The number of rounds performed by the working wipe method.
|
||||
int round_count; // The number of rounds requested by the user for the working wipe method.
|
||||
u64 round_done; // The number of bytes that have already been i/o'd.
|
||||
u64 round_errors; // The number of errors across all rounds.
|
||||
u64 round_size; // The total number of i/o bytes across all rounds.
|
||||
@@ -128,7 +143,10 @@ typedef struct nwipe_context_t_
|
||||
short sync_status; // A flag to indicate when the method is syncing.
|
||||
pthread_t thread; // The ID of the thread.
|
||||
u64 throughput; // Average throughput in bytes per second.
|
||||
char throughput_txt[13]; // Human readable throughput.
|
||||
u64 verify_errors; // The number of verification errors across all passes.
|
||||
int templ_has_hwmon_data; // 0 = no hwmon data available, 1 = hwmon data available
|
||||
int templ_has_scsitemp_data; // 0 = no scsitemp data available, 1 = scsitemp data available
|
||||
char temp1_path[MAX_HWMON_PATH_LENGTH]; // path to temperature variables /sys/class/hwmon/hwmonX/ etc.
|
||||
int temp1_crit; // Critical high drive temperature, 1000000=unitialised, millidegree celsius.
|
||||
int temp1_highest; // Historical highest temperature reached, 1000000=unitialised, millidegree celsius.
|
||||
@@ -136,7 +154,7 @@ typedef struct nwipe_context_t_
|
||||
int temp1_lcrit; // Critical low drive temperature, 1000000=unitialised, millidegree celsius.
|
||||
int temp1_lowest; // Historically lowest temperature, 1000000=unitialised, millidegree celsius.
|
||||
int temp1_max; // Maximum allowed temperature, 1000000=unitialised, millidegree celsius.
|
||||
int temp1_min; // Miniumum allowed temperature, 1000000=unitialised, millidegree celsius.
|
||||
int temp1_min; // Minimum allowed temperature, 1000000=unitialised, millidegree celsius.
|
||||
int temp1_monitored_wipe_max;
|
||||
int temp1_monitored_wipe_min;
|
||||
int temp1_monitored_wipe_avg;
|
||||
@@ -144,13 +162,36 @@ typedef struct nwipe_context_t_
|
||||
int temp1_flash_rate_counter; // used by the gui for timing the flash rate
|
||||
int temp1_flash_rate_status; // 0=blank 1=visible
|
||||
time_t temp1_time; // The time when temperature was last checked, seconds since epoch
|
||||
struct disk* templ_disk; // Pointer to disk structure for hddtemp SCSI routines
|
||||
int wipe_status; // Wipe finished = 0, wipe in progress = 1, wipe yet to start = -1.
|
||||
char wipe_status_txt[10]; // ERASED, FAILED, ABORTED, INSANITY
|
||||
int spinner_idx; // Index into the spinner character array
|
||||
char spinner_character[1]; // The current spinner character
|
||||
double duration; // Duration of the wipe in seconds
|
||||
char duration_str[20]; // The duration string in hh:mm:ss
|
||||
time_t start_time; // Start time of wipe
|
||||
time_t end_time; // End time of wipe
|
||||
u64 fsyncdata_errors; // The number of fsyncdata errors across all passes.
|
||||
char PDF_filename[FILENAME_MAX]; // The filename of the PDF certificate/report.
|
||||
int HPA_status; // 0 = No HPA found/disabled, 1 = HPA detected, 2 = Unknown, unable to checked,
|
||||
// 3 = Not applicable to this device
|
||||
u64 HPA_reported_set; // the 'HPA set' value reported hdparm -N, i.e the first value of n/n
|
||||
u64 HPA_reported_real; // the 'HPA real' value reported hdparm -N, i.e the second value of n/n
|
||||
int DCO_status; // 0 = No DCO found, 1 = DCO detected, 2 = Unknown, unable to checked
|
||||
u64 DCO_reported_real_max_sectors; // real max sectors as reported by hdparm --dco-identify
|
||||
u64 DCO_reported_real_max_size; // real max sectors in bytes
|
||||
u64 Calculated_real_max_size_in_bytes; // This value is determined from all the possible variations for drives that
|
||||
// don't support DCO/HPA and those that do. Also drives that can't provide
|
||||
// HPA/DCO due to the chips they use (USB adapters)
|
||||
char DCO_reported_real_max_size_text[NWIPE_DEVICE_SIZE_TXT_LENGTH]; // real max size in human readable form i.e 1TB
|
||||
char Calculated_real_max_size_in_bytes_text[NWIPE_DEVICE_SIZE_TXT_LENGTH]; // calculated real max human readable
|
||||
u64 HPA_sectors; // The size of the host protected area in sectors
|
||||
char HPA_size_text[NWIPE_DEVICE_SIZE_TXT_LENGTH]; // Human readable size bytes, KB, MB, GB ..
|
||||
int HPA_display_toggle_state; // 0 or 1 Used to toggle between "[1TB] [ 33C]" and [HDA STATUS]
|
||||
time_t HPA_toggle_time; // records a time, then if for instance 3 seconds has elapsed the display changes
|
||||
int test_use1;
|
||||
int test_use2;
|
||||
|
||||
/*
|
||||
* Identity contains the raw serial number of the drive
|
||||
* (where applicable), however, for use within nwipe use the
|
||||
|
||||
997
src/create_pdf.c
Normal file
997
src/create_pdf.c
Normal file
@@ -0,0 +1,997 @@
|
||||
/*
|
||||
* create_pdf.c: Routines that create the PDF erasure certificate
|
||||
*
|
||||
* Copyright PartialVolume <https://github.com/PartialVolume>.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "stdarg.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
#include "create_pdf.h"
|
||||
#include "PDFGen/pdfgen.h"
|
||||
#include "version.h"
|
||||
#include "method.h"
|
||||
#include "embedded_images/shred_db.jpg.h"
|
||||
#include "embedded_images/tick_erased.jpg.h"
|
||||
#include "embedded_images/redcross.h"
|
||||
#include "embedded_images/nwipe_exclamation.jpg.h"
|
||||
#include "logging.h"
|
||||
#include "options.h"
|
||||
#include "prng.h"
|
||||
#include "hpa_dco.h"
|
||||
#include "miscellaneous.h"
|
||||
#include <libconfig.h>
|
||||
#include "conf.h"
|
||||
|
||||
#define text_size_data 10
|
||||
|
||||
struct pdf_doc* pdf;
|
||||
struct pdf_object* page;
|
||||
|
||||
char model_header[50] = ""; /* Model text in the header */
|
||||
char serial_header[30] = ""; /* Serial number text in the header */
|
||||
char barcode[100] = ""; /* Contents of the barcode, i.e model:serial */
|
||||
char pdf_footer[MAX_PDF_FOOTER_TEXT_LENGTH];
|
||||
float height;
|
||||
float page_width;
|
||||
int status_icon;
|
||||
|
||||
int create_pdf( nwipe_context_t* ptr )
|
||||
{
|
||||
extern nwipe_prng_t nwipe_twister;
|
||||
extern nwipe_prng_t nwipe_isaac;
|
||||
extern nwipe_prng_t nwipe_isaac64;
|
||||
|
||||
/* Used by libconfig functions to retrieve data from nwipe.conf defined in conf.c */
|
||||
extern config_t nwipe_cfg;
|
||||
extern char nwipe_config_file[];
|
||||
|
||||
// char pdf_footer[MAX_PDF_FOOTER_TEXT_LENGTH];
|
||||
nwipe_context_t* c;
|
||||
c = ptr;
|
||||
// char model_header[50] = ""; /* Model text in the header */
|
||||
// char serial_header[30] = ""; /* Serial number text in the header */
|
||||
char device_size[100] = ""; /* Device size in the form xMB (xxxx bytes) */
|
||||
// char barcode[100] = ""; /* Contents of the barcode, i.e model:serial */
|
||||
char verify[20] = ""; /* Verify option text */
|
||||
char blank[10] = ""; /* blanking pass, none, zeros, ones */
|
||||
char rounds[50] = ""; /* rounds ASCII numeric */
|
||||
char prng_type[50] = ""; /* type of prng, twister, isaac, isaac64 */
|
||||
char start_time_text[50] = "";
|
||||
char end_time_text[50] = "";
|
||||
char bytes_erased[50] = "";
|
||||
char HPA_status_text[50] = "";
|
||||
char HPA_size_text[50] = "";
|
||||
char errors[50] = "";
|
||||
char throughput_txt[50] = "";
|
||||
char bytes_percent_str[7] = "";
|
||||
|
||||
// int status_icon;
|
||||
|
||||
// float height;
|
||||
// float page_width;
|
||||
|
||||
struct pdf_info info = { .creator = "https://github.com/PartialVolume/shredos.x86_64",
|
||||
.producer = "https://github.com/martijnvanbrummelen/nwipe",
|
||||
.title = "PDF Disk Erasure Certificate",
|
||||
.author = "Nwipe",
|
||||
.subject = "Disk Erase Certificate",
|
||||
.date = "Today" };
|
||||
|
||||
/* A pointer to the system time struct. */
|
||||
struct tm* p;
|
||||
|
||||
/* variables used by libconfig */
|
||||
config_setting_t* setting;
|
||||
const char *business_name, *business_address, *contact_name, *contact_phone, *op_tech_name, *customer_name,
|
||||
*customer_address, *customer_contact_name, *customer_contact_phone;
|
||||
|
||||
/* ------------------ */
|
||||
/* Initialise Various */
|
||||
|
||||
/* Used to display correct icon on page 2 */
|
||||
status_icon = 0; // zero don't display icon, see header STATUS_ICON_..
|
||||
|
||||
// nwipe_log( NWIPE_LOG_NOTICE, "Create the PDF disk erasure certificate" );
|
||||
// struct pdf_doc* pdf = pdf_create( PDF_A4_WIDTH, PDF_A4_HEIGHT, &info );
|
||||
pdf = pdf_create( PDF_A4_WIDTH, PDF_A4_HEIGHT, &info );
|
||||
|
||||
/* Create footer text string and append the version */
|
||||
snprintf( pdf_footer, sizeof( pdf_footer ), "Disc Erasure by NWIPE version %s", version_string );
|
||||
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
struct pdf_object* page_1 = pdf_append_page( pdf );
|
||||
|
||||
/* Obtain page page_width */
|
||||
page_width = pdf_page_width( page_1 );
|
||||
|
||||
/*********************************************************************
|
||||
* Create header and footer on page 1, with the exception of the green
|
||||
* tick/red icon which is set from the 'status' section below
|
||||
*/
|
||||
pdf_add_text_wrap( pdf, NULL, pdf_footer, 12, 0, 30, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
pdf_add_line( pdf, NULL, 50, 50, 550, 50, 3, PDF_BLACK );
|
||||
pdf_add_line( pdf, NULL, 50, 650, 550, 650, 3, PDF_BLACK );
|
||||
pdf_add_image_data( pdf, NULL, 45, 665, 100, 100, bin2c_shred_db_jpg, 27063 );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
snprintf( model_header, sizeof( model_header ), " %s: %s ", "Model", c->device_model );
|
||||
pdf_add_text_wrap( pdf, NULL, model_header, 14, 0, 755, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
snprintf( serial_header, sizeof( serial_header ), " %s: %s ", "S/N", c->device_serial_no );
|
||||
pdf_add_text_wrap( pdf, NULL, serial_header, 14, 0, 735, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
pdf_add_text_wrap( pdf, NULL, "Disk Erasure Report", 24, 0, 695, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
snprintf( barcode, sizeof( barcode ), "%s:%s", c->device_model, c->device_serial_no );
|
||||
pdf_add_text_wrap(
|
||||
pdf, NULL, "Page 1 - Erasure Status", 14, 0, 670, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
pdf_add_barcode( pdf, NULL, PDF_BARCODE_128A, 100, 790, 400, 25, barcode, PDF_BLACK );
|
||||
|
||||
/* ------------------------ */
|
||||
/* Organisation Information */
|
||||
|
||||
pdf_add_line( pdf, NULL, 50, 550, 550, 550, 1, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Organisation Performing The Disk Erasure", 12, 50, 630, PDF_BLUE );
|
||||
pdf_add_text( pdf, NULL, "Business Name:", 12, 60, 610, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Business Address:", 12, 60, 590, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Contact Name:", 12, 60, 570, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Contact Phone:", 12, 300, 570, PDF_GRAY );
|
||||
|
||||
/* Obtain organisational details from nwipe.conf - See conf.c */
|
||||
setting = config_lookup( &nwipe_cfg, "Organisation_Details" );
|
||||
if( setting != NULL )
|
||||
{
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
if( config_setting_lookup_string( setting, "Business_Name", &business_name ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, business_name, text_size_data, 153, 610, PDF_BLACK );
|
||||
}
|
||||
if( config_setting_lookup_string( setting, "Business_Address", &business_address ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, business_address, text_size_data, 165, 590, PDF_BLACK );
|
||||
}
|
||||
if( config_setting_lookup_string( setting, "Contact_Name", &contact_name ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, contact_name, text_size_data, 145, 570, PDF_BLACK );
|
||||
}
|
||||
if( config_setting_lookup_string( setting, "Contact_Phone", &contact_phone ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, contact_phone, text_size_data, 390, 570, PDF_BLACK );
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Cannot locate group [Organisation_Details] in %s", nwipe_config_file );
|
||||
}
|
||||
|
||||
/* -------------------- */
|
||||
/* Customer Information */
|
||||
pdf_add_line( pdf, NULL, 50, 450, 550, 450, 1, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Customer Details", 12, 50, 530, PDF_BLUE );
|
||||
pdf_add_text( pdf, NULL, "Name:", 12, 60, 510, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Address:", 12, 60, 490, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Contact Name:", 12, 60, 470, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Contact Phone:", 12, 300, 470, PDF_GRAY );
|
||||
|
||||
/* Obtain current customer details from nwipe.conf - See conf.c */
|
||||
setting = config_lookup( &nwipe_cfg, "Selected_Customer" );
|
||||
if( setting != NULL )
|
||||
{
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
if( config_setting_lookup_string( setting, "Customer_Name", &customer_name ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, customer_name, text_size_data, 100, 510, PDF_BLACK );
|
||||
}
|
||||
if( config_setting_lookup_string( setting, "Customer_Address", &customer_address ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, customer_address, text_size_data, 110, 490, PDF_BLACK );
|
||||
}
|
||||
if( config_setting_lookup_string( setting, "Contact_Name", &customer_contact_name ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, customer_contact_name, text_size_data, 145, 470, PDF_BLACK );
|
||||
}
|
||||
if( config_setting_lookup_string( setting, "Contact_Phone", &customer_contact_phone ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, customer_contact_phone, text_size_data, 390, 470, PDF_BLACK );
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Cannot locate group [Selected_Customer] in %s", nwipe_config_file );
|
||||
}
|
||||
|
||||
/******************
|
||||
* Disk Information
|
||||
*/
|
||||
pdf_add_line( pdf, NULL, 50, 350, 550, 350, 1, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Disk Information", 12, 50, 430, PDF_BLUE );
|
||||
|
||||
/************
|
||||
* Make/model
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Make/Model:", 12, 60, 410, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, c->device_model, text_size_data, 135, 410, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/************
|
||||
* Serial no.
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Serial:", 12, 340, 410, PDF_GRAY );
|
||||
if( c->device_serial_no[0] == 0 )
|
||||
{
|
||||
snprintf( c->device_serial_no, sizeof( c->device_serial_no ), "Unknown" );
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, c->device_serial_no, text_size_data, 380, 410, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/******************************
|
||||
* Bus type, ATA, USB, NVME etc
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Bus:", 12, 340, 390, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, c->device_type_str, text_size_data, 370, 390, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/*************************
|
||||
* Capacity (Size) of disk
|
||||
*/
|
||||
|
||||
/* Size (Apparent) */
|
||||
pdf_add_text( pdf, NULL, "Size(Apparent): ", 12, 60, 390, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
snprintf( device_size, sizeof( device_size ), "%s, %lli bytes", c->device_size_text, c->device_size );
|
||||
if( ( c->device_size == c->Calculated_real_max_size_in_bytes ) || c->device_type == NWIPE_DEVICE_NVME
|
||||
|| c->device_type == NWIPE_DEVICE_VIRT || c->HPA_status == HPA_NOT_APPLICABLE || c->HPA_status != HPA_UNKNOWN )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, device_size, text_size_data, 145, 390, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
pdf_add_text( pdf, NULL, device_size, text_size_data, 145, 390, PDF_RED );
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/* Size (Real) */
|
||||
pdf_add_text( pdf, NULL, "Size(Real):", 12, 60, 370, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|
||||
|| c->HPA_status == HPA_NOT_APPLICABLE )
|
||||
{
|
||||
snprintf( device_size, sizeof( device_size ), "%s, %lli bytes", c->device_size_text, c->device_size );
|
||||
pdf_add_text( pdf, NULL, device_size, text_size_data, 125, 370, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the calculared real max size as determined from HPA/DCO and libata data is larger than
|
||||
* or equal to the apparent device size then display that value in green.
|
||||
*/
|
||||
if( c->Calculated_real_max_size_in_bytes >= c->device_size )
|
||||
{
|
||||
/* displays the real max size of the disc from the DCO displayed in Green */
|
||||
snprintf( device_size,
|
||||
sizeof( device_size ),
|
||||
"%s, %lli bytes",
|
||||
c->Calculated_real_max_size_in_bytes_text,
|
||||
c->Calculated_real_max_size_in_bytes );
|
||||
pdf_add_text( pdf, NULL, device_size, text_size_data, 125, 370, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If there is no real max size either because the drive or adapter doesn't support it */
|
||||
if( c->HPA_status == HPA_UNKNOWN )
|
||||
{
|
||||
snprintf( device_size, sizeof( device_size ), "Unknown" );
|
||||
pdf_add_text( pdf, NULL, device_size, text_size_data, 125, 370, PDF_RED );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we are already here because c->DCO_reported_real_max_size < 1 so if HPA enabled then use the
|
||||
* value we determine from whether HPA set, HPA real exist and if not assume libata's value*/
|
||||
if( c->HPA_status == HPA_ENABLED )
|
||||
{
|
||||
snprintf( device_size,
|
||||
sizeof( device_size ),
|
||||
"%s, %lli bytes",
|
||||
c->device_size_text,
|
||||
c->Calculated_real_max_size_in_bytes );
|
||||
pdf_add_text( pdf, NULL, device_size, text_size_data, 125, 370, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sanity check, should never get here! */
|
||||
snprintf( device_size, sizeof( device_size ), "Sanity: HPA_status = %i", c->HPA_status );
|
||||
pdf_add_text( pdf, NULL, device_size, text_size_data, 125, 370, PDF_RED );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/* --------------- */
|
||||
/* Erasure Details */
|
||||
pdf_add_text( pdf, NULL, "Disk Erasure Details", 12, 50, 330, PDF_BLUE );
|
||||
|
||||
/* start time */
|
||||
pdf_add_text( pdf, NULL, "Start time:", 12, 60, 310, PDF_GRAY );
|
||||
p = localtime( &c->start_time );
|
||||
snprintf( start_time_text,
|
||||
sizeof( start_time_text ),
|
||||
"%i/%02i/%02i %02i:%02i:%02i",
|
||||
1900 + p->tm_year,
|
||||
1 + p->tm_mon,
|
||||
p->tm_mday,
|
||||
p->tm_hour,
|
||||
p->tm_min,
|
||||
p->tm_sec );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, start_time_text, text_size_data, 120, 310, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/* end time */
|
||||
pdf_add_text( pdf, NULL, "End time:", 12, 300, 310, PDF_GRAY );
|
||||
p = localtime( &c->end_time );
|
||||
snprintf( end_time_text,
|
||||
sizeof( end_time_text ),
|
||||
"%i/%02i/%02i %02i:%02i:%02i",
|
||||
1900 + p->tm_year,
|
||||
1 + p->tm_mon,
|
||||
p->tm_mday,
|
||||
p->tm_hour,
|
||||
p->tm_min,
|
||||
p->tm_sec );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, end_time_text, text_size_data, 360, 310, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/* Duration */
|
||||
pdf_add_text( pdf, NULL, "Duration:", 12, 60, 290, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, c->duration_str, text_size_data, 115, 290, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/*******************
|
||||
* Status of erasure
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Status:", 12, 300, 290, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
|
||||
if( !strcmp( c->wipe_status_txt, "ERASED" )
|
||||
&& ( c->HPA_status == HPA_DISABLED || c->HPA_status == HPA_NOT_APPLICABLE || c->device_type == NWIPE_DEVICE_NVME
|
||||
|| c->device_type == NWIPE_DEVICE_VIRT ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, c->wipe_status_txt, 12, 365, 290, PDF_DARK_GREEN );
|
||||
pdf_add_ellipse( pdf, NULL, 390, 295, 45, 10, 2, PDF_DARK_GREEN, PDF_TRANSPARENT );
|
||||
|
||||
/* Display the green tick icon in the header */
|
||||
pdf_add_image_data( pdf, NULL, 450, 665, 100, 100, bin2c_te_jpg, 54896 );
|
||||
status_icon = STATUS_ICON_GREEN_TICK; // used later on page 2
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !strcmp( c->wipe_status_txt, "ERASED" )
|
||||
&& ( c->HPA_status == HPA_ENABLED || c->HPA_status == HPA_UNKNOWN ) )
|
||||
{
|
||||
pdf_add_ellipse( pdf, NULL, 390, 295, 45, 10, 2, PDF_RED, PDF_BLACK );
|
||||
pdf_add_text( pdf, NULL, c->wipe_status_txt, 12, 365, 290, PDF_YELLOW );
|
||||
pdf_add_text( pdf, NULL, "See Warning !", 12, 450, 290, PDF_RED );
|
||||
|
||||
/* Display the yellow exclamation icon in the header */
|
||||
pdf_add_image_data( pdf, NULL, 450, 665, 100, 100, bin2c_nwipe_exclamation_jpg, 65791 );
|
||||
status_icon = STATUS_ICON_YELLOW_EXCLAMATION; // used later on page 2
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !strcmp( c->wipe_status_txt, "FAILED" ) )
|
||||
{
|
||||
// text shifted left slightly in ellipse due to extra character
|
||||
pdf_add_text( pdf, NULL, c->wipe_status_txt, 12, 370, 290, PDF_RED );
|
||||
|
||||
// Display the red cross in the header
|
||||
pdf_add_image_data( pdf, NULL, 450, 665, 100, 100, bin2c_redcross_jpg, 60331 );
|
||||
status_icon = STATUS_ICON_RED_CROSS; // used later on page 2
|
||||
}
|
||||
else
|
||||
{
|
||||
pdf_add_text( pdf, NULL, c->wipe_status_txt, 12, 360, 290, PDF_RED );
|
||||
|
||||
// Print the red cross
|
||||
pdf_add_image_data( pdf, NULL, 450, 665, 100, 100, bin2c_redcross_jpg, 60331 );
|
||||
status_icon = STATUS_ICON_RED_CROSS; // used later on page 2
|
||||
}
|
||||
pdf_add_ellipse( pdf, NULL, 390, 295, 45, 10, 2, PDF_RED, PDF_TRANSPARENT );
|
||||
}
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/********
|
||||
* Method
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Method:", 12, 60, 270, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, nwipe_method_label( nwipe_options.method ), text_size_data, 110, 270, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/***********
|
||||
* prng type
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "PRNG algorithm:", 12, 300, 270, PDF_GRAY );
|
||||
if( nwipe_options.method == &nwipe_verify_one || nwipe_options.method == &nwipe_verify_zero
|
||||
|| nwipe_options.method == &nwipe_zero || nwipe_options.method == &nwipe_one )
|
||||
{
|
||||
snprintf( prng_type, sizeof( prng_type ), "Not applicable to method" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.prng == &nwipe_twister )
|
||||
{
|
||||
snprintf( prng_type, sizeof( prng_type ), "Twister" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.prng == &nwipe_isaac )
|
||||
{
|
||||
snprintf( prng_type, sizeof( prng_type ), "Isaac" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.prng == &nwipe_isaac64 )
|
||||
{
|
||||
snprintf( prng_type, sizeof( prng_type ), "Isaac64" );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( prng_type, sizeof( prng_type ), "Unknown" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, prng_type, text_size_data, 395, 270, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/******************************************************
|
||||
* Final blanking pass if selected, none, zeros or ones
|
||||
*/
|
||||
if( nwipe_options.noblank )
|
||||
{
|
||||
strcpy( blank, "None" );
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( blank, "Zeros" );
|
||||
}
|
||||
pdf_add_text( pdf, NULL, "Final Pass(Zeros/Ones/None):", 12, 60, 250, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, blank, text_size_data, 230, 250, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/* ***********************************************************************
|
||||
* Create suitable text based on the numeric value of type of verification
|
||||
*/
|
||||
switch( nwipe_options.verify )
|
||||
{
|
||||
case NWIPE_VERIFY_NONE:
|
||||
strcpy( verify, "Verify None" );
|
||||
break;
|
||||
|
||||
case NWIPE_VERIFY_LAST:
|
||||
strcpy( verify, "Verify Last" );
|
||||
break;
|
||||
|
||||
case NWIPE_VERIFY_ALL:
|
||||
strcpy( verify, "Verify All" );
|
||||
break;
|
||||
}
|
||||
pdf_add_text( pdf, NULL, "Verify Pass(Last/All/None):", 12, 300, 250, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, verify, text_size_data, 450, 250, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/* ************
|
||||
* bytes erased
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "*Bytes Erased:", 12, 60, 230, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
|
||||
/* Bytes erased is not applicable when user only requested a verify */
|
||||
if( nwipe_options.method == &nwipe_verify_one || nwipe_options.method == &nwipe_verify_zero )
|
||||
{
|
||||
snprintf( bytes_erased, sizeof( bytes_erased ), "Not applicable to method" );
|
||||
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_BLACK );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|
||||
|| c->HPA_status == HPA_NOT_APPLICABLE )
|
||||
{
|
||||
convert_double_to_string( bytes_percent_str,
|
||||
(double) ( (double) c->bytes_erased / (double) c->device_size ) * 100 );
|
||||
|
||||
snprintf( bytes_erased, sizeof( bytes_erased ), "%lli, (%s%%)", c->bytes_erased, bytes_percent_str );
|
||||
|
||||
if( c->bytes_erased == c->device_size )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_RED );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
convert_double_to_string(
|
||||
bytes_percent_str,
|
||||
(double) ( (double) c->bytes_erased / (double) c->Calculated_real_max_size_in_bytes ) * 100 );
|
||||
|
||||
snprintf( bytes_erased, sizeof( bytes_erased ), "%lli, (%s%%)", c->bytes_erased, bytes_percent_str );
|
||||
|
||||
if( c->bytes_erased == c->Calculated_real_max_size_in_bytes )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
pdf_add_text( pdf, NULL, bytes_erased, text_size_data, 145, 230, PDF_RED );
|
||||
}
|
||||
}
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/************************************************
|
||||
* rounds - How many times the method is repeated
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Rounds(completed/requested):", 12, 300, 230, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
if( !strcmp( c->wipe_status_txt, "ERASED" ) )
|
||||
{
|
||||
snprintf( rounds, sizeof( rounds ), "%i/%i", c->round_working, nwipe_options.rounds );
|
||||
pdf_add_text( pdf, NULL, rounds, text_size_data, 470, 230, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( rounds, sizeof( rounds ), "%i/%i", c->round_working - 1, nwipe_options.rounds );
|
||||
pdf_add_text( pdf, NULL, rounds, text_size_data, 470, 230, PDF_RED );
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/*******************
|
||||
* HPA, DCO - LABELS
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "HPA/DCO:", 12, 60, 210, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, HPA_status_text, text_size_data, 155, 210, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
pdf_add_text( pdf, NULL, "HPA/DCO Size:", 12, 300, 210, PDF_GRAY );
|
||||
|
||||
/*******************
|
||||
* Populate HPA size
|
||||
*/
|
||||
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
if( c->HPA_status == HPA_ENABLED )
|
||||
{
|
||||
snprintf( HPA_size_text, sizeof( HPA_size_text ), "%lli sectors", c->HPA_sectors );
|
||||
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_RED );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_status == HPA_DISABLED )
|
||||
{
|
||||
snprintf( HPA_size_text, sizeof( HPA_size_text ), "No hidden sectors" );
|
||||
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_status == HPA_NOT_APPLICABLE )
|
||||
{
|
||||
snprintf( HPA_size_text, sizeof( HPA_size_text ), "Not Applicable" );
|
||||
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_DARK_GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_status == HPA_UNKNOWN )
|
||||
{
|
||||
snprintf( HPA_size_text, sizeof( HPA_size_text ), "Unknown" );
|
||||
pdf_add_text( pdf, NULL, HPA_size_text, text_size_data, 390, 210, PDF_RED );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/*********************
|
||||
* Populate HPA status (and size if not applicable, NVMe and VIRT)
|
||||
*/
|
||||
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|
||||
|| c->HPA_status == HPA_NOT_APPLICABLE )
|
||||
{
|
||||
snprintf( HPA_status_text, sizeof( HPA_status_text ), "Not applicable" );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, HPA_status_text, text_size_data, 130, 210, PDF_DARK_GREEN );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_status == HPA_ENABLED )
|
||||
{
|
||||
snprintf( HPA_status_text, sizeof( HPA_status_text ), "Hidden sectors found!" );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, HPA_status_text, text_size_data, 130, 210, PDF_RED );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_status == HPA_DISABLED )
|
||||
{
|
||||
snprintf( HPA_status_text, sizeof( HPA_status_text ), "No hidden sectors" );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, HPA_status_text, text_size_data, 130, 210, PDF_DARK_GREEN );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_status == HPA_UNKNOWN )
|
||||
{
|
||||
snprintf( HPA_status_text, sizeof( HPA_status_text ), "Unknown" );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, HPA_status_text, text_size_data, 130, 210, PDF_RED );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_status == HPA_NOT_SUPPORTED_BY_DRIVE )
|
||||
{
|
||||
snprintf( HPA_status_text, sizeof( HPA_status_text ), "No hidden sectors **DDNSHDA" );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, HPA_status_text, text_size_data, 130, 210, PDF_DARK_GREEN );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************
|
||||
* Throughput
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Throughput:", 12, 300, 190, PDF_GRAY );
|
||||
snprintf( throughput_txt, sizeof( throughput_txt ), "%s/sec", c->throughput_txt );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
pdf_add_text( pdf, NULL, throughput_txt, text_size_data, 370, 190, PDF_BLACK );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/********
|
||||
* Errors
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Errors(pass/sync/verify):", 12, 60, 190, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
snprintf( errors, sizeof( errors ), "%llu/%llu/%llu", c->pass_errors, c->fsyncdata_errors, c->verify_errors );
|
||||
if( c->pass_errors != 0 || c->fsyncdata_errors != 0 || c->verify_errors != 0 )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, errors, text_size_data, 195, 190, PDF_RED );
|
||||
}
|
||||
else
|
||||
{
|
||||
pdf_add_text( pdf, NULL, errors, text_size_data, 195, 190, PDF_DARK_GREEN );
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/*************
|
||||
* Information
|
||||
*/
|
||||
pdf_add_text( pdf, NULL, "Information:", 12, 60, 170, PDF_GRAY );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
|
||||
if( !strcmp( c->wipe_status_txt, "ERASED" ) && c->HPA_status == HPA_ENABLED )
|
||||
{
|
||||
pdf_add_ellipse( pdf, NULL, 160, 173, 30, 9, 2, PDF_RED, PDF_BLACK );
|
||||
pdf_add_text( pdf, NULL, "Warning", text_size_data, 140, 170, PDF_YELLOW );
|
||||
|
||||
pdf_add_text( pdf,
|
||||
NULL,
|
||||
"Visible sectors erased as requested, however hidden sectors NOT erased",
|
||||
text_size_data,
|
||||
200,
|
||||
170,
|
||||
PDF_RED );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_status == HPA_UNKNOWN )
|
||||
{
|
||||
pdf_add_ellipse( pdf, NULL, 160, 173, 30, 9, 2, PDF_RED, PDF_BLACK );
|
||||
pdf_add_text( pdf, NULL, "Warning", text_size_data, 140, 170, PDF_YELLOW );
|
||||
|
||||
pdf_add_text( pdf,
|
||||
NULL,
|
||||
"HPA/DCO data unavailable, can not determine hidden sector status.",
|
||||
text_size_data,
|
||||
200,
|
||||
170,
|
||||
PDF_RED );
|
||||
}
|
||||
}
|
||||
|
||||
/* info descripting what bytes erased actually means */
|
||||
pdf_add_text( pdf,
|
||||
NULL,
|
||||
"* bytes erased: The amount of drive that's been erased at least once",
|
||||
text_size_data,
|
||||
60,
|
||||
137,
|
||||
PDF_BLACK );
|
||||
|
||||
/* meaning of abreviation DDNSHPA */
|
||||
if( c->HPA_status == HPA_NOT_SUPPORTED_BY_DRIVE )
|
||||
{
|
||||
pdf_add_text(
|
||||
pdf, NULL, "** DDNSHPA = Drive does not support HPA/DCO", text_size_data, 60, 125, PDF_DARK_GREEN );
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/************************
|
||||
* Technician/Operator ID
|
||||
*/
|
||||
pdf_add_line( pdf, NULL, 50, 120, 550, 120, 1, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Technician/Operator ID", 12, 50, 100, PDF_BLUE );
|
||||
pdf_add_text( pdf, NULL, "Name/ID:", 12, 60, 80, PDF_GRAY );
|
||||
pdf_add_text( pdf, NULL, "Signature:", 12, 300, 100, PDF_BLUE );
|
||||
pdf_add_line( pdf, NULL, 360, 65, 550, 66, 1, PDF_GRAY );
|
||||
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
/* Obtain organisational details from nwipe.conf - See conf.c */
|
||||
setting = config_lookup( &nwipe_cfg, "Organisation_Details" );
|
||||
if( config_setting_lookup_string( setting, "Op_Tech_Name", &op_tech_name ) )
|
||||
{
|
||||
pdf_add_text( pdf, NULL, op_tech_name, text_size_data, 120, 80, PDF_BLACK );
|
||||
}
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
/***************************************
|
||||
* Populate page 2 and 3 with smart data
|
||||
*/
|
||||
nwipe_get_smart_data( c );
|
||||
|
||||
/*****************************
|
||||
* Create the reports filename
|
||||
*
|
||||
* Sanitize the strings that we are going to use to create the report filename
|
||||
* by converting any non alphanumeric characters to an underscore or hyphon
|
||||
*/
|
||||
replace_non_alphanumeric( end_time_text, '-' );
|
||||
replace_non_alphanumeric( c->device_model, '_' );
|
||||
replace_non_alphanumeric( c->device_serial_no, '_' );
|
||||
snprintf( c->PDF_filename,
|
||||
sizeof( c->PDF_filename ),
|
||||
"%s/nwipe_report_%s_Model_%s_Serial_%s.pdf",
|
||||
nwipe_options.PDFreportpath,
|
||||
end_time_text,
|
||||
c->device_model,
|
||||
c->device_serial_no );
|
||||
|
||||
pdf_save( pdf, c->PDF_filename );
|
||||
pdf_destroy( pdf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nwipe_get_smart_data( nwipe_context_t* c )
|
||||
{
|
||||
FILE* fp;
|
||||
|
||||
char* pdata;
|
||||
char page_title[50];
|
||||
|
||||
char smartctl_command[] = "smartctl -a %s";
|
||||
char smartctl_command2[] = "/sbin/smartctl -a %s";
|
||||
char smartctl_command3[] = "/usr/bin/smartctl -a %s";
|
||||
char final_cmd_smartctl[sizeof( smartctl_command3 ) + 256];
|
||||
char result[512];
|
||||
char smartctl_labels_to_anonymize[][18] = {
|
||||
"serial number:", "lu wwn device id:", "logical unit id:", "" /* Don't remove this empty string !, important */
|
||||
};
|
||||
|
||||
int idx, idx2, idx3;
|
||||
int x, y;
|
||||
int set_return_value;
|
||||
int page_number;
|
||||
|
||||
final_cmd_smartctl[0] = 0;
|
||||
|
||||
/* Determine whether we can access smartctl, required if the PATH environment is not setup ! (Debian sid 'su' as
|
||||
* opposed to 'su -' */
|
||||
if( system( "which smartctl > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /sbin/smartctl > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /usr/bin/smartctl > /dev/null 2>&1" ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Command not found. Install smartmontools !" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_smartctl, smartctl_command3, c->device_name );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_smartctl, smartctl_command2, c->device_name );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_smartctl, smartctl_command, c->device_name );
|
||||
}
|
||||
|
||||
if( final_cmd_smartctl[0] != 0 )
|
||||
{
|
||||
fp = popen( final_cmd_smartctl, "r" );
|
||||
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "nwipe_get_smart_data(): Failed to create stream to %s", smartctl_command );
|
||||
|
||||
set_return_value = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 50; // left side of page
|
||||
y = 630; // top row of page
|
||||
page_number = 2;
|
||||
|
||||
/* Create Page 2 of the report. This shows the drives smart data
|
||||
*/
|
||||
page = pdf_append_page( pdf );
|
||||
|
||||
/* Create the header and footer for page 2, the start of the smart data */
|
||||
snprintf( page_title, sizeof( page_title ), "Page %i - Smart Data", page_number );
|
||||
create_header_and_footer( c, page_title );
|
||||
|
||||
/* Read the output a line at a time - output it. */
|
||||
while( fgets( result, sizeof( result ) - 1, fp ) != NULL )
|
||||
{
|
||||
/* Convert the label, i.e everything before the ':' to lower case, it's required to
|
||||
* convert to lower case as smartctl seems to use inconsistent case when labeling
|
||||
* for serial number, i.e mostly it produces labels "Serial Number:" but occasionally
|
||||
* it produces a label "Serial number:" */
|
||||
|
||||
idx = 0;
|
||||
|
||||
while( result[idx] != 0 && result[idx] != ':' )
|
||||
{
|
||||
/* If upper case alpha character, change to lower case */
|
||||
if( result[idx] >= 'A' && result[idx] <= 'Z' )
|
||||
{
|
||||
result[idx] += 32;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
if( nwipe_options.quiet == 1 )
|
||||
{
|
||||
for( idx2 = 0; idx2 < 3; idx2++ )
|
||||
{
|
||||
if( strstr( result, &smartctl_labels_to_anonymize[idx2][0] ) )
|
||||
{
|
||||
if( ( pdata = strstr( result, ":" ) ) )
|
||||
{
|
||||
idx3 = 1;
|
||||
while( pdata[idx3] != 0 )
|
||||
{
|
||||
if( pdata[idx3] != ' ' )
|
||||
{
|
||||
pdata[idx3] = 'X';
|
||||
}
|
||||
idx3++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdf_set_font( pdf, "Courier" );
|
||||
pdf_add_text( pdf, NULL, result, 8, x, y, PDF_BLACK );
|
||||
y -= 9;
|
||||
|
||||
/* Have we reached the bottom of the page yet */
|
||||
if( y < 60 )
|
||||
{
|
||||
/* Append an extra page */
|
||||
page = pdf_append_page( pdf );
|
||||
page_number++;
|
||||
y = 630;
|
||||
|
||||
/* create the header and footer for the next page */
|
||||
snprintf( page_title, sizeof( page_title ), "Page %i - Smart Data", page_number );
|
||||
create_header_and_footer( c, page_title );
|
||||
}
|
||||
}
|
||||
set_return_value = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
set_return_value = 1;
|
||||
}
|
||||
return set_return_value;
|
||||
}
|
||||
|
||||
void create_header_and_footer( nwipe_context_t* c, char* page_title )
|
||||
{
|
||||
/**************************************************************************
|
||||
* Create header and footer on most recently added page, with the exception
|
||||
* of the green tick/red icon which is set from the 'status' section below.
|
||||
*/
|
||||
pdf_add_text_wrap( pdf, NULL, pdf_footer, 12, 0, 30, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
pdf_add_line( pdf, NULL, 50, 50, 550, 50, 3, PDF_BLACK );
|
||||
pdf_add_line( pdf, NULL, 50, 650, 550, 650, 3, PDF_BLACK );
|
||||
pdf_add_image_data( pdf, NULL, 45, 665, 100, 100, bin2c_shred_db_jpg, 27063 );
|
||||
pdf_set_font( pdf, "Helvetica-Bold" );
|
||||
snprintf( model_header, sizeof( model_header ), " %s: %s ", "Model", c->device_model );
|
||||
pdf_add_text_wrap( pdf, NULL, model_header, 14, 0, 755, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
snprintf( serial_header, sizeof( serial_header ), " %s: %s ", "S/N", c->device_serial_no );
|
||||
pdf_add_text_wrap( pdf, NULL, serial_header, 14, 0, 735, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
pdf_set_font( pdf, "Helvetica" );
|
||||
|
||||
pdf_add_text_wrap( pdf, NULL, "Disk Erasure Report", 24, 0, 695, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
snprintf( barcode, sizeof( barcode ), "%s:%s", c->device_model, c->device_serial_no );
|
||||
pdf_add_text_wrap( pdf, NULL, page_title, 14, 0, 670, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
|
||||
pdf_add_barcode( pdf, NULL, PDF_BARCODE_128A, 100, 790, 400, 25, barcode, PDF_BLACK );
|
||||
|
||||
/**********************************************************
|
||||
* Display the appropriate status icon, top right on page on
|
||||
* most recently added page.
|
||||
*/
|
||||
switch( status_icon )
|
||||
{
|
||||
case STATUS_ICON_GREEN_TICK:
|
||||
|
||||
/* Display the green tick icon in the header */
|
||||
pdf_add_image_data( pdf, NULL, 450, 665, 100, 100, bin2c_te_jpg, 54896 );
|
||||
break;
|
||||
|
||||
case STATUS_ICON_YELLOW_EXCLAMATION:
|
||||
|
||||
/* Display the yellow exclamation icon in the header */
|
||||
pdf_add_image_data( pdf, NULL, 450, 665, 100, 100, bin2c_nwipe_exclamation_jpg, 65791 );
|
||||
break;
|
||||
|
||||
case STATUS_ICON_RED_CROSS:
|
||||
|
||||
// Display the red cross in the header
|
||||
pdf_add_image_data( pdf, NULL, 450, 665, 100, 100, bin2c_redcross_jpg, 60331 );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
52
src/create_pdf.h
Normal file
52
src/create_pdf.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*.
|
||||
* create_pdf.h: The header file for the pdf creation routines
|
||||
*
|
||||
* Copyright https://github.com/PartialVolume/shredos.x86_64
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CREATE_PDF_H_
|
||||
#define CREATE_PDF_H_
|
||||
|
||||
#define MAX_PDF_FOOTER_TEXT_LENGTH 100
|
||||
|
||||
#define STATUS_ICON_GREEN_TICK 1
|
||||
#define STATUS_ICON_YELLOW_EXCLAMATION 2
|
||||
#define STATUS_ICON_RED_CROSS 3
|
||||
|
||||
/* Additional colors that supplement the standard colors in pdfgen.h
|
||||
*/
|
||||
/*! Utility macro to provide gray */
|
||||
#define PDF_DARK_GREEN PDF_RGB( 0, 0x64, 0 )
|
||||
|
||||
/*! Utility macro to provide gray */
|
||||
#define PDF_GRAY PDF_RGB( 0x5A, 0x5A, 0x5A )
|
||||
|
||||
/*! Utility macro to provide gray */
|
||||
#define PDF_YELLOW PDF_RGB( 0xFF, 0xFF, 0x5A )
|
||||
|
||||
/**
|
||||
* Create the disk erase report in PDF format
|
||||
* @param pointer to a drive context
|
||||
* @return returns 0 on success < 1 on error
|
||||
*/
|
||||
int create_pdf( nwipe_context_t* ptr );
|
||||
|
||||
int nwipe_get_smart_data( nwipe_context_t* );
|
||||
|
||||
void create_header_and_footer( nwipe_context_t*, char* );
|
||||
|
||||
#endif /* CREATE_PDF_H_ */
|
||||
713
src/customers.c
Normal file
713
src/customers.c
Normal file
@@ -0,0 +1,713 @@
|
||||
/*
|
||||
* ****************************************************************************
|
||||
* customers.c: Functions related to customer processing for the PDF erasure *
|
||||
* certificate. *
|
||||
* ****************************************************************************
|
||||
*
|
||||
* Copyright PartialVolume <https://github.com/PartialVolume>.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
#include "gui.h"
|
||||
#include "logging.h"
|
||||
#include "conf.h"
|
||||
#include "customers.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
void customer_processes( int mode )
|
||||
{
|
||||
/* This function reads the customers.csv file, counts the number of lines,
|
||||
* converts line feeds to NULL and constructs a array of pointers that point
|
||||
* to the variable length strings.
|
||||
*
|
||||
* Depending on the value of mode the pointer array is passed to either
|
||||
* the select_customers() or delete_customer() functions.
|
||||
*/
|
||||
|
||||
int idx;
|
||||
int idx2;
|
||||
FILE* fptr;
|
||||
|
||||
struct stat st;
|
||||
intmax_t size = 0;
|
||||
int lines;
|
||||
int list_idx;
|
||||
int current_list_size;
|
||||
|
||||
size_t result_size;
|
||||
|
||||
extern char nwipe_customers_file[];
|
||||
|
||||
/* Determine size of customers.csv file */
|
||||
stat( nwipe_customers_file, &st );
|
||||
size = st.st_size;
|
||||
current_list_size = 0;
|
||||
|
||||
nwipe_customers_buffer_t raw_buffer = (nwipe_customers_buffer_t) calloc( 1, size + 1 );
|
||||
|
||||
/* Allocate storage for the contents of customers.csv */
|
||||
nwipe_customers_buffer_t buffer = (nwipe_customers_buffer_t) calloc( 1, size + 1 );
|
||||
|
||||
/* Allocate storage for the processed version of customers.csv,
|
||||
* i.e we convert the csv format to strings without the quotes
|
||||
* and semi colon delimiters
|
||||
*/
|
||||
nwipe_customers_pointers_t list = (nwipe_customers_pointers_t) calloc( 1, sizeof( char* ) );
|
||||
current_list_size += sizeof( char* );
|
||||
|
||||
/* Open customers.csv */
|
||||
if( ( fptr = fopen( nwipe_customers_file, "rb" ) ) == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to open %s", nwipe_customers_file );
|
||||
free( buffer );
|
||||
free( *list );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read the customers.csv file and populate the list array with the data */
|
||||
result_size = fread( raw_buffer, size, 1, fptr );
|
||||
|
||||
fclose( fptr );
|
||||
|
||||
/* Validate csv contents. With the exception of line feeds,
|
||||
* remove non printable characters and move to a secondary buffer.
|
||||
*/
|
||||
idx = 0;
|
||||
idx2 = 0;
|
||||
while( idx < size )
|
||||
{
|
||||
if( ( raw_buffer[idx] > 0x1F && raw_buffer[idx] < 0x7F ) || raw_buffer[idx] == 0x0A )
|
||||
{
|
||||
/* copy printable characters and line feeds */
|
||||
buffer[idx2++] = raw_buffer[idx];
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Construct a array of pointers that point to each line of the csv file
|
||||
*/
|
||||
idx = 0;
|
||||
lines = 0;
|
||||
list_idx = 0;
|
||||
|
||||
while( idx < size )
|
||||
{
|
||||
if( buffer[idx] == 0x0A )
|
||||
{
|
||||
buffer[idx] = 0;
|
||||
|
||||
/* increment the line counter, but don't count
|
||||
* the first line as that is the csv header line.
|
||||
*/
|
||||
if( idx != 0 )
|
||||
{
|
||||
lines++;
|
||||
|
||||
/* Change the line feed to a NULL, string terminator */
|
||||
buffer[idx] = 0;
|
||||
|
||||
/* Save the pointer to the first data line of the csv. */
|
||||
list[list_idx++] = &buffer[idx + 1];
|
||||
|
||||
current_list_size += sizeof( char* );
|
||||
|
||||
/* Expand allocated memory by the size of one pointer */
|
||||
if( ( list = realloc( list, current_list_size ) ) == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to realloc customer list array, out of memory?" );
|
||||
break;
|
||||
}
|
||||
current_list_size += sizeof( char* );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Replace colons with commas */
|
||||
if( buffer[idx] == ';' )
|
||||
{
|
||||
buffer[idx] = ',';
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Sync lines variable to actual number of lines */
|
||||
if( lines > 0 )
|
||||
lines--;
|
||||
|
||||
if( idx == size )
|
||||
{
|
||||
/* makesure the very last entry is NULL terminated */
|
||||
buffer[idx] = 0;
|
||||
}
|
||||
|
||||
/* Select the requested mode, customer or delete customer.
|
||||
*/
|
||||
switch( mode )
|
||||
{
|
||||
case SELECT_CUSTOMER:
|
||||
select_customers( lines, list );
|
||||
break;
|
||||
|
||||
case DELETE_CUSTOMER:
|
||||
delete_customer( lines, list );
|
||||
break;
|
||||
}
|
||||
|
||||
free( raw_buffer );
|
||||
free( buffer );
|
||||
}
|
||||
|
||||
void select_customers( int count, char** customer_list_array )
|
||||
{
|
||||
int selected_entry = 0;
|
||||
char window_title[] = " Select Customer For PDF Report ";
|
||||
|
||||
/* Display the customer selection window */
|
||||
nwipe_gui_list( count, window_title, customer_list_array, &selected_entry );
|
||||
|
||||
/* Save the selected customer details to nwipe's config file /etc/nwipe/nwipe.conf
|
||||
* If selected entry equals 0, then the customer did not select an entry so skip save.
|
||||
*/
|
||||
if( selected_entry != 0 )
|
||||
{
|
||||
save_selected_customer( &customer_list_array[selected_entry - 1] );
|
||||
}
|
||||
}
|
||||
|
||||
void delete_customer( int count, char** customer_list_array )
|
||||
{
|
||||
char window_title[] = " Delete Customer ";
|
||||
int selected_entry = 0;
|
||||
|
||||
nwipe_gui_list( count, window_title, customer_list_array, &selected_entry );
|
||||
|
||||
if( selected_entry != 0 )
|
||||
{
|
||||
delete_customer_csv_entry( &selected_entry );
|
||||
}
|
||||
}
|
||||
|
||||
void write_customer_csv_entry( char* customer_name,
|
||||
char* customer_address,
|
||||
char* customer_contact_name,
|
||||
char* customer_contact_phone )
|
||||
{
|
||||
/**
|
||||
* Write the attached strings in csv format to the first
|
||||
* line after the header (line 2 of file)
|
||||
*/
|
||||
|
||||
FILE* fptr = 0;
|
||||
FILE* fptr2 = 0;
|
||||
|
||||
size_t result_size;
|
||||
|
||||
/* General index variables */
|
||||
int idx1, idx2, idx3;
|
||||
|
||||
/* Length of the new customer line */
|
||||
int csv_line_length;
|
||||
|
||||
/* Size of the new buffer that holds old contents plus new entry */
|
||||
int new_customers_buffer_size;
|
||||
|
||||
struct stat st;
|
||||
|
||||
extern char nwipe_customers_file[];
|
||||
extern char nwipe_customers_file_backup[];
|
||||
extern char nwipe_customers_file_backup_tmp[];
|
||||
|
||||
intmax_t existing_file_size = 0;
|
||||
|
||||
/* pointer to the new customer entry in csv format. */
|
||||
char* csv_buffer = 0;
|
||||
|
||||
/* pointer to the buffer containing the existing customer file */
|
||||
char* customers_buffer = 0;
|
||||
|
||||
/* pointer to the buffer containing the existing customer file plus the new entry */
|
||||
char* new_customers_buffer = 0;
|
||||
|
||||
size_t new_customers_buffer_length;
|
||||
|
||||
/* Determine length of all four strings and malloc sufficient storage + 12 = 8 quotes + three colons + null */
|
||||
csv_line_length = strlen( customer_name ) + strlen( customer_address ) + strlen( customer_contact_name )
|
||||
+ strlen( customer_contact_phone ) + 12;
|
||||
if( !( csv_buffer = calloc( 1, csv_line_length == 0 ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "func:nwipe_gui_add_customer:csv_buffer, calloc returned NULL " );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Determine current size of the csv file containing the customers */
|
||||
stat( nwipe_customers_file, &st );
|
||||
existing_file_size = st.st_size;
|
||||
|
||||
/* calloc sufficient storage to hold the existing customers file */
|
||||
if( !( customers_buffer = calloc( 1, existing_file_size + 1 ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "func:nwipe_gui_add_customer:customers_buffer, calloc returned NULL " );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create a third buffer which is the combined size of the previous two, i.e existing file size, plus the
|
||||
* new customer entry + 1 (NULL) */
|
||||
new_customers_buffer_size = existing_file_size + csv_line_length + 1;
|
||||
|
||||
if( !( new_customers_buffer = calloc( 1, new_customers_buffer_size ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "func:nwipe_gui_add_customer:customers_buffer, calloc returned NULL " );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the whole of customers.csv file into customers_buffer */
|
||||
if( ( fptr = fopen( nwipe_customers_file, "rb" ) ) == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to open %s", nwipe_customers_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the customers.csv file and populate the list array with the data */
|
||||
if( ( result_size = fread( customers_buffer, existing_file_size, 1, fptr ) ) != 1 )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR,
|
||||
"func:nwipe_gui_add_customer:Error reading customers file, # bytes read not as expected "
|
||||
"%i bytes",
|
||||
result_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* --------------------------------------------------------------------
|
||||
* Read the first line which is the csv header from the existing customer
|
||||
* buffer & write to the new buffer.
|
||||
*/
|
||||
|
||||
idx1 = 0; // Index for the current csv buffer
|
||||
idx2 = 0; // Index for the new csv buffer
|
||||
idx3 = 0; // Index for new customer fields
|
||||
|
||||
while( idx1 < existing_file_size && idx2 < new_customers_buffer_size )
|
||||
{
|
||||
if( customers_buffer[idx1] != LINEFEED )
|
||||
{
|
||||
new_customers_buffer[idx2++] = customers_buffer[idx1++];
|
||||
}
|
||||
else
|
||||
{
|
||||
new_customers_buffer[idx2++] = LINEFEED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* Copy the new customer name entry so it is immediately after the csv header
|
||||
*/
|
||||
|
||||
/* Start with first entries opening quote */
|
||||
new_customers_buffer[idx2++] = '"';
|
||||
|
||||
/* Copy the customer_name string */
|
||||
while( idx3 < FIELD_LENGTH && idx2 < new_customers_buffer_size && customer_name[idx3] != 0 )
|
||||
{
|
||||
new_customers_buffer[idx2++] = customer_name[idx3++];
|
||||
}
|
||||
|
||||
/* Close customer name field with a quote */
|
||||
new_customers_buffer[idx2++] = '"';
|
||||
|
||||
/* Insert field delimiters, we use a semi-colon, not a comma ';' */
|
||||
new_customers_buffer[idx2++] = ';';
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Copy the new customer address entry so it is immediately after the csv header
|
||||
*/
|
||||
|
||||
idx3 = 0;
|
||||
|
||||
/* Start with first entries opening quote */
|
||||
new_customers_buffer[idx2++] = '\"';
|
||||
|
||||
/* Copy the customer_name string */
|
||||
while( idx3 < FIELD_LENGTH && idx2 < new_customers_buffer_size && customer_address[idx3] != 0 )
|
||||
{
|
||||
new_customers_buffer[idx2++] = customer_address[idx3++];
|
||||
}
|
||||
|
||||
/* Close customer name field with a quote */
|
||||
new_customers_buffer[idx2++] = '\"';
|
||||
|
||||
/* Insert field delimiters, we use a semi-colon, not a comma ';' */
|
||||
new_customers_buffer[idx2++] = ';';
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Copy the new customer contact name entry so it is immediately after the csv header
|
||||
*/
|
||||
|
||||
idx3 = 0;
|
||||
|
||||
/* Start with first entries opening quote */
|
||||
new_customers_buffer[idx2++] = '\"';
|
||||
|
||||
/* Copy the customer_name string */
|
||||
while( idx3 < FIELD_LENGTH && idx2 < new_customers_buffer_size
|
||||
&& customer_contact_name[idx3] != 0 )
|
||||
{
|
||||
new_customers_buffer[idx2++] = customer_contact_name[idx3++];
|
||||
}
|
||||
|
||||
/* Close customer name field with a quote */
|
||||
new_customers_buffer[idx2++] = '\"';
|
||||
|
||||
/* Insert field delimiters, we use a semi-colon, not a comma ';' */
|
||||
new_customers_buffer[idx2++] = ';';
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Copy the new customer contact phone entry so it is immediately after the csv header
|
||||
*/
|
||||
|
||||
idx3 = 0;
|
||||
|
||||
/* Start with first entries opening quote */
|
||||
new_customers_buffer[idx2++] = '\"';
|
||||
|
||||
/* Copy the customer_name string */
|
||||
while( idx3 < FIELD_LENGTH && idx2 < new_customers_buffer_size
|
||||
&& customer_contact_phone[idx3] != 0 )
|
||||
{
|
||||
new_customers_buffer[idx2++] = customer_contact_phone[idx3++];
|
||||
}
|
||||
|
||||
/* Close customer name field with a quote */
|
||||
new_customers_buffer[idx2++] = '\"';
|
||||
|
||||
/* Insert a line feed to finish the new entry */
|
||||
new_customers_buffer[idx2++] = LINEFEED;
|
||||
|
||||
/* skip any LINEFEEDS in the existing customer entry as we just inserted one */
|
||||
while( customers_buffer[idx1] != 0 && customers_buffer[idx1] == LINEFEED )
|
||||
{
|
||||
idx1++;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------
|
||||
* Now copy the existing customer entries, if any, immediately after the new entry
|
||||
*/
|
||||
|
||||
while( idx1 < existing_file_size && idx2 < new_customers_buffer_size )
|
||||
{
|
||||
/* Removes any nulls when copying and pasting, which would break this process? */
|
||||
if( customers_buffer[idx1] == 0 )
|
||||
{
|
||||
while( idx1 < existing_file_size && customers_buffer[idx1] == 0 )
|
||||
{
|
||||
idx1++;
|
||||
}
|
||||
}
|
||||
new_customers_buffer[idx2++] = customers_buffer[idx1++];
|
||||
}
|
||||
|
||||
/* Rename the customers.csv file to customers.csv.backup */
|
||||
if( rename( nwipe_customers_file, nwipe_customers_file_backup_tmp ) != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Unable to rename %s to %s",
|
||||
nwipe_customers_file,
|
||||
nwipe_customers_file_backup_tmp );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create/open the customers.csv file */
|
||||
if( ( fptr2 = fopen( nwipe_customers_file, "wb" ) ) == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to open %s", nwipe_customers_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* write the new customers.csv file */
|
||||
new_customers_buffer_length = strlen( new_customers_buffer );
|
||||
|
||||
if( ( result_size = fwrite(
|
||||
new_customers_buffer, sizeof( char ), new_customers_buffer_length, fptr2 ) )
|
||||
!= new_customers_buffer_length )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR,
|
||||
"func:write_customer_csv_entry:fwrite: Error result_size = %i not as expected",
|
||||
result_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove the customer.csv.backup file if it exists */
|
||||
if( remove( nwipe_customers_file_backup ) != 0 )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR, "Unable to remove %s", nwipe_customers_file_backup_tmp );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Rename the customers.csv.backup.tmp file to customers.csv.backup */
|
||||
if( rename( nwipe_customers_file_backup_tmp, nwipe_customers_file_backup )
|
||||
!= 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Unable to rename %s to %s",
|
||||
nwipe_customers_file,
|
||||
nwipe_customers_file_backup_tmp );
|
||||
}
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"Succesfully write new customer entry to %s",
|
||||
nwipe_customers_file );
|
||||
}
|
||||
}
|
||||
fclose( fptr2 );
|
||||
}
|
||||
}
|
||||
fclose( fptr );
|
||||
}
|
||||
}
|
||||
free( new_customers_buffer );
|
||||
}
|
||||
free( customers_buffer );
|
||||
}
|
||||
free( csv_buffer );
|
||||
}
|
||||
}
|
||||
|
||||
void delete_customer_csv_entry( int* selected_entry )
|
||||
{
|
||||
/**
|
||||
* Deletes a line from the csv file. The line to be deleted is determined
|
||||
* by the value of selected_entry
|
||||
*/
|
||||
FILE* fptr = 0;
|
||||
FILE* fptr2 = 0;
|
||||
|
||||
size_t result_size;
|
||||
|
||||
struct stat st;
|
||||
|
||||
extern char nwipe_customers_file[];
|
||||
extern char nwipe_customers_file_backup[];
|
||||
extern char nwipe_customers_file_backup_tmp[];
|
||||
|
||||
intmax_t existing_file_size = 0;
|
||||
|
||||
int linecount;
|
||||
|
||||
/* General index variables */
|
||||
int idx1, idx2, idx3;
|
||||
|
||||
/* pointer to the buffer containing the existing customer file */
|
||||
char* customers_buffer = 0;
|
||||
|
||||
/* pointer to the buffer containing the existing customer minus the deleted entry */
|
||||
char* new_customers_buffer = 0;
|
||||
|
||||
int status_flag = 0;
|
||||
|
||||
size_t new_customers_buffer_length;
|
||||
|
||||
/* Determine current size of the csv file containing the customers */
|
||||
stat( nwipe_customers_file, &st );
|
||||
existing_file_size = st.st_size;
|
||||
|
||||
/* calloc sufficient storage to hold the existing customers file */
|
||||
if( !( customers_buffer = calloc( 1, existing_file_size + 1 ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"func:nwipe_gui_delete_customer_csv_entry:customers_buffer, calloc returned NULL " );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create a second buffer which is identical in size to the first, it will store the customer
|
||||
* csv file minus the one selected entry
|
||||
*/
|
||||
|
||||
if( !( new_customers_buffer = calloc( 1, existing_file_size + 1 ) ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"func:nwipe_gui_delete_customer_csv_entry:customers_buffer, calloc returned NULL " );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the whole of customers.csv file into customers_buffer */
|
||||
if( ( fptr = fopen( nwipe_customers_file, "rb" ) ) == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"func:nwipe_gui_delete_customer_csv_entry:Unable to open %s",
|
||||
nwipe_customers_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the customers.csv file and populate the list array with the data */
|
||||
if( ( result_size = fread( customers_buffer, existing_file_size, 1, fptr ) ) != 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"func:nwipe_gui_delete_customer_csv_entry:Error reading customers file, # elements read "
|
||||
"not as expected "
|
||||
"%i elements",
|
||||
result_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* --------------------------------------------------------------------
|
||||
* Read the first line which is the csv header from the existing customer
|
||||
* buffer & write to the new buffer.
|
||||
*/
|
||||
|
||||
idx1 = 0; // Index for the current csv buffer
|
||||
idx2 = 0; // Index for the new csv buffer
|
||||
|
||||
linecount = 1; // count the lines in the csv file starting at line 1
|
||||
|
||||
while( idx1 < existing_file_size && idx2 < existing_file_size )
|
||||
{
|
||||
if( customers_buffer[idx1] != LINEFEED )
|
||||
{
|
||||
new_customers_buffer[idx2++] = customers_buffer[idx1++];
|
||||
}
|
||||
else
|
||||
{
|
||||
new_customers_buffer[idx2++] = customers_buffer[idx1++];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------
|
||||
* Now copy the existing customer entries, counting the lines as we go and when we
|
||||
* get to the the line selected for deletion we skip over it and then carry on
|
||||
* copying.
|
||||
*/
|
||||
|
||||
while( idx1 < existing_file_size && idx2 < existing_file_size )
|
||||
{
|
||||
/* Don't copy nulls */
|
||||
if( customers_buffer[idx1] == 0 )
|
||||
{
|
||||
idx1++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Is this the line to delete? */
|
||||
if( linecount == *selected_entry )
|
||||
{
|
||||
/* skip all the characters in this line */
|
||||
while( idx1 < existing_file_size && customers_buffer[idx1] != LINEFEED )
|
||||
{
|
||||
idx1++;
|
||||
}
|
||||
|
||||
/* skip the trailing linefeed if it exists, may not exist if last line */
|
||||
if( customers_buffer[idx1] == LINEFEED )
|
||||
{
|
||||
idx1++;
|
||||
}
|
||||
linecount++;
|
||||
nwipe_log( NWIPE_LOG_INFO, "Deleted customer entry from cache" );
|
||||
status_flag = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Is the character a LINEFEED? */
|
||||
if( customers_buffer[idx1] == LINEFEED )
|
||||
{
|
||||
linecount++;
|
||||
}
|
||||
|
||||
/* Copy a character */
|
||||
new_customers_buffer[idx2++] = customers_buffer[idx1++];
|
||||
}
|
||||
}
|
||||
|
||||
/* Rename the customers.csv file to customers.csv.backup */
|
||||
if( rename( nwipe_customers_file, nwipe_customers_file_backup_tmp ) != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"func:delete_customer_csv_entry:Unable to rename %s to %s",
|
||||
nwipe_customers_file,
|
||||
nwipe_customers_file_backup_tmp );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create/open the customers.csv file */
|
||||
if( ( fptr2 = fopen( nwipe_customers_file, "wb" ) ) == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"func:delete_customer_csv_entry:Unable to open %s",
|
||||
nwipe_customers_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* write the new customers.csv file */
|
||||
new_customers_buffer_length = strlen( new_customers_buffer );
|
||||
|
||||
if( ( result_size = fwrite(
|
||||
new_customers_buffer, sizeof( char ), new_customers_buffer_length, fptr2 ) )
|
||||
!= new_customers_buffer_length )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR,
|
||||
"func:delete_customer_csv_entry:fwrite: Error result_size = %i not as expected",
|
||||
result_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove the customer.csv.backup file if it exists */
|
||||
if( remove( nwipe_customers_file_backup ) != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"func:delete_customer_csv_entry:Unable to remove %s",
|
||||
nwipe_customers_file_backup_tmp );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Rename the customers.csv.backup.tmp file to customers.csv.backup */
|
||||
if( rename( nwipe_customers_file_backup_tmp, nwipe_customers_file_backup ) != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"func:delete_customer_csv_entry:Unable to rename %s to %s",
|
||||
nwipe_customers_file,
|
||||
nwipe_customers_file_backup_tmp );
|
||||
}
|
||||
if( status_flag == 1 )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_INFO, "Deleted customer entry in %s", nwipe_customers_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"Failed to delete customer entry in %s",
|
||||
nwipe_customers_file );
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose( fptr2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose( fptr );
|
||||
}
|
||||
free( new_customers_buffer );
|
||||
}
|
||||
free( customers_buffer );
|
||||
}
|
||||
}
|
||||
42
src/customers.h
Normal file
42
src/customers.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* ****************************************************************************
|
||||
* customers.h: Functions related to customer processing for the PDF erasure *
|
||||
* certificate. *
|
||||
* ****************************************************************************
|
||||
*
|
||||
* Copyright PartialVolume <https://github.com/PartialVolume>.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CUSTOMERS_H_INCLUDED
|
||||
#define CUSTOMERS_H_INCLUDED
|
||||
|
||||
void customer_processes( int );
|
||||
void select_customers( int, char** );
|
||||
void delete_customer();
|
||||
void add_customer();
|
||||
void write_customer_csv_entry( char*, char*, char*, char* );
|
||||
void delete_customer_csv_entry( int* );
|
||||
|
||||
typedef char* nwipe_customers_buffer_t;
|
||||
typedef char** nwipe_customers_pointers_t;
|
||||
|
||||
#define SELECT_CUSTOMER 1
|
||||
#define DELETE_CUSTOMER 2
|
||||
|
||||
#define LINEFEED 0x0A
|
||||
|
||||
#endif // CUSTOMERS_H_INCLUDED
|
||||
180
src/device.c
180
src/device.c
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
@@ -40,6 +41,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include "hpa_dco.h"
|
||||
#include "miscellaneous.h"
|
||||
|
||||
#include <parted/parted.h>
|
||||
#include <parted/debug.h>
|
||||
@@ -55,7 +58,7 @@ int nwipe_device_scan( nwipe_context_t*** c )
|
||||
* Scans the filesystem for storage device names.
|
||||
*
|
||||
* @parameter device_names A reference to a null array pointer.
|
||||
* @modifies device_names Populates device_names with an array of nwipe_contect_t
|
||||
* @modifies device_names Populates device_names with an array of nwipe_context_t
|
||||
* @returns The number of strings in the device_names array.
|
||||
*
|
||||
*/
|
||||
@@ -67,6 +70,9 @@ int nwipe_device_scan( nwipe_context_t*** c )
|
||||
|
||||
while( ( dev = ped_device_get_next( dev ) ) )
|
||||
{
|
||||
/* to have some progress indication. can help if there are many/slow disks */
|
||||
fprintf( stderr, "." );
|
||||
|
||||
if( check_device( c, dev, dcount ) )
|
||||
dcount++;
|
||||
|
||||
@@ -85,17 +91,6 @@ int nwipe_device_scan( nwipe_context_t*** c )
|
||||
|
||||
int nwipe_device_get( nwipe_context_t*** c, char** devnamelist, int ndevnames )
|
||||
{
|
||||
/**
|
||||
* Gets information about devices
|
||||
*
|
||||
* @parameter device_names A reference to a null array pointer.
|
||||
* @parameter devnamelist An array of string pointers to the device names
|
||||
* @parameter ndevnames Number of elements in devnamelist
|
||||
* @modifies device_names Populates device_names with an array of nwipe_contect_t
|
||||
* @returns The number of strings in the device_names array.
|
||||
*
|
||||
*/
|
||||
|
||||
PedDevice* dev = NULL;
|
||||
|
||||
int i;
|
||||
@@ -103,6 +98,8 @@ int nwipe_device_get( nwipe_context_t*** c, char** devnamelist, int ndevnames )
|
||||
|
||||
for( i = 0; i < ndevnames; i++ )
|
||||
{
|
||||
/* to have some progress indication. can help if there are many/slow disks */
|
||||
fprintf( stderr, "." );
|
||||
|
||||
dev = ped_device_get( devnamelist[i] );
|
||||
if( !dev )
|
||||
@@ -134,14 +131,16 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
int fd;
|
||||
int idx;
|
||||
int r;
|
||||
char tmp_serial[21];
|
||||
char tmp_serial[NWIPE_SERIALNUMBER_LENGTH + 1];
|
||||
nwipe_device_t bus;
|
||||
int is_ssd;
|
||||
int check_HPA; // a flag that indicates whether we check for a HPA on this device
|
||||
|
||||
bus = 0;
|
||||
|
||||
/* Check whether this drive is on the excluded drive list ? */
|
||||
idx = 0;
|
||||
while( idx < 10 )
|
||||
while( idx < MAX_NUMBER_EXCLUDED_DRIVES )
|
||||
{
|
||||
if( !strcmp( dev->path, nwipe_options.exclude[idx++] ) )
|
||||
{
|
||||
@@ -157,7 +156,7 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
if( nwipe_options.nousb )
|
||||
{
|
||||
/* retrieve bus and drive serial number, HOWEVER we are only interested in the bus at this time */
|
||||
r = nwipe_get_device_bus_type_and_serialno( dev->path, &bus, tmp_serial );
|
||||
r = nwipe_get_device_bus_type_and_serialno( dev->path, &bus, &is_ssd, tmp_serial );
|
||||
|
||||
/* See nwipe_get_device_bus_type_and_serialno() function for meaning of these codes */
|
||||
if( r == 0 || ( r >= 3 && r <= 6 ) )
|
||||
@@ -208,6 +207,9 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
next_device->device_model = dev->model;
|
||||
remove_ATA_prefix( next_device->device_model );
|
||||
|
||||
/* Some USB adapters have drive model endian swapped, pattern match and fix */
|
||||
fix_endian_model_names( next_device->device_model );
|
||||
|
||||
/* full device name, i.e. /dev/sda */
|
||||
next_device->device_name = dev->path;
|
||||
|
||||
@@ -227,6 +229,11 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
}
|
||||
|
||||
next_device->device_size = dev->length * dev->sector_size;
|
||||
next_device->device_sector_size = dev->sector_size; // logical sector size
|
||||
next_device->device_block_size = dev->sector_size; // set as logical but could be a multiple of logical sector size
|
||||
next_device->device_phys_sector_size = dev->phys_sector_size; // physical sector size
|
||||
next_device->device_size_in_sectors = next_device->device_size / next_device->device_sector_size;
|
||||
next_device->device_size_in_512byte_sectors = next_device->device_size / 512;
|
||||
Determine_C_B_nomenclature( next_device->device_size, next_device->device_size_txt, NWIPE_DEVICE_SIZE_TXT_LENGTH );
|
||||
next_device->device_size_text = next_device->device_size_txt;
|
||||
next_device->result = -2;
|
||||
@@ -248,19 +255,27 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
ioctl( fd, HDIO_GET_IDENTITY, &next_device->identity );
|
||||
close( fd );
|
||||
|
||||
for( idx = 0; idx < 20; idx++ )
|
||||
for( idx = 0; idx < NWIPE_SERIALNUMBER_LENGTH; idx++ )
|
||||
{
|
||||
next_device->device_serial_no[idx] = next_device->identity.serial_no[idx];
|
||||
if( isascii( next_device->identity.serial_no[idx] ) && !iscntrl( next_device->identity.serial_no[idx] ) )
|
||||
{
|
||||
next_device->device_serial_no[idx] = next_device->identity.serial_no[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate the string.
|
||||
next_device->device_serial_no[20] = 0;
|
||||
next_device->device_serial_no[idx] = 0;
|
||||
|
||||
// Remove leading/trailing whitespace from serial number and left justify.
|
||||
trim( (char*) next_device->device_serial_no );
|
||||
|
||||
/* if we couldn't obtain serial number by using the above method .. try this */
|
||||
r = nwipe_get_device_bus_type_and_serialno( next_device->device_name, &next_device->device_type, tmp_serial );
|
||||
r = nwipe_get_device_bus_type_and_serialno(
|
||||
next_device->device_name, &next_device->device_type, &next_device->device_is_ssd, tmp_serial );
|
||||
|
||||
/* If serial number & bus retrieved (0) OR unsupported USB bus identified (5) */
|
||||
if( r == 0 || r == 5 )
|
||||
@@ -268,7 +283,7 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
/* If the serial number hasn't already been populated */
|
||||
if( next_device->device_serial_no[0] == 0 )
|
||||
{
|
||||
strcpy( next_device->device_serial_no, tmp_serial );
|
||||
strncpy( next_device->device_serial_no, tmp_serial, NWIPE_SERIALNUMBER_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,27 +292,53 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
{
|
||||
if( next_device->device_serial_no[0] == 0 )
|
||||
{
|
||||
strcpy( next_device->device_serial_no, "???????????????" );
|
||||
strncpy( next_device->device_serial_no, "????????????????????", NWIPE_SERIALNUMBER_LENGTH + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( next_device->device_serial_no, "XXXXXXXXXXXXXXX" );
|
||||
strncpy( next_device->device_serial_no, "XXXXXXXXXXXXXXXXXXXX", NWIPE_SERIALNUMBER_LENGTH + 1 );
|
||||
}
|
||||
}
|
||||
/* strncpy would have copied the null terminator BUT just to be sure, just in case somebody changes the length
|
||||
* of those strings we should explicitly terminate the string */
|
||||
next_device->device_serial_no[NWIPE_SERIALNUMBER_LENGTH] = 0;
|
||||
|
||||
/* Initialise the variables that toggle the [size][temp c] with [HPA status]
|
||||
* Not currently used, but may be used in the future or for other purposes
|
||||
*/
|
||||
next_device->HPA_toggle_time = time( NULL );
|
||||
next_device->HPA_display_toggle_state = 0;
|
||||
|
||||
/* Initialise the HPA variables for this device
|
||||
*/
|
||||
next_device->HPA_reported_set = 0;
|
||||
next_device->HPA_reported_real = 0;
|
||||
next_device->DCO_reported_real_max_sectors = 0;
|
||||
next_device->HPA_status = HPA_NOT_APPLICABLE;
|
||||
|
||||
/* All device strings should be 4 characters, prefix with space if under 4 characters
|
||||
* We also set a switch for certain devices to check for the host protected area (HPA)
|
||||
*/
|
||||
check_HPA = 0;
|
||||
|
||||
// WARNING TEMP LINE WARNING
|
||||
// next_device->device_type = NWIPE_DEVICE_ATA;
|
||||
|
||||
/* All device strings should be 4 characters, prefix with space if under 4 characters */
|
||||
switch( next_device->device_type )
|
||||
{
|
||||
case NWIPE_DEVICE_UNKNOWN:
|
||||
strcpy( next_device->device_type_str, " UNK" );
|
||||
check_HPA = 1;
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_IDE:
|
||||
strcpy( next_device->device_type_str, " IDE" );
|
||||
check_HPA = 1;
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_SCSI:
|
||||
strcpy( next_device->device_type_str, " SCSI" );
|
||||
check_HPA = 1;
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_COMPAQ:
|
||||
@@ -306,6 +347,7 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
|
||||
case NWIPE_DEVICE_USB:
|
||||
strcpy( next_device->device_type_str, " USB" );
|
||||
check_HPA = 1;
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_IEEE1394:
|
||||
@@ -314,6 +356,7 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
|
||||
case NWIPE_DEVICE_ATA:
|
||||
strcpy( next_device->device_type_str, " ATA" );
|
||||
check_HPA = 1;
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_NVME:
|
||||
@@ -326,7 +369,20 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
|
||||
case NWIPE_DEVICE_SAS:
|
||||
strcpy( next_device->device_type_str, " SAS" );
|
||||
check_HPA = 1;
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_MMC:
|
||||
strcpy( next_device->device_type_str, " MMC" );
|
||||
break;
|
||||
}
|
||||
if( next_device->device_is_ssd )
|
||||
{
|
||||
strcpy( next_device->device_type_str + 4, "-SSD" );
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( next_device->device_type_str + 4, " " );
|
||||
}
|
||||
|
||||
if( strlen( (const char*) next_device->device_serial_no ) )
|
||||
@@ -359,6 +415,23 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
next_device->device_size_text,
|
||||
next_device->device_serial_no );
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"%s, sector(logical)/block(physical) sizes %i/%i",
|
||||
next_device->device_name,
|
||||
dev->sector_size,
|
||||
dev->phys_sector_size );
|
||||
|
||||
/******************************
|
||||
* Check for hidden sector_size
|
||||
*/
|
||||
if( check_HPA == 1 )
|
||||
{
|
||||
hpa_dco_status( next_device );
|
||||
}
|
||||
|
||||
/* print an empty line to separate the drives in the log */
|
||||
nwipe_log( NWIPE_LOG_INFO, " " );
|
||||
|
||||
( *c )[dcount] = next_device;
|
||||
return 1;
|
||||
}
|
||||
@@ -416,10 +489,10 @@ char* trim( char* str )
|
||||
return str;
|
||||
}
|
||||
|
||||
int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, char* serialnumber )
|
||||
int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, int* is_ssd, char* serialnumber )
|
||||
{
|
||||
/* The caller provides a string that contains the device, i.e. /dev/sdc, also a pointer
|
||||
* to a integer (bus type) and thirdly a 21 byte
|
||||
* to an integer (bus type), another pointer to an integer (is_ssd), and finally a 21 byte
|
||||
* character string which this function populates with the serial number (20 characters + null terminator).
|
||||
*
|
||||
* The function populates the bus integer and serial number strings for the given device.
|
||||
@@ -581,6 +654,13 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
{
|
||||
*bus = NWIPE_DEVICE_VIRT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "/mmcblk" ) != 0 )
|
||||
{
|
||||
*bus = NWIPE_DEVICE_MMC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -662,7 +742,7 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
{
|
||||
/* Convert the label, i.e everything before the ':' to lower case, it's required to
|
||||
* convert to lower case as smartctl seems to use inconsistent case when labeling
|
||||
* for serial number, i.e mostly it produces labels "Serial Number:" but occasionaly
|
||||
* for serial number, i.e mostly it produces labels "Serial Number:" but occasionally
|
||||
* it produces a label "Serial number:" */
|
||||
|
||||
idx = 0;
|
||||
@@ -671,7 +751,7 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
/* If upper case alpha character, change to lower case */
|
||||
if( result[idx] >= 'A' && result[idx] <= 'Z' )
|
||||
{
|
||||
result[idx] += 32;
|
||||
result[idx] = tolower( result[idx] );
|
||||
}
|
||||
|
||||
idx++;
|
||||
@@ -718,7 +798,7 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
}
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_DEBUG, "smartctl: %s", result );
|
||||
nwipe_log( NWIPE_LOG_INFO, "smartctl: %s", result );
|
||||
}
|
||||
|
||||
if( strstr( result, "serial number:" ) != 0 )
|
||||
@@ -726,7 +806,8 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
/* strip any leading or trailing spaces and left justify, +15 is the length of "Serial Number:" */
|
||||
trim( &result[15] );
|
||||
|
||||
strncpy( serialnumber, &result[15], 20 );
|
||||
strncpy( serialnumber, &result[15], NWIPE_SERIALNUMBER_LENGTH );
|
||||
serialnumber[NWIPE_SERIALNUMBER_LENGTH] = 0;
|
||||
}
|
||||
|
||||
if( *bus == 0 )
|
||||
@@ -735,6 +816,10 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
{
|
||||
/* strip any leading or trailing spaces and left justify, +4 is the length of "bus type:" */
|
||||
trim( &result[19] );
|
||||
for( idx = 19; result[idx]; idx++ )
|
||||
{
|
||||
result[idx] = tolower( result[idx] );
|
||||
}
|
||||
|
||||
if( strncmp( &result[19], "sas", 3 ) == 0 )
|
||||
{
|
||||
@@ -747,6 +832,10 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
|
||||
/* strip any leading or trailing spaces and left justify, +4 is the length of "bus type:" */
|
||||
trim( &result[16] );
|
||||
for( idx = 16; result[idx]; idx++ )
|
||||
{
|
||||
result[idx] = tolower( result[idx] );
|
||||
}
|
||||
|
||||
if( strncmp( &result[16], "sata", 4 ) == 0 )
|
||||
{
|
||||
@@ -754,6 +843,20 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
}
|
||||
}
|
||||
}
|
||||
if( strstr( result, "rotation rate:" ) != 0 )
|
||||
{
|
||||
/* strip any leading or trailing spaces and left justify, +15 is the length of "Rotation Rate:" */
|
||||
trim( &result[15] );
|
||||
for( idx = 15; result[idx]; idx++ )
|
||||
{
|
||||
result[idx] = tolower( result[idx] );
|
||||
}
|
||||
|
||||
if( strncmp( &result[15], "solid state device", 19 ) == 0 )
|
||||
{
|
||||
*is_ssd = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* close */
|
||||
@@ -780,9 +883,9 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
|
||||
if( exit_status == 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "%s USB bridge, no pass-through support", device );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Smartctl is unable to provide smart data for %s", device );
|
||||
|
||||
if( *bus == NWIPE_DEVICE_USB )
|
||||
if( *bus == NWIPE_DEVICE_USB || *bus == NWIPE_DEVICE_MMC )
|
||||
{
|
||||
strcpy( serialnumber, "(S/N: unknown)" );
|
||||
set_return_value = 5;
|
||||
@@ -795,21 +898,6 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
|
||||
return set_return_value;
|
||||
}
|
||||
|
||||
void strip_CR_LF( char* str )
|
||||
{
|
||||
/* In the specified string, replace any CR or LF with a space */
|
||||
int idx = 0;
|
||||
int len = strlen( str );
|
||||
while( idx < len )
|
||||
{
|
||||
if( str[idx] == 0x0A || str[idx] == 0x0D )
|
||||
{
|
||||
str[idx] = ' ';
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void remove_ATA_prefix( char* str )
|
||||
{
|
||||
/* Remove "ATA" prefix if present in the model no. string, left justifing string */
|
||||
|
||||
14
src/device.h
14
src/device.h
@@ -27,8 +27,20 @@
|
||||
|
||||
void nwipe_device_identify( nwipe_context_t* c ); // Get hardware information about the device.
|
||||
int nwipe_device_scan( nwipe_context_t*** c ); // Find devices that we can wipe.
|
||||
|
||||
/**
|
||||
* Gets information about devices
|
||||
*
|
||||
* @parameter device_names A reference to a null array pointer.
|
||||
* @parameter devnamelist An array of string pointers to the device names
|
||||
* @parameter ndevnames Number of elements in devnamelist
|
||||
* @modifies device_names Populates device_names with an array of nwipe_contect_t
|
||||
* @returns The number of strings in the device_names array.
|
||||
*
|
||||
*/
|
||||
int nwipe_device_get( nwipe_context_t*** c, char** devnamelist, int ndevnames ); // Get info about devices to wipe.
|
||||
int nwipe_get_device_bus_type_and_serialno( char*, nwipe_device_t*, char* );
|
||||
|
||||
int nwipe_get_device_bus_type_and_serialno( char*, nwipe_device_t*, int*, char* );
|
||||
void strip_CR_LF( char* );
|
||||
void determine_disk_capacity_nomenclature( u64, char* );
|
||||
void remove_ATA_prefix( char* );
|
||||
|
||||
BIN
src/embedded_images/nwipe_exclamation.jpg
Normal file
BIN
src/embedded_images/nwipe_exclamation.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
4
src/embedded_images/nwipe_exclamation.jpg.c
Normal file
4
src/embedded_images/nwipe_exclamation.jpg.c
Normal file
File diff suppressed because one or more lines are too long
16
src/embedded_images/nwipe_exclamation.jpg.h
Normal file
16
src/embedded_images/nwipe_exclamation.jpg.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Autogenerated by hxtools bin2c */
|
||||
#ifndef NWIPE_EXCLAMATION_JPG_H
|
||||
#define NWIPE_EXCLAMATION_JPG_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const unsigned char bin2c_nwipe_exclamation_jpg[63304];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* NWIPE_EXCLAMATION_JPG_H */
|
||||
BIN
src/embedded_images/nwipe_exclamation.xcf
Normal file
BIN
src/embedded_images/nwipe_exclamation.xcf
Normal file
Binary file not shown.
4
src/embedded_images/redcross.c
Normal file
4
src/embedded_images/redcross.c
Normal file
File diff suppressed because one or more lines are too long
16
src/embedded_images/redcross.h
Normal file
16
src/embedded_images/redcross.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Autogenerated by hxtools bin2c */
|
||||
#ifndef REDCROSS_H
|
||||
#define REDCROSS_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const unsigned char bin2c_redcross_jpg[60331];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* REDCROSS_H */
|
||||
BIN
src/embedded_images/redcross.jpg
Normal file
BIN
src/embedded_images/redcross.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
BIN
src/embedded_images/redcross.xcf
Normal file
BIN
src/embedded_images/redcross.xcf
Normal file
Binary file not shown.
BIN
src/embedded_images/shred_db.jpg
Normal file
BIN
src/embedded_images/shred_db.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
4
src/embedded_images/shred_db.jpg.c
Normal file
4
src/embedded_images/shred_db.jpg.c
Normal file
File diff suppressed because one or more lines are too long
16
src/embedded_images/shred_db.jpg.h
Normal file
16
src/embedded_images/shred_db.jpg.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Autogenerated by hxtools bin2c */
|
||||
#ifndef SHRED_DB_JPG_H
|
||||
#define SHRED_DB_JPG_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const unsigned char bin2c_shred_db_jpg[27063];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SHRED_DB_JPG_H */
|
||||
BIN
src/embedded_images/tick_erased.jpg
Normal file
BIN
src/embedded_images/tick_erased.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
4
src/embedded_images/tick_erased.jpg.c
Normal file
4
src/embedded_images/tick_erased.jpg.c
Normal file
File diff suppressed because one or more lines are too long
16
src/embedded_images/tick_erased.jpg.h
Normal file
16
src/embedded_images/tick_erased.jpg.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Autogenerated by hxtools bin2c */
|
||||
#ifndef TICK_ERASED_JPG_H
|
||||
#define TICK_ERASED_JPG_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const unsigned char bin2c_te_jpg[54896];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* TICK_ERASED_JPG_H */
|
||||
BIN
src/embedded_images/tick_erased.xcf
Normal file
BIN
src/embedded_images/tick_erased.xcf
Normal file
Binary file not shown.
85
src/gui.h
85
src/gui.h
@@ -33,6 +33,18 @@ void nwipe_gui_create_stats_window( void ); // Create the stats window
|
||||
void nwipe_gui_create_all_windows_on_terminal_resize(
|
||||
int force_creation,
|
||||
const char* footer_text ); // If terminal is resized recreate all windows
|
||||
|
||||
/**
|
||||
* The primary user interface. Allows the user to
|
||||
* change options and specify the devices to be wiped.
|
||||
*
|
||||
* @parameter count The number of contexts in the array.
|
||||
* @parameter c An array of device contexts.
|
||||
*
|
||||
* @modifies c[].select Sets the select flag according to user input.
|
||||
* @modifies options Sets program options according to to user input.
|
||||
*
|
||||
*/
|
||||
void nwipe_gui_select( int count, nwipe_context_t** c ); // Select devices to wipe.
|
||||
void* nwipe_gui_status( void* ptr ); // Update operation progress.
|
||||
void nwipe_gui_method( void ); // Change the method option.
|
||||
@@ -41,8 +53,69 @@ void nwipe_gui_prng( void ); // Change the prng option.
|
||||
void nwipe_gui_rounds( void ); // Change the rounds option.
|
||||
void nwipe_gui_verify( void ); // Change the verify option.
|
||||
void nwipe_gui_noblank( void ); // Change the noblank option.
|
||||
void nwipe_gui_config( void ); // Change the nwipe settings
|
||||
void nwipe_gui_edit_organisation( void ); // Edit organisation performing the erasure
|
||||
void nwipe_gui_organisation_business_name( const char* ); // Edit business name performing erase
|
||||
void nwipe_gui_organisation_business_address( const char* ); // Edit business address performing erase
|
||||
void nwipe_gui_organisation_contact_name( const char* ); // Edit business contact name
|
||||
void nwipe_gui_organisation_contact_phone( const char* ); // Edit business contact phone
|
||||
void nwipe_gui_organisation_op_tech_name( const char* ); // Edit the name of the operator/technician
|
||||
void nwipe_gui_list( int, char* window_title, char**, int* );
|
||||
void nwipe_gui_add_customer( void ); // Add new customer
|
||||
void nwipe_gui_add_customer_name( char* ); // Add new customer name
|
||||
void nwipe_gui_add_customer_address( char* ); // Add new customer address
|
||||
void nwipe_gui_add_customer_contact_name( char* ); // Add new customer contact name
|
||||
void nwipe_gui_add_customer_contact_phone( char* ); // Add new customer contact phone
|
||||
int nwipe_gui_yes_no_footer( void ); // Change footer to yes no
|
||||
|
||||
/** nwipe_gui_preview_org_customer( int )
|
||||
* Display a editable preview of organisation, customer and date/time
|
||||
*
|
||||
* @param int mode 0 = use prior to drive selection
|
||||
* 1 = use in config menus
|
||||
* The different modes simply change the text in the footer menu and in the case
|
||||
* of mode 0 enable the A key which means accept & display drive selection.
|
||||
*/
|
||||
void nwipe_gui_preview_org_customer( int ); // Preview window for wipe organisation and customer
|
||||
|
||||
void nwipe_gui_set_system_year( void ); // Set the systems current year
|
||||
void nwipe_gui_set_system_month( void ); // Set the systems month
|
||||
void nwipe_gui_set_system_day( void ); // Set the system day of the month
|
||||
void nwipe_gui_set_system_hour( void ); // Set the system hour
|
||||
void nwipe_gui_set_system_minute( void ); // Set the system minute
|
||||
|
||||
/**
|
||||
* Truncate a string based on start position and terminal width
|
||||
*
|
||||
* @parameter wcols Width of window, obtained from getmaxyx(..)
|
||||
* @parameter start_column Start column where the string starts
|
||||
* @parameter input_string The string to be truncated if necessary
|
||||
* @parameter ouput_string The possibly truncated string
|
||||
* @parameter ouput_string_length Max length of output string
|
||||
* @Return returns a pointer to the output string
|
||||
*/
|
||||
char* str_truncate( int, int, const char*, char*, int ); // Truncate string based on start column and terminal width
|
||||
|
||||
/**
|
||||
* Set system date and time
|
||||
*
|
||||
* @parameter void
|
||||
* @Return void
|
||||
*/
|
||||
void nwipe_gui_set_date_time( void );
|
||||
|
||||
int spinner( nwipe_context_t** ptr, int ); // Return the next spinner character
|
||||
void temp1_flash( nwipe_context_t* ); // toggles term1_flash_status, which flashes the temperature
|
||||
|
||||
/**
|
||||
* If the current drive temperature is available, print it to the GUI.
|
||||
* This function determines if the drive temperature limits are specified &
|
||||
* if so, whether the temperature should be printed as white text on blue if the
|
||||
* drive is operating within it's temperature specification or red text on
|
||||
* blue if the drive has exceeded the critical high temperature or black on
|
||||
* blue if the drive has dropped below the drives minimum temperature specification.
|
||||
* @param pointer to the drive context
|
||||
*/
|
||||
void wprintw_temperature( nwipe_context_t* );
|
||||
|
||||
int compute_stats( void* ptr );
|
||||
@@ -54,9 +127,19 @@ void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_done, t
|
||||
* the drive selection screen is displayed. (prior to wipe starting). */
|
||||
#define GETCH_BLOCK_MS 250 /* millisecond block time for getch() */
|
||||
|
||||
/* Note The value of 1 (100ms) is the ideal speed for screen refresh during a wipe, a value of 2 is noticably slower,
|
||||
/* Note The value of 1 (100ms) is the ideal speed for screen refresh during a wipe, a value of 2 is noticeably slower,
|
||||
* don't change unless you understand how this value affects keyboard responsiveness and speed of screen stats/spinner
|
||||
* updating */
|
||||
#define GETCH_GUI_STATS_UPDATE_MS 1 /* 1 * 100 = 1/10/sec = millisecond block time for gui stats screen updates */
|
||||
|
||||
#define FIELD_LENGTH 256
|
||||
|
||||
#define MAX_TITLE_LENGTH 76
|
||||
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
#define SHOWING_PRIOR_TO_DRIVE_SELECTION 0
|
||||
#define SHOWING_IN_CONFIG_MENUS 1
|
||||
|
||||
#endif /* GUI_H_ */
|
||||
|
||||
159
src/hddtemp_scsi/get_scsi_temp.c
Normal file
159
src/hddtemp_scsi/get_scsi_temp.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* get_scsi_temp.c: functions that populate the drive temperature variables
|
||||
* in SCSI/SAS drives context structure.
|
||||
* Routines from hddtemp are used here.
|
||||
*
|
||||
* Author: Gerold Gruber <Gerold.Gruber@edv2g.de>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
//#define _LARGEFILE64_SOURCE
|
||||
//#define _FILE_OFFSET_BITS 64
|
||||
#define _BSD_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
#include "method.h"
|
||||
#include "device.h"
|
||||
#include "prng.h"
|
||||
#include "options.h"
|
||||
#include "device.h"
|
||||
#include "logging.h"
|
||||
#include "temperature.h"
|
||||
#include "miscellaneous.h"
|
||||
#include "hddtemp.h"
|
||||
#include "scsi.h"
|
||||
|
||||
int scsi_get_temperature( struct disk * );
|
||||
|
||||
int nwipe_init_scsi_temperature( nwipe_context_t* c )
|
||||
{
|
||||
|
||||
/* dsk anlegen, malloc */
|
||||
struct disk *dsk = (struct disk *) malloc(sizeof(struct disk));
|
||||
|
||||
/* Check the allocation. */
|
||||
if( !dsk )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "malloc" );
|
||||
nwipe_log( NWIPE_LOG_FATAL, "Unable to get memory for disk struct for %s",
|
||||
c->device_name );
|
||||
exit( 1 ) ;
|
||||
}
|
||||
|
||||
assert(dsk);
|
||||
|
||||
memset(dsk, 0, sizeof(*dsk));
|
||||
|
||||
/* save the dsk pointer for later use */
|
||||
c->templ_disk = dsk;
|
||||
|
||||
/* initialize */
|
||||
dsk->drive = c->device_name;
|
||||
dsk->type = BUS_SCSI; /* we know this as we are only called in this case */
|
||||
|
||||
errno = 0;
|
||||
dsk->errormsg[0] = '\0';
|
||||
if( (dsk->fd = open(dsk->drive, O_RDONLY | O_NONBLOCK)) < 0) {
|
||||
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, "open: %s\n", strerror(errno));
|
||||
dsk->type = ERROR;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// sg_logs -t <device>
|
||||
if( scsi_get_temperature( dsk ) == GETTEMP_SUCCESS )
|
||||
{
|
||||
c->temp1_input = dsk->value;
|
||||
c->temp1_crit = dsk->refvalue;
|
||||
c->temp1_lcrit = -40; /* just to give it a value with some kind of sense */
|
||||
c->temp1_highest = dsk->value;
|
||||
c->temp1_lowest = dsk->value;
|
||||
c->temp1_max = dsk->refvalue - 5; /* seems to be kind of useful */
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Can not read SCSI temperature for %s, %s",
|
||||
dsk->drive, dsk->errormsg );
|
||||
close( dsk->fd );
|
||||
free( dsk );
|
||||
c->templ_disk = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int nwipe_get_scsi_temperature( nwipe_context_t* c )
|
||||
{
|
||||
struct disk *dsk;
|
||||
|
||||
dsk = c->templ_disk;
|
||||
|
||||
if( c->templ_disk != NULL && c->templ_disk->fd != -1 )
|
||||
{
|
||||
if( scsi_get_temperature( dsk ) == GETTEMP_SUCCESS )
|
||||
{
|
||||
c->temp1_input = dsk->value;
|
||||
|
||||
/* not at all of interest */
|
||||
if( c->temp1_input > c->temp1_highest )
|
||||
{
|
||||
c->temp1_highest = c->temp1_input;
|
||||
}
|
||||
if( c->temp1_input < c->temp1_lowest )
|
||||
{
|
||||
c->temp1_lowest = c->temp1_input;
|
||||
}
|
||||
|
||||
/* end not at all of interest ;-) */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Could not read SCSI temperature for %s, %s",
|
||||
dsk->drive, dsk->errormsg );
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "no SCSI temperature reading for %s", dsk->drive );
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nwipe_shut_scsi_temperature( nwipe_context_t* c )
|
||||
{
|
||||
if( c->templ_disk->fd != -1 )
|
||||
{
|
||||
close( c->templ_disk->fd );
|
||||
}
|
||||
if( c->templ_disk != NULL )
|
||||
{
|
||||
free( c->templ_disk );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
91
src/hddtemp_scsi/hddtemp.h
Normal file
91
src/hddtemp_scsi/hddtemp.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __HDDTEMP_H__
|
||||
#define __HDDTEMP_H__
|
||||
|
||||
#include <time.h>
|
||||
// #include "db.h"
|
||||
|
||||
//#ifdef ARCH_I386
|
||||
//typedef unsigned short u16;
|
||||
//#endif
|
||||
#include <linux/types.h>
|
||||
typedef __u16 u16;
|
||||
|
||||
#define MAX_ERRORMSG_SIZE 128
|
||||
#define DEFAULT_ATTRIBUTE_ID 194
|
||||
|
||||
#define F_to_C(val) (int)(((double)(val)-32.0)/1.8)
|
||||
#define C_to_F(val) (int)(((double)(val)*(double)1.8) + (double)32.0)
|
||||
|
||||
enum e_bustype { ERROR = 0, BUS_UNKNOWN, BUS_SATA, BUS_ATA, BUS_SCSI, BUS_TYPE_MAX };
|
||||
|
||||
#define GETTEMP_SUCCESS 0
|
||||
#define GETTEMP_ERROR 1
|
||||
#define GETTEMP_NOT_APPLICABLE 2
|
||||
#define GETTEMP_UNKNOWN 3
|
||||
#define GETTEMP_GUESS 4
|
||||
#define GETTEMP_KNOWN 5
|
||||
#define GETTEMP_NOSENSOR 6
|
||||
#define GETTEMP_DRIVE_SLEEP 7
|
||||
|
||||
enum e_powermode {
|
||||
PWM_UNKNOWN,
|
||||
PWM_ACTIVE,
|
||||
PWM_SLEEPING,
|
||||
PWM_STANDBY
|
||||
};
|
||||
|
||||
|
||||
struct disk {
|
||||
struct disk * next;
|
||||
|
||||
int fd;
|
||||
const char * drive;
|
||||
const char * model;
|
||||
enum e_bustype type;
|
||||
int value; /* the drive's temperature */
|
||||
int refvalue; /* aka trip temperature */
|
||||
struct harddrive_entry * db_entry;
|
||||
|
||||
char errormsg[MAX_ERRORMSG_SIZE];
|
||||
// enum e_gettemp ret;
|
||||
int ret;
|
||||
time_t last_time;
|
||||
};
|
||||
|
||||
struct bustype {
|
||||
char *name;
|
||||
int (*probe)(int);
|
||||
const char *(*model)(int);
|
||||
enum e_gettemp (*get_temperature)(struct disk *);
|
||||
};
|
||||
|
||||
|
||||
extern struct bustype * bus[BUS_TYPE_MAX];
|
||||
extern char errormsg[MAX_ERRORMSG_SIZE];
|
||||
extern int tcp_daemon, debug, quiet, wakeup, af_hint;
|
||||
extern char separator;
|
||||
extern long portnum, syslog_interval;
|
||||
extern char * listen_addr;
|
||||
|
||||
int value_to_unit(struct disk *dsk);
|
||||
char get_unit(struct disk *dsk);
|
||||
|
||||
#endif
|
||||
125
src/hddtemp_scsi/scsi.c
Normal file
125
src/hddtemp_scsi/scsi.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Adapted from a patch sended by : Frederic LOCHON <lochon@roulaise.net>
|
||||
*/
|
||||
/*
|
||||
* Adapted for use with nwipe by : Gerold Gruber <Gerold.Gruber@edv2g.de>
|
||||
*/
|
||||
|
||||
// Include file generated by ./configure
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
// Gettext includes
|
||||
#if ENABLE_NLS
|
||||
#include <libintl.h>
|
||||
#define _(String) gettext (String)
|
||||
#else
|
||||
#define _(String) (String)
|
||||
#endif
|
||||
|
||||
// Standard includes
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
// Application specific includes
|
||||
#include "scsicmds.h"
|
||||
#include "hddtemp.h"
|
||||
|
||||
int scsi_get_temperature(struct disk *dsk) {
|
||||
int i;
|
||||
int tempPage = 0;
|
||||
unsigned char buffer[1024];
|
||||
|
||||
/*
|
||||
on triche un peu
|
||||
we cheat a little and do not really read form drivedb as SCSI disks are not included there
|
||||
original code omitted as there is no need for it in the context of nwipe
|
||||
*/
|
||||
|
||||
/*
|
||||
Enable SMART
|
||||
*/
|
||||
if (scsi_smartDEXCPTdisable(dsk->fd) != 0) {
|
||||
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, "%s", strerror(errno));
|
||||
close(dsk->fd);
|
||||
dsk->fd = -1;
|
||||
return GETTEMP_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
Temp. capable
|
||||
*/
|
||||
if (scsi_logsense(dsk->fd , SUPPORT_LOG_PAGES, buffer, sizeof(buffer)) != 0) {
|
||||
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("log sense failed : %s"), strerror(errno));
|
||||
close(dsk->fd);
|
||||
dsk->fd = -1;
|
||||
return GETTEMP_ERROR;
|
||||
}
|
||||
|
||||
for ( i = 4; i < buffer[3] + LOGPAGEHDRSIZE ; i++) {
|
||||
if (buffer[i] == TEMPERATURE_PAGE) {
|
||||
tempPage = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(tempPage) {
|
||||
/*
|
||||
get temperature (from scsiGetTemp (scsicmd.c))
|
||||
*/
|
||||
if (scsi_logsense(dsk->fd , TEMPERATURE_PAGE, buffer, sizeof(buffer)) != 0) {
|
||||
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("log sense failed : %s"), strerror(errno));
|
||||
close(dsk->fd);
|
||||
dsk->fd = -1;
|
||||
return GETTEMP_ERROR;
|
||||
}
|
||||
|
||||
if( (int)buffer[7] == 2 ) /* PARAMETER LENGTH */
|
||||
{
|
||||
dsk->value = buffer[9];
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("parameter length unexpected: %d"), (int)buffer[7] );
|
||||
return GETTEMP_UNKNOWN;
|
||||
}
|
||||
dsk->refvalue = buffer[15];
|
||||
if( (int)buffer[13] == 2 ) /* PARAMETER LENGTH */
|
||||
{
|
||||
dsk->refvalue = buffer[15];
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("parameter ref length unexpected: %d"), (int)buffer[13] );
|
||||
return GETTEMP_UNKNOWN;
|
||||
}
|
||||
return GETTEMP_SUCCESS;
|
||||
} else {
|
||||
return GETTEMP_NOSENSOR;
|
||||
}
|
||||
}
|
||||
24
src/hddtemp_scsi/scsi.h
Normal file
24
src/hddtemp_scsi/scsi.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SCSIC_H_
|
||||
#define SCSIC_H_
|
||||
|
||||
extern struct bustype scsi_bus;
|
||||
|
||||
#endif
|
||||
221
src/hddtemp_scsi/scsicmds.c
Normal file
221
src/hddtemp_scsi/scsicmds.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// Include file generated by ./configure
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
// Gettext includes
|
||||
#if ENABLE_NLS
|
||||
#include <libintl.h>
|
||||
#define _(String) gettext (String)
|
||||
#else
|
||||
#define _(String) (String)
|
||||
#endif
|
||||
|
||||
// Standard includes
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/sg.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
|
||||
// Application specific includes
|
||||
#include "scsicmds.h"
|
||||
|
||||
static void scsi_fixstring(unsigned char *s, int bytecount)
|
||||
{
|
||||
unsigned char *p;
|
||||
unsigned char *end;
|
||||
|
||||
p = s;
|
||||
end = s + bytecount;
|
||||
|
||||
/* strip leading blanks */
|
||||
while (s != end && *s == ' ')
|
||||
++s;
|
||||
/* compress internal blanks and strip trailing blanks */
|
||||
while (s != end && *s) {
|
||||
if (*s++ != ' ' || (s != end && *s && *s != ' '))
|
||||
*p++ = *(s-1);
|
||||
}
|
||||
/* wipe out trailing garbage */
|
||||
while (p != end)
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
int scsi_SG_IO(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, unsigned char *sense, unsigned char sense_len, int dxfer_direction) {
|
||||
struct sg_io_hdr io_hdr;
|
||||
|
||||
memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.cmdp = cdb;
|
||||
io_hdr.cmd_len = cdb_len;
|
||||
io_hdr.dxfer_len = buffer_len;
|
||||
io_hdr.dxferp = buffer;
|
||||
io_hdr.mx_sb_len = sense_len;
|
||||
io_hdr.sbp = sense;
|
||||
io_hdr.dxfer_direction = dxfer_direction;
|
||||
io_hdr.timeout = 3000; /* 3 seconds should be ample */
|
||||
|
||||
return ioctl(device, SG_IO, &io_hdr);
|
||||
}
|
||||
|
||||
int scsi_SEND_COMMAND(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, int dxfer_direction)
|
||||
{
|
||||
unsigned char buf[2048];
|
||||
unsigned int inbufsize, outbufsize, ret;
|
||||
|
||||
switch(dxfer_direction) {
|
||||
case SG_DXFER_FROM_DEV:
|
||||
inbufsize = 0;
|
||||
outbufsize = buffer_len;
|
||||
break;
|
||||
case SG_DXFER_TO_DEV:
|
||||
inbufsize = buffer_len;
|
||||
outbufsize = 0;
|
||||
break;
|
||||
default:
|
||||
inbufsize = 0;
|
||||
outbufsize = 0;
|
||||
break;
|
||||
}
|
||||
memcpy(buf, &inbufsize , sizeof(inbufsize));
|
||||
memcpy(buf + sizeof(inbufsize), &outbufsize , sizeof(outbufsize));
|
||||
memcpy(buf + sizeof(inbufsize) + sizeof(outbufsize), cdb, cdb_len);
|
||||
memcpy(buf + sizeof(inbufsize) + sizeof(outbufsize) + cdb_len, buffer, buffer_len);
|
||||
|
||||
ret = ioctl(device, SCSI_IOCTL_SEND_COMMAND, buf);
|
||||
|
||||
memcpy(buffer, buf + sizeof(inbufsize) + sizeof(outbufsize), buffer_len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int scsi_command(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, int dxfer_direction)
|
||||
{
|
||||
static int SG_IO_supported = -1;
|
||||
int ret;
|
||||
|
||||
if (SG_IO_supported == 1)
|
||||
return scsi_SG_IO(device, cdb, cdb_len, buffer, buffer_len, NULL, 0, dxfer_direction);
|
||||
else if (SG_IO_supported == 0)
|
||||
return scsi_SEND_COMMAND(device, cdb, cdb_len, buffer, buffer_len, dxfer_direction);
|
||||
else {
|
||||
ret = scsi_SG_IO(device, cdb, cdb_len, buffer, buffer_len, NULL, 0, dxfer_direction);
|
||||
if (ret == 0) {
|
||||
SG_IO_supported = 1;
|
||||
return ret;
|
||||
} else {
|
||||
SG_IO_supported = 0;
|
||||
return scsi_SEND_COMMAND(device, cdb, cdb_len, buffer, buffer_len, dxfer_direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_inquiry(int device, unsigned char *buffer)
|
||||
{
|
||||
unsigned char cdb[6];
|
||||
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = INQUIRY;
|
||||
cdb[4] = 36; /* should be 36 for unsafe devices (like USB mass storage stuff)
|
||||
* otherwise they can lock up! SPC sections 7.4 and 8.6 */
|
||||
|
||||
if (scsi_command(device, cdb, sizeof(cdb), buffer, cdb[4], SG_DXFER_FROM_DEV) != 0)
|
||||
return 1;
|
||||
else {
|
||||
scsi_fixstring(buffer + 8, 24);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_modesense(int device, unsigned char pagenum, unsigned char *buffer, int buffer_len) {
|
||||
unsigned char cdb[6];
|
||||
int ret;
|
||||
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = MODE_SENSE;
|
||||
cdb[2] = pagenum;
|
||||
cdb[4] = 0xff;
|
||||
|
||||
ret = scsi_command(device, cdb, sizeof(cdb), buffer, buffer_len, SG_DXFER_FROM_DEV);
|
||||
if (ret == 0) {
|
||||
if ((buffer[3] + 5) > buffer[0]) /* response length too short */
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int scsi_modeselect(int device, char *buffer) {
|
||||
unsigned char cdb[6];
|
||||
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = MODE_SELECT;
|
||||
cdb[1] = 0x11;
|
||||
cdb[4] = buffer[0] + 1;
|
||||
|
||||
memset(buffer, 0, 12);
|
||||
buffer[3] = 0x08;
|
||||
buffer[10] = 0x02;
|
||||
buffer[12] &= 0x3f;
|
||||
|
||||
return scsi_command(device, cdb, sizeof(cdb), buffer, cdb[4], SG_DXFER_TO_DEV);
|
||||
}
|
||||
|
||||
int scsi_logsense(int device, int pagenum, unsigned char *buffer, int buffer_len) {
|
||||
unsigned char cdb[10];
|
||||
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = LOG_SENSE;
|
||||
cdb[2] = 0x40 | pagenum;
|
||||
cdb[7] = 0x04;
|
||||
|
||||
return scsi_command(device, cdb, sizeof(cdb), buffer, buffer_len, SG_DXFER_FROM_DEV);
|
||||
}
|
||||
|
||||
int scsi_smartsupport(int device) {
|
||||
unsigned char buf[255];
|
||||
|
||||
if (scsi_modesense (device, EXCEPTIONS_CONTROL_PAGE, buf, sizeof(buf)) != 0)
|
||||
return 0;
|
||||
else
|
||||
return (buf[14] & 0x08) == 0;
|
||||
}
|
||||
|
||||
int scsi_smartDEXCPTdisable(int device) {
|
||||
unsigned char buf[255];
|
||||
|
||||
if (scsi_modesense (device, EXCEPTIONS_CONTROL_PAGE, buf, sizeof(buf)) != 0)
|
||||
return 1;
|
||||
|
||||
if (buf[14] & 0x08) {
|
||||
buf[14] &= 0xf7;
|
||||
buf[15] = 0x04;
|
||||
return scsi_modeselect (device, buf);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
36
src/hddtemp_scsi/scsicmds.h
Normal file
36
src/hddtemp_scsi/scsicmds.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SCSICMDS_H_
|
||||
#define SCSICMDS_H_
|
||||
|
||||
#define SUPPORT_LOG_PAGES 0x00
|
||||
#define TEMPERATURE_PAGE 0x0d
|
||||
#define EXCEPTIONS_CONTROL_PAGE 0x1c
|
||||
#define LOGPAGEHDRSIZE 4
|
||||
|
||||
int scsi_SG_IO(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, unsigned char *sense, unsigned char sense_len, int dxfer_direction);
|
||||
int scsi_inquiry(int device, unsigned char *buffer);
|
||||
int scsi_modesense(int device, unsigned char pagenum, unsigned char *buffer, int buffer_len);
|
||||
int scsi_modeselect(int device, char *buffer);
|
||||
int scsi_logsense(int device, int pagenum, unsigned char *buffer, int buffer_len);
|
||||
int scsi_smartsupport(int device);
|
||||
int scsi_smartDEXCPTdisable(int device);
|
||||
|
||||
#endif
|
||||
858
src/hpa_dco.c
Normal file
858
src/hpa_dco.c
Normal file
@@ -0,0 +1,858 @@
|
||||
/*
|
||||
* hpa_dco.c: functions that handle the host protected area (HPA) and
|
||||
* device configuration overlay (DCO)
|
||||
*
|
||||
* Copyright PartialVolume <https://github.com/PartialVolume>.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <scsi/sg.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
#include "version.h"
|
||||
#include "method.h"
|
||||
#include "logging.h"
|
||||
#include "options.h"
|
||||
#include "hpa_dco.h"
|
||||
#include "miscellaneous.h"
|
||||
|
||||
/* This function makes use of both the hdparm program to determine HPA/DCO status and we also access
|
||||
* the device configuration overlay identify data structure via the sg driver with ioctl calls.
|
||||
* I would prefer to write these functions without any reliance on hdparm however for the time being
|
||||
* we will utilize both methods. However, I don't like doing it like this as a change in formatted
|
||||
* output of hdparm could potentially break HPA/DCO detection requiring a fix. Time permitting I may
|
||||
* come back to this and fully implement it without any reliance on hdparm.
|
||||
*/
|
||||
|
||||
int hpa_dco_status( nwipe_context_t* ptr )
|
||||
{
|
||||
nwipe_context_t* c;
|
||||
c = ptr;
|
||||
|
||||
int r; // A result buffer.
|
||||
int set_return_value;
|
||||
int exit_status;
|
||||
int hpa_line_found;
|
||||
int dco_line_found;
|
||||
|
||||
FILE* fp;
|
||||
char path_hdparm_cmd1_get_hpa[] = "hdparm --verbose -N";
|
||||
char path_hdparm_cmd2_get_hpa[] = "/sbin/hdparm --verbose -N";
|
||||
char path_hdparm_cmd3_get_hpa[] = "/usr/bin/hdparm --verbose -N";
|
||||
|
||||
char path_hdparm_cmd4_get_dco[] = "hdparm --verbose --dco-identify";
|
||||
char path_hdparm_cmd5_get_dco[] = "/sbin/hdparm --verbose --dco-identify";
|
||||
char path_hdparm_cmd6_get_dco[] = "/usr/bin/hdparm --verbose --dco-identify";
|
||||
|
||||
char pipe_std_err[] = "2>&1";
|
||||
|
||||
char result[512];
|
||||
|
||||
u64 nwipe_dco_real_max_sectors;
|
||||
|
||||
char* p;
|
||||
|
||||
/* Use the longest of the 'path_hdparm_cmd.....' strings above to
|
||||
*determine size in the strings below
|
||||
*/
|
||||
char hdparm_cmd_get_hpa[sizeof( path_hdparm_cmd3_get_hpa ) + sizeof( c->device_name ) + sizeof( pipe_std_err )];
|
||||
char hdparm_cmd_get_dco[sizeof( path_hdparm_cmd6_get_dco ) + sizeof( c->device_name ) + sizeof( pipe_std_err )];
|
||||
|
||||
/* Initialise return value */
|
||||
set_return_value = 0;
|
||||
|
||||
/* Construct the command including path to the binary if required, I do it like this to cope
|
||||
* with distros that don't setup their paths in a standard way or maybe don't even define a
|
||||
* path. By doing this we avoid the 'No such file or directory' message you would otherwise
|
||||
* get on some distros. -> debian SID
|
||||
*/
|
||||
|
||||
if( system( "which hdparm > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /sbin/hdparm > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /usr/bin/hdparm > /dev/null 2>&1" ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hdparm command not found." );
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"Required by nwipe for HPA/DCO detection & correction and ATA secure erase." );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "** Please install hdparm **\n" );
|
||||
cleanup();
|
||||
exit( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( hdparm_cmd_get_hpa,
|
||||
sizeof( hdparm_cmd_get_hpa ),
|
||||
"%s %s %s\n",
|
||||
path_hdparm_cmd3_get_hpa,
|
||||
c->device_name,
|
||||
pipe_std_err );
|
||||
snprintf( hdparm_cmd_get_dco,
|
||||
sizeof( hdparm_cmd_get_dco ),
|
||||
"%s %s %s\n",
|
||||
path_hdparm_cmd6_get_dco,
|
||||
c->device_name,
|
||||
pipe_std_err );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( hdparm_cmd_get_hpa,
|
||||
sizeof( hdparm_cmd_get_hpa ),
|
||||
"%s %s %s\n",
|
||||
path_hdparm_cmd2_get_hpa,
|
||||
c->device_name,
|
||||
pipe_std_err );
|
||||
snprintf( hdparm_cmd_get_dco,
|
||||
sizeof( hdparm_cmd_get_dco ),
|
||||
"%s %s %s\n",
|
||||
path_hdparm_cmd5_get_dco,
|
||||
c->device_name,
|
||||
pipe_std_err );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( hdparm_cmd_get_hpa,
|
||||
sizeof( hdparm_cmd_get_hpa ),
|
||||
"%s %s %s\n",
|
||||
path_hdparm_cmd1_get_hpa,
|
||||
c->device_name,
|
||||
pipe_std_err );
|
||||
snprintf( hdparm_cmd_get_dco,
|
||||
sizeof( hdparm_cmd_get_dco ),
|
||||
"%s %s %s\n",
|
||||
path_hdparm_cmd4_get_dco,
|
||||
c->device_name,
|
||||
pipe_std_err );
|
||||
}
|
||||
|
||||
/* Initialise the results buffer, so we don't some how inadvertently process a past result */
|
||||
memset( result, 0, sizeof( result ) );
|
||||
|
||||
if( hdparm_cmd_get_hpa[0] != 0 )
|
||||
{
|
||||
|
||||
fp = popen( hdparm_cmd_get_hpa, "r" );
|
||||
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hpa_dco_status: Failed to create stream to %s", hdparm_cmd_get_hpa );
|
||||
|
||||
set_return_value = 1;
|
||||
}
|
||||
|
||||
if( fp != NULL )
|
||||
{
|
||||
hpa_line_found = 0; //* init */
|
||||
|
||||
/* Read the output a line at a time - output it. */
|
||||
while( fgets( result, sizeof( result ) - 1, fp ) != NULL )
|
||||
{
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_DEBUG, "%s \n%s", hdparm_cmd_get_hpa, result );
|
||||
}
|
||||
|
||||
/* Change the output of hdparm to lower case and search using lower case strings, to try
|
||||
* to avoid minor changes in case in hdparm's output from breaking HPA/DCO detection
|
||||
*/
|
||||
strlower( result ); // convert the result to lower case
|
||||
|
||||
/* Scan the hdparm results for HPA is disabled
|
||||
*/
|
||||
if( strstr( result, "sg_io: bad/missing sense data" ) != 0 )
|
||||
{
|
||||
c->HPA_status = HPA_UNKNOWN;
|
||||
nwipe_log( NWIPE_LOG_ERROR, "SG_IO bad/missing sense data %s", hdparm_cmd_get_hpa );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "hpa is disabled" ) != 0 )
|
||||
{
|
||||
c->HPA_status = HPA_DISABLED;
|
||||
|
||||
nwipe_log( NWIPE_LOG_DEBUG,
|
||||
"hdparm says the host protected area is disabled on %s but this information may or "
|
||||
"may not be correct, as occurs when you get a SG_IO error and 0/1 sectors and it "
|
||||
"says HPA is enabled. Further checks are conducted below..",
|
||||
c->device_name );
|
||||
hpa_line_found = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "hpa is enabled" ) != 0 )
|
||||
{
|
||||
c->HPA_status = HPA_ENABLED;
|
||||
nwipe_log( NWIPE_LOG_DEBUG,
|
||||
"hdparm says the host protected area is enabled on %s but this information may "
|
||||
"or may not be correct, as occurs when you get a SG_IO error and 0/1 sectors "
|
||||
"and it says HPA is enabled. Further checks are conducted below..",
|
||||
c->device_name );
|
||||
hpa_line_found = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "accessible max address disabled" ) != 0 )
|
||||
{
|
||||
c->HPA_status = HPA_DISABLED;
|
||||
nwipe_log( NWIPE_LOG_DEBUG,
|
||||
"hdparm says the accessible max address disabled on %s"
|
||||
"this means that there are no hidden sectors, "
|
||||
"",
|
||||
c->device_name );
|
||||
hpa_line_found = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "accessible max address enabled" ) != 0 )
|
||||
{
|
||||
c->HPA_status = HPA_ENABLED;
|
||||
nwipe_log( NWIPE_LOG_DEBUG,
|
||||
"hdparm says the accessible max address enabled on %s"
|
||||
"this means that there are hidden sectors",
|
||||
c->device_name );
|
||||
hpa_line_found = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "invalid" ) != 0 )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_WARNING,
|
||||
"hdparm reports invalid output, sector information may be invalid, buggy "
|
||||
"drive firmware on %s?",
|
||||
c->device_name );
|
||||
// We'll assume the HPA values are in the string as we may be able to extract
|
||||
// something meaningful
|
||||
hpa_line_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if the HPA line was found then process the line,
|
||||
* extracting the 'hpa set' and 'hpa real' values.
|
||||
*/
|
||||
if( hpa_line_found == 1 )
|
||||
{
|
||||
/* Extract the 'HPA set' value, the first value in the line and convert
|
||||
* to binary and save in context */
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO, "HPA: %s on %s", result, c->device_name );
|
||||
|
||||
c->HPA_reported_set = str_ascii_number_to_ll( result );
|
||||
|
||||
/* Check whether the number was too large or no number found & log */
|
||||
if( c->HPA_reported_set == -1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "HPA_set_value: HPA set value too large on %s", c->device_name );
|
||||
c->HPA_reported_set = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_reported_set == -2 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "HPA_set_value: No HPA set value found %s", c->device_name );
|
||||
c->HPA_reported_set = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract the 'HPA real' value, the second value in the line and convert
|
||||
* to binary and save in context, this is a little more difficult as sometimes
|
||||
* a odd value is returned so instead of nnnnn/nnnnn you get nnnnnn/1(nnnnnn).
|
||||
* So first we scan for a open bracket '(' then if there is no '(' we then start the
|
||||
* search immediately after the '/'.
|
||||
*/
|
||||
if( ( p = strstr( result, "(" ) ) )
|
||||
{
|
||||
c->HPA_reported_real = str_ascii_number_to_ll( p + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( p = strstr( result, "/" ) ) )
|
||||
{
|
||||
c->HPA_reported_real = str_ascii_number_to_ll( p + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether the number was too large or no number found & log */
|
||||
if( c->HPA_reported_real == -1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "HPA_set_value: HPA real value too large on %s", c->device_name );
|
||||
c->HPA_reported_real = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_reported_real == -2 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "HPA_set_value: No HPA real value found %s", c->device_name );
|
||||
c->HPA_reported_real = 0;
|
||||
}
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"HPA values %lli / %lli on %s",
|
||||
c->HPA_reported_set,
|
||||
c->HPA_reported_real,
|
||||
c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
c->HPA_status = HPA_UNKNOWN;
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"[UNKNOWN] We can't find the HPA line, has hdparm ouput unknown/changed? %s",
|
||||
c->device_name );
|
||||
}
|
||||
|
||||
/* close */
|
||||
r = pclose( fp );
|
||||
if( r > 0 )
|
||||
{
|
||||
exit_status = WEXITSTATUS( r );
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"hpa_dco_status(): hdparm failed, \"%s\" exit status = %u",
|
||||
hdparm_cmd_get_hpa,
|
||||
exit_status );
|
||||
}
|
||||
|
||||
if( exit_status == 127 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Command not found. Installing hdparm is mandatory !" );
|
||||
set_return_value = 2;
|
||||
if( nwipe_options.nousb )
|
||||
{
|
||||
return set_return_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise the results buffer again, so we don't
|
||||
* some how inadvertently process a past result */
|
||||
memset( result, 0, sizeof( result ) );
|
||||
|
||||
/* -----------------------------------------------
|
||||
* Run the dco identify command and determine the
|
||||
* real max sectors, store it in the drive context
|
||||
* for comparison against the hpa reported drive
|
||||
* size values.
|
||||
*/
|
||||
|
||||
dco_line_found = 0;
|
||||
|
||||
if( hdparm_cmd_get_dco[0] != 0 )
|
||||
{
|
||||
|
||||
fp = popen( hdparm_cmd_get_dco, "r" );
|
||||
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hpa_dco_status: Failed to create stream to %s", hdparm_cmd_get_dco );
|
||||
|
||||
set_return_value = 1;
|
||||
}
|
||||
|
||||
if( fp != NULL )
|
||||
{
|
||||
/* Read the output a line at a time - output it. */
|
||||
while( fgets( result, sizeof( result ) - 1, fp ) != NULL )
|
||||
{
|
||||
/* Change the output of hdparm to lower case and search using lower case strings, to try
|
||||
* to avoid minor changes in case in hdparm's output from breaking HPA/DCO detection */
|
||||
strlower( result );
|
||||
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_DEBUG, "%s \n%s", hdparm_cmd_get_dco, result );
|
||||
}
|
||||
|
||||
if( strstr( result, "real max sectors" ) != 0 )
|
||||
{
|
||||
/* extract the real max sectors, convert to binary and store in drive context */
|
||||
dco_line_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* DCO line found, now process it */
|
||||
if( dco_line_found == 1 )
|
||||
{
|
||||
c->DCO_reported_real_max_sectors = str_ascii_number_to_ll( result );
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"hdparm:DCO Real max sectors reported as %lli on %s",
|
||||
c->DCO_reported_real_max_sectors,
|
||||
c->device_name );
|
||||
|
||||
/* Validate the real max sectors to detect extreme or impossible
|
||||
* values, so the size must be greater than zero but less than
|
||||
* 200TB (429496729600 sectors). As its 2023 and the largest drive
|
||||
* available is 20TB I wonder if somebody in the future will be looking
|
||||
* at this and thinking, yep we need to increase that value... and I'm
|
||||
* wondering what year that will be. This validation is necessary all
|
||||
* because of a bug in hdparm v9.60 (and maybe other versions) which
|
||||
* produced wildly inaccurate values, often negative.
|
||||
*/
|
||||
if( c->DCO_reported_real_max_sectors > 0 && c->DCO_reported_real_max_sectors < 429496729600 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"NWipe: DCO Real max sectors reported as %lli on %s",
|
||||
c->DCO_reported_real_max_sectors,
|
||||
c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call nwipe's own low level function to retrieve the drive configuration
|
||||
* overlay and retrieve the real max sectors. We may remove reliance on hdparm
|
||||
* if nwipes own low level drive access code works well.
|
||||
*/
|
||||
c->DCO_reported_real_max_sectors = nwipe_read_dco_real_max_sectors( c->device_name );
|
||||
|
||||
/* Check our real max sectors function is returning sensible data too */
|
||||
if( c->DCO_reported_real_max_sectors > 0 && c->DCO_reported_real_max_sectors < 429496729600 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"NWipe: DCO Real max sectors reported as %lli on %s",
|
||||
c->DCO_reported_real_max_sectors,
|
||||
c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
c->DCO_reported_real_max_sectors = 0;
|
||||
nwipe_log( NWIPE_LOG_INFO, "DCO Real max sectors not found" );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c->DCO_reported_real_max_sectors = 0;
|
||||
nwipe_log( NWIPE_LOG_INFO, "DCO Real max sectors not found" );
|
||||
}
|
||||
|
||||
nwipe_log(
|
||||
NWIPE_LOG_INFO,
|
||||
"libata: apparent max sectors reported as %lli with sector size as %i/%i (logical/physical) on %s",
|
||||
c->device_size_in_sectors,
|
||||
c->device_sector_size, // logical
|
||||
c->device_phys_sector_size, // physical
|
||||
c->device_name );
|
||||
|
||||
/* close */
|
||||
r = pclose( fp );
|
||||
if( r > 0 )
|
||||
{
|
||||
exit_status = WEXITSTATUS( r );
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"hpa_dco_status(): hdparm failed, \"%s\" exit status = %u",
|
||||
hdparm_cmd_get_dco,
|
||||
exit_status );
|
||||
}
|
||||
|
||||
if( exit_status == 127 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Command not found. Installing hdparm is mandatory !" );
|
||||
set_return_value = 2;
|
||||
if( nwipe_options.nousb )
|
||||
{
|
||||
return set_return_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare the results of hdparm -N (HPA set / HPA real)
|
||||
* and hdparm --dco-identidy (real max sectors). All three
|
||||
* values may be different or perhaps 'HPA set' and 'HPA real' are
|
||||
* different and 'HPA real' matches 'real max sectors'.
|
||||
*
|
||||
* A perfect HPA disabled result would be where all three
|
||||
* values are the same. It can then be considered that the
|
||||
* HPA is disabled.
|
||||
*
|
||||
* If 'HPA set' and 'HPA real' are different then it
|
||||
* can be considered that HPA is enabled, assuming 'HPA set'
|
||||
* and 'HPA real' are not 0/1 which occurs when a SG_IO error
|
||||
* occurs. That also is checked for as it often indicates a
|
||||
* poor USB device that does not have ATA pass through support.
|
||||
*
|
||||
* However we also need to consider that more recent drives
|
||||
* no longer support HPA/DCO such as the Seagate ST10000NM0016,
|
||||
* ST4000NM0033 and ST1000DM003. If you try to issue those drives
|
||||
* with the ATA command code 0xB1 (device configuration overlay)
|
||||
* you will get a generic illegal request in the returned sense data.
|
||||
*
|
||||
* One other thing to note, we use HPA enabled/disabled to mean
|
||||
* hidden area detected or not detected, this could be caused by
|
||||
* either the dco-setmax being issued or Np, either way an area
|
||||
* of the disc can be hidden. From the user interface we just call
|
||||
* it a HPA/DCO hidden area detected (or not) which is more
|
||||
* meaningful than just saying HDA enabled or disabled and a user
|
||||
* not familiar with the term HPA or DCO not understanding why a
|
||||
* HDA being detected could be significant.
|
||||
*/
|
||||
|
||||
/* Determine, based on the values of 'HPA set', 'HPA real and
|
||||
* 'real max sectors' whether we set the HPA flag as HPA_DISABLED,
|
||||
* HPA_ENABLED, HPA_UNKNOWN or HPA_NOT_APPLICABLE. The HPA flag
|
||||
* will be displayed in the GUI and on the certificate and is
|
||||
* used to determine whether to reset the HPA.
|
||||
*
|
||||
*/
|
||||
|
||||
/* WARNING temp assignments WARNING
|
||||
* s=28,r=28,rm=0
|
||||
*
|
||||
*/
|
||||
#if 0
|
||||
c->HPA_reported_set = 10;
|
||||
c->HPA_reported_real = 28;
|
||||
c->DCO_reported_real_max_sectors = 0;
|
||||
|
||||
c->HPA_reported_set = 28;
|
||||
c->HPA_reported_real = 28;
|
||||
c->DCO_reported_real_max_sectors = 0;
|
||||
|
||||
c->HPA_reported_set = 1000;
|
||||
c->HPA_reported_real = 2048;
|
||||
c->DCO_reported_real_max_sectors = 2048;
|
||||
#endif
|
||||
|
||||
/* If any of the HPA or DCO values are larger than the apparent size then HPA is enabled. */
|
||||
if( /*c->HPA_reported_set > c->device_size_in_sectors || */ c->HPA_reported_real > c->device_size_in_512byte_sectors
|
||||
|| c->DCO_reported_real_max_sectors > c->device_size_in_512byte_sectors )
|
||||
{
|
||||
c->HPA_status = HPA_ENABLED;
|
||||
nwipe_log( NWIPE_LOG_WARNING, " *********************************" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, " *** HIDDEN SECTORS DETECTED ! *** on %s", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_WARNING, " *********************************" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This occurs when a SG_IO error occurs with USB devices that don't support ATA pass
|
||||
* through */
|
||||
if( c->HPA_reported_set == 0 && c->HPA_reported_real == 0 && c->DCO_reported_real_max_sectors <= 1 )
|
||||
{
|
||||
c->HPA_status = HPA_UNKNOWN;
|
||||
if( c->device_bus == NWIPE_DEVICE_USB )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"HIDDEN SECTORS INDETERMINATE! on %s, Some USB adapters & memory sticks don't support "
|
||||
"ATA pass through",
|
||||
c->device_name );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c->HPA_status = HPA_DISABLED;
|
||||
nwipe_log( NWIPE_LOG_INFO, "No hidden sectors on %s", c->device_name );
|
||||
}
|
||||
}
|
||||
|
||||
c->DCO_reported_real_max_size = c->DCO_reported_real_max_sectors * c->device_sector_size;
|
||||
|
||||
nwipe_dco_real_max_sectors = nwipe_read_dco_real_max_sectors( c->device_name );
|
||||
|
||||
/* Analyse all the variations to produce the final real max bytes which takes into
|
||||
* account drives that don't support DCO or HPA. This result is used in the PDF
|
||||
* creation functions.
|
||||
*/
|
||||
|
||||
if( c->device_type == NWIPE_DEVICE_NVME || c->device_type == NWIPE_DEVICE_VIRT
|
||||
|| c->HPA_status == HPA_NOT_APPLICABLE )
|
||||
{
|
||||
c->Calculated_real_max_size_in_bytes = c->device_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the DCO is reporting a real max sectors > the apparent size
|
||||
* as reported by libata then that is what we will use as the real disc size
|
||||
*/
|
||||
if( c->DCO_reported_real_max_size > c->device_size_in_512byte_sectors )
|
||||
{
|
||||
c->Calculated_real_max_size_in_bytes = c->DCO_reported_real_max_sectors * c->device_sector_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If HPA is enabled and DCO real max sectors did not exist, then we have to assume - c->HPA_reported_real
|
||||
* is the value we need, however if that is zero, then c->HPA_reported_set and if that is zero then
|
||||
* c->device_size as reported by libata
|
||||
*/
|
||||
if( c->HPA_reported_real > c->device_size_in_512byte_sectors )
|
||||
{
|
||||
c->Calculated_real_max_size_in_bytes = c->HPA_reported_real * c->device_sector_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c->HPA_reported_set > c->device_size_in_512byte_sectors )
|
||||
{
|
||||
c->Calculated_real_max_size_in_bytes = c->HPA_reported_set * c->device_sector_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->Calculated_real_max_size_in_bytes = c->device_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
* create two variables for later use by the PDF creation function
|
||||
* based on real max sectors and calculated real max size in bytes.
|
||||
*
|
||||
* DCO_reported_real_max_size = real max sectors * sector size = bytes
|
||||
* DCO_reported_real_max_size_text = human readable string, i.e 1TB etc.
|
||||
*/
|
||||
|
||||
Determine_C_B_nomenclature(
|
||||
c->DCO_reported_real_max_size, c->DCO_reported_real_max_size_text, NWIPE_DEVICE_SIZE_TXT_LENGTH );
|
||||
Determine_C_B_nomenclature(
|
||||
c->Calculated_real_max_size_in_bytes, c->Calculated_real_max_size_in_bytes_text, NWIPE_DEVICE_SIZE_TXT_LENGTH );
|
||||
|
||||
/* ----------------------------------------------------------------------------------
|
||||
* Determine the size of the HPA if it's enabled and store the results in the context
|
||||
*/
|
||||
|
||||
if( c->HPA_status == HPA_ENABLED )
|
||||
{
|
||||
if( c->Calculated_real_max_size_in_bytes != c->device_size )
|
||||
{
|
||||
c->HPA_sectors =
|
||||
( (u64) ( c->Calculated_real_max_size_in_bytes - c->device_size ) / c->device_sector_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
c->HPA_sectors = 0;
|
||||
}
|
||||
|
||||
/* Convert the size to a human readable format and save in context */
|
||||
Determine_C_B_nomenclature( c->HPA_sectors, c->HPA_size_text, NWIPE_DEVICE_SIZE_TXT_LENGTH );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HPA not enabled so initialise these values */
|
||||
c->HPA_sectors = 0;
|
||||
c->HPA_size_text[0] = 0;
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_DEBUG,
|
||||
"c->Calculated_real_max_size_in_bytes=%lli, c->device_size=%lli, c->device_sector_size=%lli, "
|
||||
"c->DCO_reported_real_max_size=%lli, c->DCO_reported_real_max_sectors=%lli, c->HPA_sectors=%lli, "
|
||||
"c->HPA_reported_set=%lli, c->HPA_reported_real=%lli, c->device_type=%i, "
|
||||
"libata:c->device_size_in_sectors=%lli ",
|
||||
"libata:c->device_size_in_512byte_sectors=%lli ",
|
||||
c->Calculated_real_max_size_in_bytes,
|
||||
c->device_size,
|
||||
c->device_sector_size,
|
||||
c->DCO_reported_real_max_size,
|
||||
c->DCO_reported_real_max_sectors,
|
||||
c->HPA_sectors,
|
||||
c->HPA_reported_set,
|
||||
c->HPA_reported_real,
|
||||
c->device_type,
|
||||
c->device_size_in_sectors,
|
||||
c->device_size_in_512byte_sectors );
|
||||
|
||||
return set_return_value;
|
||||
}
|
||||
|
||||
u64 nwipe_read_dco_real_max_sectors( char* device )
|
||||
{
|
||||
/* This function sends a device configuration overlay identify command 0xB1 (dco-identify)
|
||||
* to the drive and extracts the real max sectors. The value is incremented by 1 and
|
||||
* then returned. We rely upon this function to determine real max sectors as there
|
||||
* is a bug in hdparm 9.60, including possibly earlier or later versions but which is
|
||||
* fixed in 9.65, that returns a incorrect (negative) value
|
||||
* for some drives that are possibly over a certain size.
|
||||
*/
|
||||
|
||||
/* TODO Add checks in case of failure, especially with recent drives that may not
|
||||
* support drive configuration overlay commands.
|
||||
*/
|
||||
|
||||
#define LBA_SIZE 512
|
||||
#define CMD_LEN 16
|
||||
#define BLOCK_MAX 65535
|
||||
#define LBA_MAX ( 1 << 30 )
|
||||
#define SENSE_BUFFER_SIZE 32
|
||||
|
||||
u64 nwipe_real_max_sectors;
|
||||
|
||||
/* This command issues command 0xb1 (dco-identify) 15th byte */
|
||||
unsigned char cmd_blk[CMD_LEN] = { 0x85, 0x08, 0x0e, 0x00, 0xc2, 0, 0x01, 0, 0, 0, 0, 0, 0, 0x40, 0xb1, 0 };
|
||||
|
||||
sg_io_hdr_t io_hdr;
|
||||
unsigned char buffer[LBA_SIZE]; // Received data block
|
||||
unsigned char sense_buffer[SENSE_BUFFER_SIZE]; // Sense data
|
||||
|
||||
/* three characters represent one byte of sense data, i.e
|
||||
* two characters and a space "01 AE 67"
|
||||
*/
|
||||
char sense_buffer_hex[( SENSE_BUFFER_SIZE * 3 ) + 1];
|
||||
|
||||
int i, i2; // index
|
||||
int fd; // file descripter
|
||||
|
||||
if( ( fd = open( device, O_RDWR ) ) < 0 )
|
||||
{
|
||||
/* Unable to open device */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Initialise the sg header for reading the
|
||||
* device configuration overlay identify data
|
||||
*/
|
||||
memset( &io_hdr, 0, sizeof( sg_io_hdr_t ) );
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.cmd_len = sizeof( cmd_blk );
|
||||
io_hdr.mx_sb_len = sizeof( sense_buffer );
|
||||
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
io_hdr.dxfer_len = LBA_SIZE;
|
||||
io_hdr.dxferp = buffer;
|
||||
io_hdr.cmdp = cmd_blk;
|
||||
io_hdr.sbp = sense_buffer;
|
||||
io_hdr.timeout = 20000;
|
||||
|
||||
if( ioctl( fd, SG_IO, &io_hdr ) < 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "IOCTL command failed retrieving DCO" );
|
||||
i2 = 0;
|
||||
for( i = 0, i2 = 0; i < SENSE_BUFFER_SIZE; i++, i2 += 3 )
|
||||
{
|
||||
/* IOCTL returned an error */
|
||||
snprintf( &sense_buffer_hex[i2], sizeof( sense_buffer_hex ), "%02x ", sense_buffer[i] );
|
||||
}
|
||||
sense_buffer_hex[i2] = 0; // terminate string
|
||||
nwipe_log( NWIPE_LOG_DEBUG, "Sense buffer from failed DCO identify cmd:%s", sense_buffer_hex );
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Close the device */
|
||||
close( fd );
|
||||
|
||||
/***************************************************************
|
||||
* Extract the real max sectors from the returned 512 byte block.
|
||||
* Assuming the first word/byte is 0. We extract the bytes & switch
|
||||
* the endian. Words 3-6(bytes 6-13) contain the max sector address
|
||||
*/
|
||||
nwipe_real_max_sectors = (u64) ( (u64) buffer[13] << 56 ) | ( (u64) buffer[12] << 48 ) | ( (u64) buffer[11] << 40 )
|
||||
| ( (u64) buffer[10] << 32 ) | ( (u64) buffer[9] << 24 ) | ( (u64) buffer[8] << 16 ) | ( (u64) buffer[7] << 8 )
|
||||
| buffer[6];
|
||||
|
||||
/* Don't really understand this but hdparm adds 1 to
|
||||
* the real max sectors too, counting zero as sector?
|
||||
* but only increment if it's already greater than zero
|
||||
*/
|
||||
if( nwipe_real_max_sectors > 0 )
|
||||
{
|
||||
nwipe_real_max_sectors++;
|
||||
}
|
||||
|
||||
nwipe_log(
|
||||
NWIPE_LOG_INFO, "func:nwipe_read_dco_real_max_sectors(), DCO real max sectors = %lli", nwipe_real_max_sectors );
|
||||
|
||||
return nwipe_real_max_sectors;
|
||||
}
|
||||
|
||||
int ascii2binary_array( char* input, unsigned char* output_bin, int bin_size )
|
||||
{
|
||||
/* Converts ascii sense data output by hdparm to binary.
|
||||
* Scans a character string that contains hexadecimal ascii data, ignores spaces
|
||||
* and extracts and converts the hexadecimal ascii data to binary and places in a array.
|
||||
* Typically for dco_identify sense data the bin size will be 512 bytes but for error
|
||||
* sense data this would be 32 bytes.
|
||||
*/
|
||||
int idx_in; // Index into ascii input string
|
||||
int idx_out; // Index into the binary output array
|
||||
int byte_count; // Counts which 4 bit value we are working on
|
||||
char upper4bits;
|
||||
char lower4bits;
|
||||
|
||||
byte_count = 0;
|
||||
idx_in = 0;
|
||||
idx_out = 0;
|
||||
while( input[idx_in] != 0 )
|
||||
{
|
||||
if( input[idx_in] >= '0' && input[idx_in] <= '9' )
|
||||
{
|
||||
if( byte_count == 0 )
|
||||
{
|
||||
upper4bits = input[idx_in] - 0x30;
|
||||
byte_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
lower4bits = input[idx_in] - 0x30;
|
||||
output_bin[idx_out++] = ( upper4bits << 4 ) | ( lower4bits );
|
||||
byte_count = 0;
|
||||
|
||||
if( idx_out >= bin_size )
|
||||
{
|
||||
return 0; // output array full.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( input[idx_in] >= 'a' && input[idx_in] <= 'f' )
|
||||
{
|
||||
if( byte_count == 0 )
|
||||
{
|
||||
upper4bits = input[idx_in] - 0x57;
|
||||
byte_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
lower4bits = input[idx_in] - 0x57;
|
||||
output_bin[idx_out++] = ( upper4bits << 4 ) | ( lower4bits );
|
||||
byte_count = 0;
|
||||
|
||||
if( idx_out >= bin_size )
|
||||
{
|
||||
return 0; // output array full.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
idx_in++; // next byte in the input string
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
43
src/hpa_dco.h
Normal file
43
src/hpa_dco.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*.
|
||||
* hpa_dco.h: The header file for the host protected area (HPA) and
|
||||
* disk configuration overlay routines
|
||||
*
|
||||
* Copyright https://github.com/PartialVolume/shredos.x86_64
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
#ifndef HPA_DCO_H_
|
||||
#define HPA_DCO_H_
|
||||
|
||||
#define HPA_DISABLED 0
|
||||
#define HPA_ENABLED 1
|
||||
#define HPA_UNKNOWN 2
|
||||
#define HPA_NOT_APPLICABLE 3
|
||||
#define HPA_NOT_SUPPORTED_BY_DRIVE 4
|
||||
|
||||
int hpa_dco_status( nwipe_context_t* );
|
||||
|
||||
u64 nwipe_read_dco_real_max_sectors( char* );
|
||||
|
||||
typedef struct nwipe_sense_dco_identify_t_t_
|
||||
{
|
||||
/* This struct contains some of the decoded fields from the sense data after a
|
||||
* ATA 0xB1 device configuration overlay command has been issued. We mainly
|
||||
* use it to decode the real max sectors
|
||||
*/
|
||||
u64 dco_real_max_sectors;
|
||||
} nwipe_sense_dco_identify_t_t_;
|
||||
|
||||
#endif /* HPA_DCO_H_ */
|
||||
172
src/logging.c
172
src/logging.c
@@ -36,6 +36,8 @@
|
||||
#include "prng.h"
|
||||
#include "options.h"
|
||||
#include "logging.h"
|
||||
#include "create_pdf.h"
|
||||
#include "miscellaneous.h"
|
||||
|
||||
/* Global array to hold log values to print when logging to STDOUT */
|
||||
char** log_lines;
|
||||
@@ -84,6 +86,19 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
|
||||
/* initialise characters written */
|
||||
chars_written = 0;
|
||||
|
||||
/* Only log messages with the debug label if the command line --verbose
|
||||
* options has been specified, otherwise just return
|
||||
*/
|
||||
if( level == NWIPE_LOG_DEBUG && nwipe_options.verbose == 0 )
|
||||
{
|
||||
r = pthread_mutex_unlock( &mutex1 );
|
||||
if( r != 0 )
|
||||
{
|
||||
fprintf( stderr, "nwipe_log: pthread_mutex_unlock failed. Code %i \n", r );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print the date. The rc script uses the same format. */
|
||||
if( level != NWIPE_LOG_NOTIMESTAMP )
|
||||
{
|
||||
@@ -386,7 +401,6 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
|
||||
}
|
||||
user_abort = 1;
|
||||
terminate_signal = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,9 +419,6 @@ void nwipe_perror( int nwipe_errno, const char* f, const char* s )
|
||||
{
|
||||
/**
|
||||
* Wrapper for perror().
|
||||
*
|
||||
* We may wish to tweak or squelch this later.
|
||||
*
|
||||
*/
|
||||
|
||||
nwipe_log( NWIPE_LOG_ERROR, "%s: %s: %s", f, s, strerror( nwipe_errno ) );
|
||||
@@ -603,16 +614,16 @@ int nwipe_log_sysinfo()
|
||||
if( *( &dmidecode_keywords[keywords_idx][1][0] ) == '0' )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], "XXXXXXXXXXXXXXX" );
|
||||
NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], "XXXXXXXXXXXXXXX" );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
|
||||
}
|
||||
}
|
||||
/* close */
|
||||
@@ -635,7 +646,12 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
{
|
||||
/* Prints two summary tables, the first is the device pass and verification summary
|
||||
* and the second is the main summary table detaining the drives, status, throughput,
|
||||
* model and serial number */
|
||||
* model and serial number.
|
||||
*
|
||||
* This function also calls the create_pdf() function that creates the PDF erasure
|
||||
* report file. A page report on the success or failure of the erasure operation
|
||||
*/
|
||||
|
||||
int i;
|
||||
int idx_src;
|
||||
int idx_dest;
|
||||
@@ -650,7 +666,7 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
// char duration[5];
|
||||
char duration[314];
|
||||
char model[18];
|
||||
char serial_no[20];
|
||||
char serial_no[NWIPE_SERIALNUMBER_LENGTH + 1];
|
||||
char exclamation_flag[2];
|
||||
int hours;
|
||||
int minutes;
|
||||
@@ -775,26 +791,32 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
|
||||
strncpy( status, "-FAILED-", 8 );
|
||||
status[8] = 0;
|
||||
|
||||
strcpy( c[i]->wipe_status_txt, "FAILED" ); // copy to context for use by certificate
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c[i]->wipe_status == 0 )
|
||||
if( c[i]->wipe_status == 0 /* && user_abort != 1 */ )
|
||||
{
|
||||
strncpy( exclamation_flag, " ", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
|
||||
strncpy( status, " Erased ", 8 );
|
||||
status[8] = 0;
|
||||
|
||||
strcpy( c[i]->wipe_status_txt, "ERASED" ); // copy to context for use by certificate
|
||||
}
|
||||
else
|
||||
{
|
||||
if( user_abort == 1 )
|
||||
if( c[i]->wipe_status == 1 && user_abort == 1 )
|
||||
{
|
||||
strncpy( exclamation_flag, "!", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
|
||||
strncpy( status, "UABORTED", 8 );
|
||||
status[8] = 0;
|
||||
|
||||
strcpy( c[i]->wipe_status_txt, "ABORTED" ); // copy to context for use by certificate
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -804,6 +826,8 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
|
||||
strncpy( status, "INSANITY", 8 );
|
||||
status[8] = 0;
|
||||
|
||||
strcpy( c[i]->wipe_status_txt, "INSANITY" ); // copy to context for use by certificate
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -811,6 +835,9 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
/* Determine the size of throughput so that the correct nomenclature can be used */
|
||||
Determine_C_B_nomenclature( c[i]->throughput, throughput, 13 );
|
||||
|
||||
/* write the duration string to the drive context for later use by create_pdf() */
|
||||
snprintf( c[i]->throughput_txt, sizeof( c[i]->throughput_txt ), "%s", throughput );
|
||||
|
||||
/* Add this devices throughput to the total throughput */
|
||||
total_throughput += c[i]->throughput;
|
||||
|
||||
@@ -825,8 +852,13 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
{
|
||||
if( c[i]->start_time != 0 && c[i]->end_time == 0 )
|
||||
{
|
||||
/* For a summary in the event of a system shutdown */
|
||||
/* For a summary in the event of a system shutdown, user abort */
|
||||
c[i]->duration = difftime( t, c[i]->start_time );
|
||||
|
||||
/* If end_time is zero, which may occur if the wipe is aborted, then set
|
||||
* end_time to current time. Important to do as endtime is used by
|
||||
* the PDF report function */
|
||||
c[i]->end_time = time( &t );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -835,12 +867,16 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
/* Convert binary seconds into three binary variables, hours, minutes and seconds */
|
||||
convert_seconds_to_hours_minutes_seconds( total_duration_seconds, &hours, &minutes, &seconds );
|
||||
|
||||
/* write the duration string to the drive context for later use by create_pdf() */
|
||||
snprintf( c[i]->duration_str, sizeof( c[i]->duration_str ), "%02i:%02i:%02i", hours, minutes, seconds );
|
||||
|
||||
/* Device Model */
|
||||
strncpy( model, c[i]->device_model, 17 );
|
||||
model[17] = 0;
|
||||
|
||||
/* Serial No. */
|
||||
strncpy( serial_no, c[i]->device_serial_no, 20 );
|
||||
strncpy( serial_no, c[i]->device_serial_no, NWIPE_SERIALNUMBER_LENGTH );
|
||||
serial_no[NWIPE_SERIALNUMBER_LENGTH] = 0;
|
||||
model[17] = 0;
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
@@ -854,6 +890,15 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
seconds,
|
||||
model,
|
||||
serial_no );
|
||||
|
||||
/* Create the PDF report/certificate */
|
||||
if( nwipe_options.PDF_enable == 1 )
|
||||
// if( strcmp( nwipe_options.PDFreportpath, "noPDF" ) != 0 )
|
||||
{
|
||||
/* to have some progress indication. can help if there are many/slow disks */
|
||||
fprintf( stderr, "." );
|
||||
create_pdf( c[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the size of throughput so that the correct nomenclature can be used */
|
||||
@@ -903,105 +948,12 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"********************************************************************************" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "" );
|
||||
}
|
||||
|
||||
void Determine_C_B_nomenclature( u64 speed, char* result, int result_array_size )
|
||||
{
|
||||
|
||||
/* C_B ? Determine Capacity or Bandwidth nomenclature
|
||||
*
|
||||
* A pointer to a result character string with a minimum of 13 characters in length
|
||||
* should be provided.
|
||||
*
|
||||
* Outputs a string of the form xxxTB/s, xxxGB/s, xxxMB/s, xxxKB/s B/s depending on the value of 'speed'
|
||||
/* Log information regarding where the PDF certificate is saved but log after the summary table so
|
||||
* this information is only printed once.
|
||||
*/
|
||||
|
||||
/* Initialise the output array */
|
||||
int idx = 0;
|
||||
|
||||
while( idx < result_array_size )
|
||||
if( strcmp( nwipe_options.PDFreportpath, "noPDF" ) != 0 )
|
||||
{
|
||||
result[idx++] = 0;
|
||||
}
|
||||
|
||||
/* Determine the size of throughput so that the correct nomenclature can be used */
|
||||
if( speed >= INT64_C( 1000000000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu TB", speed / INT64_C( 1000000000000 ) );
|
||||
}
|
||||
else if( speed >= INT64_C( 1000000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu GB", speed / INT64_C( 1000000000 ) );
|
||||
}
|
||||
else if( speed >= INT64_C( 1000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu MB", speed / INT64_C( 1000000 ) );
|
||||
}
|
||||
else if( speed >= INT64_C( 1000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu KB", speed / INT64_C( 1000 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu B", speed / INT64_C( 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void convert_seconds_to_hours_minutes_seconds( u64 total_seconds, int* hours, int* minutes, int* seconds )
|
||||
{
|
||||
/* Convert binary seconds into binary hours, minutes and seconds */
|
||||
|
||||
if( total_seconds % 60 )
|
||||
{
|
||||
*minutes = total_seconds / 60;
|
||||
|
||||
*seconds = total_seconds - ( *minutes * 60 );
|
||||
}
|
||||
else
|
||||
{
|
||||
*minutes = total_seconds / 60;
|
||||
|
||||
*seconds = 0;
|
||||
}
|
||||
if( *minutes > 59 )
|
||||
{
|
||||
*hours = *minutes / 60;
|
||||
if( *minutes % 60 )
|
||||
{
|
||||
*minutes = *minutes - ( *hours * 60 );
|
||||
}
|
||||
else
|
||||
{
|
||||
*minutes = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nwipe_strip_path( char* output, char* input )
|
||||
{
|
||||
/* Take the input string, say "/dev/sda" and remove the "/dev/", prefix the result
|
||||
* with 'length' spaces. So if length=8 and input=/dev/sda, output will
|
||||
* be " sda", a string 8 characters long right justified with spaces.
|
||||
*/
|
||||
int idx_dest;
|
||||
int idx_src;
|
||||
idx_dest = 8;
|
||||
// idx_dest = length;
|
||||
output[idx_dest--] = 0;
|
||||
idx_src = strlen( input );
|
||||
idx_src--;
|
||||
|
||||
while( idx_dest >= 0 )
|
||||
{
|
||||
/* if the device name contains a / start prefixing spaces */
|
||||
if( input[idx_src] == '/' )
|
||||
{
|
||||
output[idx_dest--] = ' ';
|
||||
continue;
|
||||
}
|
||||
if( idx_src >= 0 )
|
||||
{
|
||||
output[idx_dest--] = input[idx_src--];
|
||||
}
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "Creating PDF report in %s\n", nwipe_options.PDFreportpath );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,17 +22,18 @@
|
||||
#define LOGGING_H_
|
||||
|
||||
/* Maximum size of a log message */
|
||||
#define MAX_LOG_LINE_CHARS 512
|
||||
#define MAX_LOG_LINE_CHARS 1024
|
||||
|
||||
#define MAX_SIZE_OS_STRING 1024 /* Maximum size of acceptable OS string */
|
||||
|
||||
#define MAX_SIZE_OS_STRING 512 /* Maximum size of acceptable OS string */
|
||||
#define OS_info_Line_offset 31 /* OS_info line offset in log */
|
||||
#define OS_info_Line_Length 48 /* OS_info line length */
|
||||
|
||||
typedef enum nwipe_log_t_ {
|
||||
NWIPE_LOG_NONE = 0,
|
||||
NWIPE_LOG_DEBUG, // TODO: Very verbose logging.
|
||||
NWIPE_LOG_INFO, // TODO: Verbose logging.
|
||||
NWIPE_LOG_NOTICE, // Most logging happens at this level.
|
||||
NWIPE_LOG_DEBUG, // Output only when --verbose option used on cmd line.
|
||||
NWIPE_LOG_INFO, // General Info not specifically relevant to the wipe.
|
||||
NWIPE_LOG_NOTICE, // Most logging happens at this level related to wiping.
|
||||
NWIPE_LOG_WARNING, // Things that the user should know about.
|
||||
NWIPE_LOG_ERROR, // Non-fatal errors that result in failure.
|
||||
NWIPE_LOG_FATAL, // Errors that cause the program to exit.
|
||||
@@ -40,13 +41,25 @@ typedef enum nwipe_log_t_ {
|
||||
NWIPE_LOG_NOTIMESTAMP // logs the message without the timestamp
|
||||
} nwipe_log_t;
|
||||
|
||||
/**
|
||||
* Writes a string to the log. nwipe_log timestamps the string
|
||||
* @param level the tag to display:
|
||||
* NWIPE_LOG_NONE Don't display a tag
|
||||
* NWIPE_LOG_DEBUG, Very verbose logging.
|
||||
* NWIPE_LOG_INFO, Verbose logging.
|
||||
* NWIPE_LOG_NOTICE, Most logging happens at this level.
|
||||
* NWIPE_LOG_WARNING, Things that the user should know about.
|
||||
* NWIPE_LOG_ERROR, Non-fatal errors that result in failure.
|
||||
* NWIPE_LOG_FATAL, Errors that cause the program to exit.
|
||||
* NWIPE_LOG_SANITY, Programming errors.
|
||||
* NWIPE_LOG_NOTIMESTAMP logs the message without the timestamp
|
||||
* @param format the string to be logged
|
||||
*/
|
||||
void nwipe_log( nwipe_log_t level, const char* format, ... );
|
||||
|
||||
void nwipe_perror( int nwipe_errno, const char* f, const char* s );
|
||||
void nwipe_log_OSinfo();
|
||||
int nwipe_log_sysinfo();
|
||||
void nwipe_log_summary( nwipe_context_t**, int ); // This produces the wipe status table on exit
|
||||
void Determine_C_B_nomenclature( u64, char*, int );
|
||||
void convert_seconds_to_hours_minutes_seconds( u64, int*, int*, int* );
|
||||
int nwipe_strip_path( char*, char* );
|
||||
|
||||
#endif /* LOGGING_H_ */
|
||||
|
||||
31
src/method.c
31
src/method.c
@@ -172,7 +172,7 @@ void* nwipe_one( void* ptr )
|
||||
/* set wipe in progress flag for GUI */
|
||||
c->wipe_status = 1;
|
||||
|
||||
/* setup for a zero-fill. */
|
||||
/* setup for a one-fill. */
|
||||
|
||||
char onefill[1] = { '\xFF' };
|
||||
nwipe_pattern_t patterns[] = { { 1, &onefill[0] }, // pass 1: 1s
|
||||
@@ -1215,7 +1215,11 @@ void calculate_round_size( nwipe_context_t* c )
|
||||
* all methods and processed first then created a switch statement that contains method specific changes if any
|
||||
*/
|
||||
|
||||
/* Don't change the order of these values as the case statements use their index in the array */
|
||||
/* Don't change the order of these values as the case statements use their index in the array, New methods
|
||||
* don't need to be added to this array unless they have complicated calculations like Ops2 and IS5. If you do
|
||||
* add a method, just add it to the bottom of the array_methods array and also to the bottom of the switch
|
||||
* statement.
|
||||
*/
|
||||
void* array_methods[] = { &nwipe_zero,
|
||||
&nwipe_ops2,
|
||||
&nwipe_dodshort,
|
||||
@@ -1226,13 +1230,17 @@ void calculate_round_size( nwipe_context_t* c )
|
||||
NULL };
|
||||
int i;
|
||||
|
||||
/* This while loop allows us to effectively create a const so we can use a case statement rather than if statements.
|
||||
* This is probably more readable as more methods may get added in the future. The code could be condensed as some
|
||||
* methods have identical adjustments, however as there are only a few methods I felt it was easier to understand as
|
||||
* it is, however this could be changed if necessary.
|
||||
/* This while loop allows us to effectively create a const that represents a method so we can use a case statement
|
||||
* rather than if statements.
|
||||
*
|
||||
* Using a switch statement looks better than if statments as more methods may get added in the future expanding the
|
||||
* list. The code could be condensed as some methods have identical adjustments, however as there are only a few
|
||||
* methods I felt it was easier to understand as it is, however this could be changed if necessary.
|
||||
*/
|
||||
|
||||
int selected_method;
|
||||
/* Initialise, -1 = no additional calculation required */
|
||||
int selected_method = -1;
|
||||
|
||||
i = 0;
|
||||
while( array_methods[i] != NULL )
|
||||
{
|
||||
@@ -1243,6 +1251,10 @@ void calculate_round_size( nwipe_context_t* c )
|
||||
i++;
|
||||
}
|
||||
|
||||
/* On exit from the while loop the selected method either equals an index to a method
|
||||
* or it equals -1 which means no extra calculations are required that are method specific
|
||||
*/
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
/* We must read back all passes, so double the byte count. */
|
||||
@@ -1369,6 +1381,11 @@ void calculate_round_size( nwipe_context_t* c )
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case -1:
|
||||
/* Method not listed so don't do any extra calculations
|
||||
* ---------------------------------------------------- */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
666
src/miscellaneous.c
Normal file
666
src/miscellaneous.c
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
* miscellaneous.c: functions that may be generally used throughout nwipes code,
|
||||
* mainly string processing functions but also time related functions.
|
||||
*
|
||||
* Copyright PartialVolume <https://github.com/PartialVolume>.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
#include "logging.h"
|
||||
#include "miscellaneous.h"
|
||||
|
||||
/* Convert string to upper case
|
||||
*/
|
||||
void strupper( char* str )
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = 0;
|
||||
while( str[idx] != 0 )
|
||||
{
|
||||
/* If upper case alpha character, change to lower case */
|
||||
if( str[idx] >= 'A' && str[idx] <= 'Z' )
|
||||
{
|
||||
str[idx] -= 32;
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert string to lower case
|
||||
*/
|
||||
void strlower( char* str )
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = 0;
|
||||
while( str[idx] != 0 )
|
||||
{
|
||||
/* If upper case alpha character, change to lower case */
|
||||
if( str[idx] >= 'A' && str[idx] <= 'Z' )
|
||||
{
|
||||
str[idx] += 32;
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void strip_CR_LF( char* str )
|
||||
{
|
||||
/* In the specified string, replace any CR or LF with a space */
|
||||
int idx = 0;
|
||||
int len = strlen( str );
|
||||
while( idx < len )
|
||||
{
|
||||
if( str[idx] == 0x0A || str[idx] == 0x0D )
|
||||
{
|
||||
str[idx] = ' ';
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search a string for a positive number, convert the first
|
||||
* number found to binary and return the binary number.
|
||||
* returns the number or -1 if number too large or -2 if
|
||||
* no number found.
|
||||
*/
|
||||
|
||||
u64 str_ascii_number_to_ll( char* str )
|
||||
{
|
||||
int idx;
|
||||
int idx2;
|
||||
char number_copy[20];
|
||||
|
||||
idx = 0; // index into the main string we are searching
|
||||
idx2 = 0; // index used for backup copy of ascii number
|
||||
|
||||
while( str[idx] != 0 )
|
||||
{
|
||||
/* Find the start of the number */
|
||||
if( str[idx] >= '0' && str[idx] <= '9' )
|
||||
{
|
||||
while( str[idx] != 0 )
|
||||
{
|
||||
/* Find the end of the number */
|
||||
if( str[idx] >= '0' && str[idx] <= '9' )
|
||||
{
|
||||
if( idx2 < sizeof( number_copy ) - 1 )
|
||||
{
|
||||
number_copy[idx2++] = str[idx++];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Number is too large ! */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* end found */
|
||||
number_copy[idx2] = 0; // terminate our copy
|
||||
|
||||
/* convert ascii number to longlong */
|
||||
return atoll( number_copy );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
return -2; /* no number found */
|
||||
}
|
||||
|
||||
void Determine_C_B_nomenclature( u64 qty, char* result, int result_array_size )
|
||||
{
|
||||
|
||||
/* C_B ? Determine Capacity or Bandwidth nomenclature
|
||||
*
|
||||
* A pointer to a result character string with a minimum of 13 characters in length
|
||||
* should be provided.
|
||||
*
|
||||
* Outputs a string of the form xxxTB, xxxGB, xxxMB, xxxKB B depending on the value of 'qty'
|
||||
*/
|
||||
|
||||
/* Initialise the output array */
|
||||
int idx = 0;
|
||||
|
||||
while( idx < result_array_size )
|
||||
{
|
||||
result[idx++] = 0;
|
||||
}
|
||||
|
||||
/* Determine the size of throughput so that the correct nomenclature can be used */
|
||||
if( qty >= INT64_C( 10000000000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%4llu TB", qty / INT64_C( 1000000000000 ) );
|
||||
}
|
||||
else if( qty >= INT64_C( 10000000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%4llu GB", qty / INT64_C( 1000000000 ) );
|
||||
}
|
||||
else if( qty >= INT64_C( 10000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%4llu MB", qty / INT64_C( 1000000 ) );
|
||||
}
|
||||
else if( qty >= INT64_C( 10000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%4llu KB", qty / INT64_C( 1000 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( result, result_array_size, "%4llu B", qty / INT64_C( 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void convert_seconds_to_hours_minutes_seconds( u64 total_seconds, int* hours, int* minutes, int* seconds )
|
||||
{
|
||||
/* Convert binary seconds into binary hours, minutes and seconds */
|
||||
|
||||
if( total_seconds % 60 )
|
||||
{
|
||||
*minutes = total_seconds / 60;
|
||||
|
||||
*seconds = total_seconds - ( *minutes * 60 );
|
||||
}
|
||||
else
|
||||
{
|
||||
*minutes = total_seconds / 60;
|
||||
|
||||
*seconds = 0;
|
||||
}
|
||||
if( *minutes > 59 )
|
||||
{
|
||||
*hours = *minutes / 60;
|
||||
if( *minutes % 60 )
|
||||
{
|
||||
*minutes = *minutes - ( *hours * 60 );
|
||||
}
|
||||
else
|
||||
{
|
||||
*minutes = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nwipe_strip_path( char* output, char* input )
|
||||
{
|
||||
/* Take the input string, say "/dev/sda" and remove the "/dev/", prefix the result
|
||||
* with 'length' spaces. So if length=8 and input=/dev/sda, output will
|
||||
* be " sda", a string 8 characters long right justified with spaces.
|
||||
*/
|
||||
int idx_dest;
|
||||
int idx_src;
|
||||
idx_dest = 8;
|
||||
// idx_dest = length;
|
||||
output[idx_dest--] = 0;
|
||||
idx_src = strlen( input );
|
||||
idx_src--;
|
||||
|
||||
while( idx_dest >= 0 )
|
||||
{
|
||||
/* if the device name contains a / start prefixing spaces */
|
||||
if( input[idx_src] == '/' )
|
||||
{
|
||||
output[idx_dest--] = ' ';
|
||||
continue;
|
||||
}
|
||||
if( idx_src >= 0 )
|
||||
{
|
||||
output[idx_dest--] = input[idx_src--];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void replace_non_alphanumeric( char* str, char replacement_char )
|
||||
{
|
||||
int i = 0;
|
||||
while( str[i] != 0 )
|
||||
{
|
||||
if( str[i] < '0' || ( str[i] > '9' && str[i] < 'A' ) || ( str[i] > 'Z' && str[i] < 'a' ) || str[i] > 'z' )
|
||||
{
|
||||
str[i] = replacement_char;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void convert_double_to_string( char* output_str, double value )
|
||||
{
|
||||
int idx = 0;
|
||||
int idx2;
|
||||
int idx3 = 0;
|
||||
|
||||
char percstr[512] = "";
|
||||
|
||||
snprintf( percstr, sizeof( percstr ), "%5.32lf", value );
|
||||
|
||||
while( percstr[idx] != 0 )
|
||||
{
|
||||
if( percstr[idx] == '.' )
|
||||
{
|
||||
for( idx2 = 0; idx2 < 3; idx2++ )
|
||||
{
|
||||
output_str[idx3++] = percstr[idx++];
|
||||
}
|
||||
break;
|
||||
}
|
||||
output_str[idx3++] = percstr[idx++];
|
||||
}
|
||||
output_str[idx3] = 0;
|
||||
}
|
||||
|
||||
int read_system_datetime( char* year, char* month, char* day, char* hours, char* minutes, char* seconds )
|
||||
{
|
||||
/* Reads system date & time and populates the caller provided strings.
|
||||
* Each string is null terminated by this function. The calling program
|
||||
* must provide the minimum string sizes as shown below.
|
||||
*
|
||||
* year 5 bytes (4 numeric digits plus NULL terminator)
|
||||
* month 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* day 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* hours 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* minutes 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* seconds 3 bytes (2 numeric digits plus NULL terminator)
|
||||
*
|
||||
* return value:
|
||||
* 0 = success
|
||||
* -1 = Failure, see nwipe log for detail.
|
||||
*/
|
||||
FILE* fp;
|
||||
int r; // A result buffer.
|
||||
int idx; // general index
|
||||
int status = 0;
|
||||
|
||||
/**
|
||||
* Obtain the year
|
||||
*/
|
||||
fp = popen( "date +%Y", "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to obtain system year using commmand = date +%Y" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the first line and validate it. Should be 4 numeric digits */
|
||||
if( fgets( year, FOUR_DIGITS + 1, fp ) != NULL )
|
||||
{
|
||||
idx = 0;
|
||||
while( idx < 4 )
|
||||
{
|
||||
if( year[idx] >= '0' && year[idx] <= '9' )
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we haven't reached the correct number of digits due to invalid data, log error */
|
||||
year[++idx] = 0; /* terminate the string, prior to using in nwipe_log */
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Obtained system year using command = date +%Y, but result appears invalid = %s",
|
||||
year );
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
year[idx] = 0; /* terminate the string */
|
||||
}
|
||||
r = pclose( fp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the month
|
||||
*/
|
||||
fp = popen( "date +%m", "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to obtain system month using the command = date +%m" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the first line and validate it. Should be 2 numeric digits */
|
||||
if( fgets( month, TWO_DIGITS + 1, fp ) != NULL )
|
||||
{
|
||||
idx = 0;
|
||||
while( idx < 2 )
|
||||
{
|
||||
if( month[idx] >= '0' && month[idx] <= '9' )
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we haven't reached the correct number of digits due to invalid data, log error */
|
||||
month[++idx] = 0; /* terminate the string, prior to using in nwipe_log */
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Obtained system month using command = date +%m, but result appears invalid = %s",
|
||||
month );
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
month[idx] = 0; /* terminate the string */
|
||||
}
|
||||
r = pclose( fp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the day
|
||||
*/
|
||||
fp = popen( "date +\%d", "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to obtain system day using the command = date +\%d" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the first line and validate it. Should be 2 numeric digits */
|
||||
if( fgets( day, TWO_DIGITS + 1, fp ) != NULL )
|
||||
{
|
||||
idx = 0;
|
||||
while( idx < 2 )
|
||||
{
|
||||
if( day[idx] >= '0' && day[idx] <= '9' )
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we haven't reached the correct number of digits due to invalid data, log error */
|
||||
day[++idx] = 0; /* terminate the string, prior to using in nwipe_log */
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Obtained system day using command = date +\%d, but result appears invalid = %s",
|
||||
day );
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
day[idx] = 0; /* terminate the string */
|
||||
}
|
||||
r = pclose( fp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the hours
|
||||
*/
|
||||
fp = popen( "date +%H", "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to obtain system hour using the command = date +%H" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the first line and validate it. Should be 2 numeric digits */
|
||||
if( fgets( hours, TWO_DIGITS + 1, fp ) != NULL )
|
||||
{
|
||||
// nwipe_log( NWIPE_LOG_INFO, "Seconds = %s, Year = %s", seconds, year);
|
||||
idx = 0;
|
||||
while( idx < 2 )
|
||||
{
|
||||
if( hours[idx] >= '0' && hours[idx] <= '9' )
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we haven't reached the correct number of digits due to invalid data, log error */
|
||||
hours[++idx] = 0; /* terminate the string, prior to using in nwipe_log */
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Obtained system hours using command = date +%H, but result appears invalid = %s",
|
||||
hours );
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
hours[idx] = 0; /* terminate the string */
|
||||
}
|
||||
r = pclose( fp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the minutes
|
||||
*/
|
||||
fp = popen( "date +%M", "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to obtain system minutes using the command = date +%M" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the first line and validate it. Should be 2 numeric digits */
|
||||
if( fgets( minutes, TWO_DIGITS + 1, fp ) != NULL )
|
||||
{
|
||||
// nwipe_log( NWIPE_LOG_INFO, "Seconds = %s, Year = %s", seconds, year);
|
||||
idx = 0;
|
||||
while( idx < 2 )
|
||||
{
|
||||
if( minutes[idx] >= '0' && minutes[idx] <= '9' )
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we haven't reached the correct number of digits due to invalid data, log the error */
|
||||
minutes[++idx] = 0; /* terminate the string, prior to using in nwipe_log */
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Obtained system minutes using command = date +%H, but result appears invalid = %s",
|
||||
minutes );
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
minutes[idx] = 0; /* terminate the string */
|
||||
}
|
||||
r = pclose( fp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the seconds
|
||||
*/
|
||||
fp = popen( "date +%S", "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to obtain system seconds using the command = date +%S" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the first line and validate it. Should be 2 numeric digits */
|
||||
if( fgets( seconds, TWO_DIGITS + 1, fp ) != NULL )
|
||||
{
|
||||
// nwipe_log( NWIPE_LOG_INFO, "Seconds = %s, Year = %s", seconds, year);
|
||||
idx = 0;
|
||||
while( idx < 2 )
|
||||
{
|
||||
if( seconds[idx] >= '0' && seconds[idx] <= '9' )
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we haven't reached the correct number of digits due to invalid data, log error */
|
||||
seconds[++idx] = 0; /* terminate the string, prior to using in nwipe_log */
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"Obtained system seconds using command = date +%S, but result appears invalid = %s",
|
||||
seconds );
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
seconds[idx] = 0; /* terminate the string */
|
||||
}
|
||||
r = pclose( fp );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int write_system_datetime( char* year, char* month, char* day, char* hours, char* minutes, char* seconds )
|
||||
{
|
||||
/* Writes the system date & time using data from the caller provided strings.
|
||||
* The calling program must provide the minimum string sizes as shown below
|
||||
* populated with current date and time data.
|
||||
*
|
||||
* year 5 bytes (4 numeric digits plus NULL terminator)
|
||||
* month 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* day 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* hours 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* minutes 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* seconds 3 bytes (2 numeric digits plus NULL terminator)
|
||||
*
|
||||
* return value:
|
||||
* 0 = success
|
||||
* -1 = Failure, see nwipe log for detail.
|
||||
*/
|
||||
FILE* fp;
|
||||
int r; // A result buffer.
|
||||
int idx; // general index
|
||||
int strIdx; // Index into each string
|
||||
int bufferIdx; // Index into the buffer
|
||||
char buffer[5];
|
||||
|
||||
/**
|
||||
* Basic validation that confirms the input strings are numeric and of the correct length, we do this
|
||||
* by first constructing three arrays. The first are the names of the variables in order
|
||||
* year, month, day, hours, minutes and seconds. The second array contains the address of
|
||||
* each of those strings. The third array are the lengths.
|
||||
* This allows us to create a single loop to validate all fields.
|
||||
*/
|
||||
|
||||
char* names[] = { "year", "month", "day", "hours", "minutes", "seconds" };
|
||||
char* pdata[] = { year, month, day, hours, minutes, seconds };
|
||||
int lengths[] = { 4, 2, 2, 2, 2, 2 };
|
||||
char cmd_format[] = "date %s%s%s%s%s.%s >/dev/null 2>&1";
|
||||
char cmd[256];
|
||||
|
||||
for( idx = 0; idx < 6; idx++ )
|
||||
{
|
||||
strIdx = 0; // initialise string index
|
||||
|
||||
/* check each characters is numeric */
|
||||
while( strIdx < lengths[idx] )
|
||||
{
|
||||
if( pdata[idx][strIdx] >= '0' && pdata[idx][strIdx] <= '9' )
|
||||
{
|
||||
strIdx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we haven't reached the correct number of digits due to invalid data, log error,
|
||||
* but first we read the valid data acquired so far into a buffer, this is done to avoid
|
||||
* writing to the user provided string because if they did not size the string correctly
|
||||
* writing a zero at the end could cause a segfault.
|
||||
*/
|
||||
|
||||
for( bufferIdx = 0; bufferIdx < strIdx + 1; bufferIdx++ )
|
||||
{
|
||||
buffer[bufferIdx] = pdata[idx][bufferIdx];
|
||||
}
|
||||
buffer[bufferIdx] = 0; /* terminate the string, prior to using in nwipe_log */
|
||||
|
||||
/* A typical error will look like ..
|
||||
* "User provided year data that appear invalid = 202£" */
|
||||
nwipe_log( NWIPE_LOG_ERROR, "User provided %s data that appears invalid = %s", names[idx], buffer );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Now using the validated strings construct the date command that we will use to write the system date/time
|
||||
*/
|
||||
sprintf( cmd, cmd_format, month, day, hours, minutes, year, seconds );
|
||||
|
||||
/**
|
||||
* Run the date command to write the new date/time
|
||||
*/
|
||||
|
||||
fp = popen( cmd, "w" );
|
||||
r = pclose( fp );
|
||||
|
||||
if( fp == NULL || r != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Failed to write system date/time using command = %s", cmd );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Date/time succesfully writen to system using command = %s", cmd );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fix_endian_model_names( char* model )
|
||||
{
|
||||
/* Some IDE USB adapters get the endian wrong, we can't determine the endian from the drive
|
||||
* as the drive standard doesn't provide that information, so we have to resort to matching
|
||||
* the model name against known strings with the endian incorrect, then reverse the endian.
|
||||
*/
|
||||
|
||||
int idx = 0;
|
||||
int idx2 = 0;
|
||||
unsigned int length = 0;
|
||||
char* tmp_string;
|
||||
|
||||
length = strlen( model );
|
||||
|
||||
tmp_string = calloc( length, 1 );
|
||||
|
||||
/* "ASSMNU G" = "SAMSUNG ", tested against model Samsung HM160HC so that
|
||||
* "ASSMNU G MH61H0 C" becomes "SAMSUNG HM160HC ")
|
||||
*/
|
||||
if( !( strncmp( model, "ASSMNU G", 8 ) ) )
|
||||
{
|
||||
while( model[idx] != 0 )
|
||||
{
|
||||
tmp_string[idx2 + 1] = model[idx];
|
||||
if( model[idx + 1] != 0 )
|
||||
{
|
||||
tmp_string[idx2] = model[idx + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( tmp_string[idx2 + 1] == ' ' && model[idx + 2] == ' ' )
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
|
||||
idx += 2;
|
||||
idx2 += 2;
|
||||
}
|
||||
|
||||
tmp_string[idx2 + 1] = 0;
|
||||
strcpy( model, tmp_string );
|
||||
}
|
||||
}
|
||||
132
src/miscellaneous.h
Normal file
132
src/miscellaneous.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* miscellaneous.h: header file for miscellaneous.c ..
|
||||
*
|
||||
* functions that may be generally used throughout nwipes code,
|
||||
* mainly string processing related functions.
|
||||
*
|
||||
* Copyright PartialVolume <https://github.com/PartialVolume>.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MISCELLANEOUS_H_
|
||||
#define MISCELLANEOUS_H_
|
||||
|
||||
#define FOUR_DIGITS 4
|
||||
#define TWO_DIGITS 2
|
||||
|
||||
/**
|
||||
* Convert the string from lower to upper case
|
||||
* @param pointer to a null terminated string
|
||||
* @return void
|
||||
*/
|
||||
void strupper( char* );
|
||||
|
||||
/**
|
||||
* Convert the string from upper to lower case
|
||||
* @param pointer to a null terminated string
|
||||
* @return void
|
||||
*/
|
||||
void strlower( char* str );
|
||||
|
||||
/**
|
||||
* Search a string for a positive number, convert the first
|
||||
* number found to binary and return the binary number.
|
||||
* returns the number or -1 if number too large or -2 if
|
||||
* no number found.
|
||||
*
|
||||
* @param pointer to a null terminated string
|
||||
* @return longlong returns:
|
||||
* the number
|
||||
* -1 = number too large
|
||||
* -2 = no number found.
|
||||
*/
|
||||
u64 str_ascii_number_to_ll( char* );
|
||||
|
||||
void Determine_C_B_nomenclature( u64, char*, int );
|
||||
void convert_seconds_to_hours_minutes_seconds( u64, int*, int*, int* );
|
||||
int nwipe_strip_path( char*, char* );
|
||||
|
||||
/**
|
||||
* Scan a string and replace any characters that are not alpha-numeric with
|
||||
* the character_char.
|
||||
* Example:
|
||||
* char str[] = 18:21:56;
|
||||
* calling the function replace_non_alphanumeric( &str, '_' )
|
||||
* would result in str changing from 18:21:56 to 18_21_56
|
||||
* @param char* pointer to the string to be processed
|
||||
* @param char the character used to replace non alpha-numeric characters
|
||||
* @return void
|
||||
*/
|
||||
void replace_non_alphanumeric( char*, char );
|
||||
|
||||
/**
|
||||
* I found this function necessary when converting a double of say
|
||||
* 99.999999999999999999 to text using printf. I only wanted 99.99
|
||||
* printed but if you specified a precision of %.2f in printf i.e 2 digits
|
||||
* after the decimal point you get 100.00 and not 99.99 If you increase
|
||||
* the precision to %.10f then you get 99.9999999999 but I only want
|
||||
* two significant digits displayed.i.e 99.99% not 100%
|
||||
* So this function converts to double retaining sufficient precision
|
||||
* so that a 30TB disc with one hidden sector will display as 99.99% erased
|
||||
* As an example if the double value to be converted is 99.999999999999999987
|
||||
* this function will always output 99.99 unlike printf which outputs 100.00
|
||||
* @param char* pointer to the string we write our percentage to. Needs to be
|
||||
* a minimum of 7 bytes, i.e 100.00 plus null terminator.
|
||||
* @param double the floating point value to be converted to a string.
|
||||
* @return void
|
||||
*/
|
||||
void convert_double_to_string( char*, double );
|
||||
|
||||
/**
|
||||
* Reads system date & time and populates the caller provided strings.
|
||||
* Each string is null terminated by this function. The calling
|
||||
* program must provide the minimum string sizes as shown below.
|
||||
*
|
||||
* @param char* year 5 bytes (4 numeric digits plus NULL terminator)
|
||||
* @param char* month 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @param char* day 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @param char* hours 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @param char* minutes 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @param char* seconds 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @return 0 = success, -1 = failure. See nwipe log for detail.
|
||||
*/
|
||||
int read_system_datetime( char*, char*, char*, char*, char*, char* );
|
||||
|
||||
/**
|
||||
* Writes system date & time from the caller provided strings.
|
||||
* The calling program must provide the minimum populated string sizes
|
||||
* as shown below.
|
||||
*
|
||||
* @param char* year 5 bytes (4 numeric digits plus NULL terminator)
|
||||
* @param char* month 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @param char* day 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @param char* hours 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @param char* minutes 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @param char* seconds 3 bytes (2 numeric digits plus NULL terminator)
|
||||
* @return 0 = success, -1 = failure. See nwipe log for detail.
|
||||
*/
|
||||
int write_system_datetime( char*, char*, char*, char*, char*, char* );
|
||||
|
||||
/**
|
||||
* Fixes drive model names that have the incorrect endian. This happens
|
||||
* with some IDE USB adapters.
|
||||
*
|
||||
* @param char* pointer to the drive model names
|
||||
* @return void
|
||||
*/
|
||||
void fix_endian_model_names( char* model );
|
||||
|
||||
#endif /* HPA_DCO_H_ */
|
||||
184
src/nwipe.c
184
src/nwipe.c
@@ -28,10 +28,14 @@
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
@@ -42,6 +46,7 @@
|
||||
#include "logging.h"
|
||||
#include "gui.h"
|
||||
#include "temperature.h"
|
||||
#include "miscellaneous.h"
|
||||
|
||||
#include <sys/ioctl.h> /* FIXME: Twice Included */
|
||||
#include <sys/shm.h>
|
||||
@@ -49,12 +54,31 @@
|
||||
|
||||
#include <parted/parted.h>
|
||||
#include <parted/debug.h>
|
||||
#include "conf.h"
|
||||
#include "version.h"
|
||||
#include "hpa_dco.h"
|
||||
#include "conf.h"
|
||||
#include <libconfig.h>
|
||||
|
||||
int terminate_signal;
|
||||
int user_abort;
|
||||
int global_wipe_status;
|
||||
|
||||
/* helper function for sorting */
|
||||
int devnamecmp( const void* a, const void* b )
|
||||
{
|
||||
// nwipe_log( NWIPE_LOG_DEBUG, "a: %s, b: %s", ( *( nwipe_context_t** ) a)->device_name, ( *( nwipe_context_t** )
|
||||
// b)->device_name );
|
||||
|
||||
int ldiff = strlen( ( *(nwipe_context_t**) a )->device_name ) - strlen( ( *(nwipe_context_t**) b )->device_name );
|
||||
if( ldiff != 0 )
|
||||
{
|
||||
return ldiff;
|
||||
}
|
||||
int ret = strcmp( ( *(nwipe_context_t**) a )->device_name, ( *(nwipe_context_t**) b )->device_name );
|
||||
return ( ret );
|
||||
}
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
int nwipe_optind; // The result of nwipe_options().
|
||||
@@ -64,6 +88,7 @@ int main( int argc, char** argv )
|
||||
int any_threads_still_running; // used in wipe thread cancellation wait loop
|
||||
int thread_timeout_counter; // timeout thread cancellation after THREAD_CANCELLATION_TIMEOUT seconds
|
||||
pthread_t nwipe_gui_thread = 0; // The thread ID of the GUI thread.
|
||||
pthread_t nwipe_temperature_thread = 0; // The thread ID of the temperature update thread
|
||||
pthread_t nwipe_sigint_thread; // The thread ID of the sigint handler.
|
||||
|
||||
char modprobe_command[] = "modprobe %s";
|
||||
@@ -82,12 +107,6 @@ int main( int argc, char** argv )
|
||||
/* The generic result buffer. */
|
||||
int r;
|
||||
|
||||
/* Log nwipes version */
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s", banner );
|
||||
|
||||
/* Log OS info */
|
||||
nwipe_log_OSinfo();
|
||||
|
||||
/* Initialise the termintaion signal, 1=terminate nwipe */
|
||||
terminate_signal = 0;
|
||||
|
||||
@@ -112,11 +131,67 @@ int main( int argc, char** argv )
|
||||
/* Initialised and populated in device scan. */
|
||||
nwipe_context_t** c1 = 0;
|
||||
|
||||
if( geteuid() != 0 )
|
||||
{
|
||||
printf( "nwipe must run with root permissions, which is not the case.\nAborting\n" );
|
||||
exit( 99 );
|
||||
}
|
||||
|
||||
int wipe_threads_started = 0;
|
||||
|
||||
/* Parse command line options. */
|
||||
/** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE **
|
||||
* Important Note: if you want nwipe_log messages to go into the logfile
|
||||
* any 'nwipe_log()' commands must appear after the options are parsed here,
|
||||
* else they will appear in the console but not in the logfile, that is,
|
||||
* assuming you specified a log file on the command line as an nwipe option.
|
||||
*/
|
||||
|
||||
/*****************************
|
||||
* Parse command line options.
|
||||
*/
|
||||
|
||||
/* Initialise the libconfig code that handles nwipe.conf */
|
||||
nwipe_conf_init();
|
||||
|
||||
nwipe_optind = nwipe_options_parse( argc, argv );
|
||||
|
||||
/* Log nwipes version */
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s", banner );
|
||||
|
||||
/* Log OS info */
|
||||
nwipe_log_OSinfo();
|
||||
|
||||
/* Check that hdparm exists, we use hdparm for some HPA/DCO detection etc, if not
|
||||
* exit nwipe. These checks are required if the PATH environment is not setup !
|
||||
* Example: Debian sid 'su' as opposed to 'su -'
|
||||
*/
|
||||
if( system( "which hdparm > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /sbin/hdparm > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /usr/bin/hdparm > /dev/null 2>&1" ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hdparm command not found." );
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"Required by nwipe for HPA/DCO detection & correction and ATA secure erase." );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "** Please install hdparm **\n" );
|
||||
cleanup();
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the given path for PDF reports is a writeable directory */
|
||||
if( strcmp( nwipe_options.PDFreportpath, "noPDF" ) != 0 )
|
||||
{
|
||||
if( access( nwipe_options.PDFreportpath, W_OK ) != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "PDFreportpath %s is not a writeable directory.", nwipe_options.PDFreportpath );
|
||||
cleanup();
|
||||
exit( 2 );
|
||||
}
|
||||
}
|
||||
|
||||
if( nwipe_optind == argc )
|
||||
{
|
||||
/* File names were not given by the user. Scan for devices. */
|
||||
@@ -148,13 +223,18 @@ int main( int argc, char** argv )
|
||||
nwipe_enumerated = nwipe_device_get( &c1, argv, argc );
|
||||
if( nwipe_enumerated == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Devices not found. Check you're not excluding drives unnecessarily." );
|
||||
printf( "No drives found\n" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Devices not found. Check you're not excluding drives unnecessarily," );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "and you are running nwipe as sudo or as root." );
|
||||
printf( "Devices not found, check you're not excluding drives unnecessarily \n and you are running nwipe "
|
||||
"as sudo or as root." );
|
||||
cleanup();
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* sort list of devices here */
|
||||
qsort( (void*) c1, (size_t) nwipe_enumerated, sizeof( nwipe_context_t* ), devnamecmp );
|
||||
|
||||
if( terminate_signal == 1 )
|
||||
{
|
||||
cleanup();
|
||||
@@ -166,6 +246,12 @@ int main( int argc, char** argv )
|
||||
|
||||
/* The array of pointers to contexts that will actually be wiped. */
|
||||
nwipe_context_t** c2 = (nwipe_context_t**) malloc( nwipe_enumerated * sizeof( nwipe_context_t* ) );
|
||||
if( c2 == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "memory allocation for c2 failed" );
|
||||
cleanup();
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* Open the entropy source. */
|
||||
nwipe_entropy = open( NWIPE_KNOB_ENTROPY, O_RDONLY );
|
||||
@@ -255,7 +341,7 @@ int main( int argc, char** argv )
|
||||
/* load the drivetemp module */
|
||||
if( system( final_cmd_modprobe ) != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hwmon: Unable to load module drivetemp, temperatures may be unavilable." );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hwmon: Unable to load module drivetemp, temperatures may be unavailable." );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hwmon: It's possible the drivetemp software isn't modular but built-in" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hwmon: to the kernel, as is the case with ShredOS.x86_64 in which case" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "hwmon: the temperatures will actually be available despite this issue." );
|
||||
@@ -294,7 +380,13 @@ int main( int argc, char** argv )
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Device %s hwmon path = %s", c1[i]->device_name, c1[i]->temp1_path );
|
||||
}
|
||||
|
||||
nwipe_update_temperature( c1[i] );
|
||||
// nwipe_update_temperature( c1[i] );
|
||||
|
||||
/* Log the temperature crtical, highest, lowest and lowest critical temperature
|
||||
* limits to nwipes log file using the INFO catagory
|
||||
*/
|
||||
|
||||
nwipe_log_drives_temperature_limits( c1[i] );
|
||||
}
|
||||
|
||||
/* Check for initialization errors. */
|
||||
@@ -305,6 +397,15 @@ int main( int argc, char** argv )
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set up the data structures to pass the temperature thread the data it needs */
|
||||
nwipe_thread_data_ptr_t nwipe_temperature_thread_data;
|
||||
nwipe_temperature_thread_data.c = c1;
|
||||
nwipe_temperature_thread_data.nwipe_misc_thread_data = &nwipe_misc_thread_data;
|
||||
|
||||
/* Fork the temperature thread */
|
||||
errno = pthread_create(
|
||||
&nwipe_temperature_thread, NULL, nwipe_update_temperature_thread, &nwipe_temperature_thread_data );
|
||||
|
||||
/* Start the ncurses interface. */
|
||||
if( !nwipe_options.nogui )
|
||||
nwipe_gui_init();
|
||||
@@ -326,10 +427,17 @@ int main( int argc, char** argv )
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.PDF_preview_details == 1 )
|
||||
{
|
||||
nwipe_gui_preview_org_customer( SHOWING_PRIOR_TO_DRIVE_SELECTION );
|
||||
}
|
||||
|
||||
nwipe_gui_select( nwipe_enumerated, c1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise some of the variables in the drive contexts
|
||||
*/
|
||||
for( i = 0; i < nwipe_enumerated; i++ )
|
||||
{
|
||||
/* Set the PRNG implementation, which must always come after the function nwipe_gui_select ! */
|
||||
@@ -346,6 +454,9 @@ int main( int argc, char** argv )
|
||||
|
||||
/* Initialise the wipe result value */
|
||||
c1[i]->result = 0;
|
||||
|
||||
/* Initialise the variable that tracks how much of the drive has been erased */
|
||||
c1[i]->bytes_erased = 0;
|
||||
}
|
||||
|
||||
/* Pass the number selected to the struct for other threads */
|
||||
@@ -431,7 +542,8 @@ int main( int argc, char** argv )
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%s has serial number %s", c2[i]->device_name, c2[i]->device_serial_no );
|
||||
}
|
||||
|
||||
/* Do sector size and block size checking. */
|
||||
/* Do sector size and block size checking. I don't think this does anything useful as logical/Physical
|
||||
* sector sizes are obtained by libparted in check.c */
|
||||
if( ioctl( c2[i]->device_fd, BLKSSZGET, &c2[i]->device_sector_size ) == 0 )
|
||||
{
|
||||
|
||||
@@ -702,6 +814,42 @@ int main( int argc, char** argv )
|
||||
thread_timeout_counter--;
|
||||
sleep( 1 );
|
||||
}
|
||||
|
||||
/* Now all the wipe threads have finished, we can issue a terminate_signal = 1
|
||||
* which will cause the temperature update thread to terminate, this is necessary
|
||||
* because in gui mode the terminate_signal is set when the user presses a key to
|
||||
* exit on completion of all the wipes, however in non gui mode that code isn't
|
||||
* active (being in the gui section) so here we need to set the terminate signal
|
||||
* specifically for a completed wipes/s just for non gui mode.
|
||||
*/
|
||||
terminate_signal = 1;
|
||||
|
||||
/* Kill the temperature update thread */
|
||||
if( nwipe_temperature_thread )
|
||||
{
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Cancelling the temperature thread." );
|
||||
}
|
||||
|
||||
/* We don't want to use pthread_cancel as our temperature thread is aware of the control-c
|
||||
* signal and will exit itself we just join the temperature thread and wait for confirmation
|
||||
*/
|
||||
r = pthread_join( nwipe_temperature_thread, NULL );
|
||||
if( r != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"main()>pthread_join():Error when waiting for temperature thread to cancel." );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "temperature thread has been cancelled" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
@@ -936,11 +1084,12 @@ void* signal_hand( void* ptr )
|
||||
int cleanup()
|
||||
{
|
||||
int i;
|
||||
extern int log_elements_displayed;
|
||||
extern int log_elements_allocated;
|
||||
extern int log_elements_displayed; // initialised and found in logging.c
|
||||
extern int log_elements_allocated; // initialised and found in logging.c
|
||||
extern char** log_lines;
|
||||
extern config_t nwipe_cfg;
|
||||
|
||||
/* Print the logs held in memory. */
|
||||
/* Print the logs held in memory to the console */
|
||||
for( i = log_elements_displayed; i < log_elements_allocated; i++ )
|
||||
{
|
||||
printf( "%s\n", log_lines[i] );
|
||||
@@ -958,7 +1107,10 @@ int cleanup()
|
||||
free( log_lines );
|
||||
}
|
||||
|
||||
/* TODO: All other cleanup required */
|
||||
/* Deallocate libconfig resources */
|
||||
config_destroy( &nwipe_cfg );
|
||||
|
||||
/* TODO: Any other cleanup required ? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
18
src/nwipe.h
18
src/nwipe.h
@@ -36,15 +36,6 @@ void* signal_hand( void* );
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
/* workaround for Fedora */
|
||||
#ifndef off64_t
|
||||
#ifndef off_t
|
||||
#define off64_t int64_t
|
||||
#else
|
||||
#define off64_t off_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Busybox headers. */
|
||||
#ifdef BB_VER
|
||||
#include "busybox.h"
|
||||
@@ -68,6 +59,15 @@ void* signal_hand( void* );
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* workaround for Fedora */
|
||||
#ifndef off64_t
|
||||
#ifndef off_t
|
||||
#define off64_t int64_t
|
||||
#else
|
||||
#define off64_t off_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*#include "config.h"*/
|
||||
|
||||
/* System errors. */
|
||||
|
||||
113
src/options.c
113
src/options.c
@@ -27,6 +27,7 @@
|
||||
#include "options.h"
|
||||
#include "logging.h"
|
||||
#include "version.h"
|
||||
#include "conf.h"
|
||||
|
||||
/* The global options struct. */
|
||||
nwipe_options_t nwipe_options;
|
||||
@@ -54,7 +55,12 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
int i;
|
||||
|
||||
/* The list of acceptable short options. */
|
||||
char nwipe_options_short[] = "Vvhl:m:p:qr:e:";
|
||||
char nwipe_options_short[] = "Vvhl:P:m:p:qr:e:";
|
||||
|
||||
/* Used when reading value fron nwipe.conf */
|
||||
const char* read_value = NULL;
|
||||
|
||||
int ret;
|
||||
|
||||
/* The list of acceptable long options. */
|
||||
static struct option nwipe_options_long[] = {
|
||||
@@ -73,6 +79,9 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
/* Log file. Corresponds to the 'l' short option. */
|
||||
{ "logfile", required_argument, 0, 'l' },
|
||||
|
||||
/* PDFreport path. Corresponds to the 'P' short option. */
|
||||
{ "PDFreportpath", required_argument, 0, 'P' },
|
||||
|
||||
/* Exclude devices, comma separated list */
|
||||
{ "exclude", required_argument, 0, 'e' },
|
||||
|
||||
@@ -131,6 +140,76 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
nwipe_options.verbose = 0;
|
||||
nwipe_options.verify = NWIPE_VERIFY_LAST;
|
||||
memset( nwipe_options.logfile, '\0', sizeof( nwipe_options.logfile ) );
|
||||
memset( nwipe_options.PDFreportpath, '\0', sizeof( nwipe_options.PDFreportpath ) );
|
||||
strncpy( nwipe_options.PDFreportpath, ".", 2 );
|
||||
|
||||
/* Read PDF settings from nwipe.conf if available */
|
||||
if( ( ret = nwipe_conf_read_setting( "PDF_Certificate.PDF_Enable", &read_value ) ) )
|
||||
{
|
||||
/* error occurred */
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"nwipe_conf_read_setting():Error reading PDF_Certificate.PDF_Enable from nwipe.conf, ret code %i",
|
||||
ret );
|
||||
|
||||
/* Use default values */
|
||||
nwipe_options.PDF_enable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !strcmp( read_value, "ENABLED" ) )
|
||||
{
|
||||
nwipe_options.PDF_enable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !strcmp( read_value, "DISABLED" ) )
|
||||
{
|
||||
nwipe_options.PDF_enable = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// error occurred
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR,
|
||||
"PDF_Certificate.PDF_Enable in nwipe.conf returned a value that was neither ENABLED or DISABLED" );
|
||||
nwipe_options.PDF_enable = 1; // Default to Enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* PDF Preview enable/disable */
|
||||
if( ( ret = nwipe_conf_read_setting( "PDF_Certificate.PDF_Preview", &read_value ) ) )
|
||||
{
|
||||
/* error occurred */
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"nwipe_conf_read_setting():Error reading PDF_Certificate.PDF_Preview from nwipe.conf, ret code %i",
|
||||
ret );
|
||||
|
||||
/* Use default values */
|
||||
nwipe_options.PDF_enable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !strcmp( read_value, "ENABLED" ) )
|
||||
{
|
||||
nwipe_options.PDF_preview_details = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !strcmp( read_value, "DISABLED" ) )
|
||||
{
|
||||
nwipe_options.PDF_preview_details = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* error occurred */
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR,
|
||||
"PDF_Certificate.PDF_Preview in nwipe.conf returned a value that was neither ENABLED or DISABLED" );
|
||||
nwipe_options.PDF_preview_details = 1; /* Default to Enabled */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise each of the strings in the excluded drives array */
|
||||
for( i = 0; i < MAX_NUMBER_EXCLUDED_DRIVES; i++ )
|
||||
@@ -315,6 +394,29 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
strncpy( nwipe_options.logfile, optarg, sizeof( nwipe_options.logfile ) );
|
||||
break;
|
||||
|
||||
case 'P': /* PDFreport path option. */
|
||||
|
||||
nwipe_options.PDFreportpath[strlen( optarg )] = '\0';
|
||||
strncpy( nwipe_options.PDFreportpath, optarg, sizeof( nwipe_options.PDFreportpath ) );
|
||||
|
||||
/* Command line options will override what's in nwipe.conf */
|
||||
if( strcmp( nwipe_options.PDFreportpath, "noPDF" ) == 0 )
|
||||
{
|
||||
nwipe_options.PDF_enable = 0;
|
||||
nwipe_conf_update_setting( "PDF_Certificate.PDF_Enable", "DISABLED" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strcmp( nwipe_options.PDFreportpath, "." ) )
|
||||
{
|
||||
/* and if the user has specified a PDF path then enable PDF */
|
||||
nwipe_options.PDF_enable = 1;
|
||||
nwipe_conf_update_setting( "PDF_Certificate.PDF_Enable", "ENABLED" );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'e': /* exclude drives option */
|
||||
|
||||
idx_drive_chr = 0;
|
||||
@@ -354,6 +456,13 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
}
|
||||
}
|
||||
}
|
||||
if( idx_drive == MAX_NUMBER_EXCLUDED_DRIVES )
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"The number of excluded drives has reached the programs configured limit, aborting\n" );
|
||||
exit( 130 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -570,6 +679,8 @@ void display_help()
|
||||
puts( " verify_zero - Verifies disk is zero filled" );
|
||||
puts( " verify_one - Verifies disk is 0xFF filled\n" );
|
||||
puts( " -l, --logfile=FILE Filename to log to. Default is STDOUT\n" );
|
||||
puts( " -P, --PDFreportpath=PATH Path to write PDF reports to. Default is \".\"" );
|
||||
puts( " If set to \"noPDF\" no PDF reports are written.\n" );
|
||||
puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac|isaac64)\n" );
|
||||
puts( " -q, --quiet Anonymize logs and the GUI by removing unique data, i.e." );
|
||||
puts( " serial numbers, LU WWN Device ID, and SMBIOS/DMI data" );
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
#define NWIPE_KNOB_SCSI "/proc/scsi/scsi"
|
||||
#define NWIPE_KNOB_SLEEP 1
|
||||
#define NWIPE_KNOB_STAT "/proc/stat"
|
||||
#define MAX_NUMBER_EXCLUDED_DRIVES 10
|
||||
#define MAX_NUMBER_EXCLUDED_DRIVES 32
|
||||
#define MAX_DRIVE_PATH_LENGTH 200 // e.g. /dev/sda is only 8 characters long, so 200 should be plenty.
|
||||
#define DEFAULT_SYNC_RATE 100000
|
||||
#define PATHNAME_MAX 2048
|
||||
|
||||
/* Function prototypes for loading options from the environment and command line. */
|
||||
int nwipe_options_parse( int argc, char** argv );
|
||||
@@ -58,12 +59,15 @@ typedef struct
|
||||
char* banner; // The product banner shown on the top line of the screen.
|
||||
void* method; // A function pointer to the wipe method that will be used.
|
||||
char logfile[FILENAME_MAX]; // The filename to log the output to.
|
||||
char PDFreportpath[PATHNAME_MAX]; // The path to write the PDF report to.
|
||||
char exclude[MAX_NUMBER_EXCLUDED_DRIVES][MAX_DRIVE_PATH_LENGTH]; // Drives excluded from the search.
|
||||
nwipe_prng_t* prng; // The pseudo random number generator implementation.
|
||||
nwipe_prng_t* prng; // The pseudo random number generator implementation. pointer to the function.
|
||||
int quiet; // Anonymize serial numbers
|
||||
int rounds; // The number of times that the wipe method should be called.
|
||||
int sync; // A flag to indicate whether and how often writes should be sync'd.
|
||||
int verbose; // Make log more verbose
|
||||
int PDF_enable; // 0=PDF creation disabled, 1=PDF creation enabled
|
||||
int PDF_preview_details; // 0=Disable preview Org/Cust/date/time before drive selection, 1=Enable Preview
|
||||
nwipe_verify_t verify; // A flag to indicate whether writes should be verified.
|
||||
} nwipe_options_t;
|
||||
|
||||
|
||||
57
src/pass.c
57
src/pass.c
@@ -127,7 +127,6 @@ int nwipe_random_verify( nwipe_context_t* c )
|
||||
|
||||
if( r != 0 )
|
||||
{
|
||||
/* FIXME: Is there a better way to handle this? */
|
||||
nwipe_perror( errno, __FUNCTION__, "fdatasync" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name );
|
||||
c->fsyncdata_errors++;
|
||||
@@ -338,6 +337,10 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
if( idx == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_FATAL, "ERROR, prng wrote nothing to the buffer" );
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -350,6 +353,10 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "write" );
|
||||
nwipe_log( NWIPE_LOG_FATAL, "Unable to read from '%s'.", c->device_name );
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -374,6 +381,10 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
nwipe_perror( errno, __FUNCTION__, "lseek" );
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR, "Unable to bump the '%s' file offset after a partial write.", c->device_name );
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -409,6 +420,10 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Wrote %llu bytes on '%s'.", c->pass_done, c->device_name );
|
||||
c->fsyncdata_errors++;
|
||||
free( b );
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -418,7 +433,13 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
|
||||
pthread_testcancel();
|
||||
|
||||
} /* remaining bytes */
|
||||
/* If statement required so that it does not reset on subsequent passes */
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
|
||||
} /* /remaining bytes */
|
||||
|
||||
/* Release the output buffer. */
|
||||
free( b );
|
||||
@@ -434,10 +455,14 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
|
||||
if( r != 0 )
|
||||
{
|
||||
/* FIXME: Is there a better way to handle this? */
|
||||
nwipe_perror( errno, __FUNCTION__, "fdatasync" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name );
|
||||
c->fsyncdata_errors++;
|
||||
if( c->bytes_erased < ( c->device_size - z - blocksize ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z - blocksize;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We're done. */
|
||||
@@ -529,7 +554,6 @@ int nwipe_static_verify( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern )
|
||||
|
||||
if( r != 0 )
|
||||
{
|
||||
/* FIXME: Is there a better way to handle this? */
|
||||
nwipe_perror( errno, __FUNCTION__, "fdatasync" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name );
|
||||
c->fsyncdata_errors++;
|
||||
@@ -761,6 +785,10 @@ int nwipe_static_pass( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "write" );
|
||||
nwipe_log( NWIPE_LOG_FATAL, "Unable to write to '%s'.", c->device_name );
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -785,6 +813,10 @@ int nwipe_static_pass( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern )
|
||||
nwipe_perror( errno, __FUNCTION__, "lseek" );
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR, "Unable to bump the '%s' file offset after a partial write.", c->device_name );
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -829,6 +861,10 @@ int nwipe_static_pass( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern )
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Wrote %llu bytes on '%s'.", c->pass_done, c->device_name );
|
||||
c->fsyncdata_errors++;
|
||||
free( b );
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -838,7 +874,12 @@ int nwipe_static_pass( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern )
|
||||
|
||||
pthread_testcancel();
|
||||
|
||||
} /* remaining bytes */
|
||||
if( c->bytes_erased < ( c->device_size - z ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z;
|
||||
}
|
||||
|
||||
} /* /remaining bytes */
|
||||
|
||||
/* Tell our parent that we are syncing the device. */
|
||||
c->sync_status = 1;
|
||||
@@ -851,10 +892,14 @@ int nwipe_static_pass( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern )
|
||||
|
||||
if( r != 0 )
|
||||
{
|
||||
/* FIXME: Is there a better way to handle this? */
|
||||
nwipe_perror( errno, __FUNCTION__, "fdatasync" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name );
|
||||
c->fsyncdata_errors++;
|
||||
if( c->bytes_erased < ( c->device_size - z - blocksize ) ) // How much of the device has been erased?
|
||||
{
|
||||
c->bytes_erased = c->device_size - z - blocksize;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Release the output buffer. */
|
||||
|
||||
@@ -36,7 +36,7 @@ static inline void u32_to_buffer( u8* restrict buffer, u32 val, const int len )
|
||||
{
|
||||
for( int i = 0; i < len; ++i )
|
||||
{
|
||||
buffer[i] = ( u8 )( val & 0xFFUL );
|
||||
buffer[i] = (u8) ( val & 0xFFUL );
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ static inline void u64_to_buffer( u8* restrict buffer, u64 val, const int len )
|
||||
{
|
||||
for( int i = 0; i < len; ++i )
|
||||
{
|
||||
buffer[i] = ( u8 )( val & 0xFFULL );
|
||||
buffer[i] = (u8) ( val & 0xFFULL );
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/redcross.jpg
Normal file
BIN
src/redcross.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
BIN
src/te.jpg
Normal file
BIN
src/te.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
@@ -26,6 +26,7 @@
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
@@ -36,14 +37,13 @@
|
||||
#include "device.h"
|
||||
#include "logging.h"
|
||||
#include "temperature.h"
|
||||
#include "miscellaneous.h"
|
||||
|
||||
extern int terminate_signal;
|
||||
|
||||
int nwipe_init_temperature( nwipe_context_t* c )
|
||||
{
|
||||
/* This function is called after each nwipe_context_t has been created.
|
||||
* It initialises the temperature variables in each context and then
|
||||
* constructs a path that is placed in the context that points to the
|
||||
* appropriate /sys/class/hwmon/hwmonX directory that corresponds with
|
||||
* the particular drive represented in the context structure.
|
||||
/* See header definition for description of function
|
||||
*/
|
||||
DIR* dir;
|
||||
DIR* dir2;
|
||||
@@ -57,21 +57,23 @@ int nwipe_init_temperature( nwipe_context_t* c )
|
||||
struct dirent* dp;
|
||||
struct dirent* dp2;
|
||||
|
||||
/* Why Initialise with 1000000? Because the GUI needs to know whether data
|
||||
* has been obtained so it can display appropriate information when a
|
||||
/* Why Initialise with 1000000 (defined as NO_TEMPERATURE_DATA)?
|
||||
* Because the GUI needs to know whether data has been obtained
|
||||
* so it can display appropriate information when a
|
||||
* device is unable to provide temperature data */
|
||||
|
||||
c->temp1_crit = 1000000;
|
||||
c->temp1_highest = 1000000;
|
||||
c->temp1_input = 1000000;
|
||||
c->temp1_lcrit = 1000000;
|
||||
c->temp1_lowest = 1000000;
|
||||
c->temp1_max = 1000000;
|
||||
c->temp1_min = 1000000;
|
||||
c->temp1_monitored_wipe_max = 1000000;
|
||||
c->temp1_monitored_wipe_min = 1000000;
|
||||
c->temp1_monitored_wipe_avg = 1000000;
|
||||
c->temp1_flash_rate = 2;
|
||||
c->templ_has_hwmon_data = 0;
|
||||
c->temp1_crit = NO_TEMPERATURE_DATA;
|
||||
c->temp1_highest = NO_TEMPERATURE_DATA;
|
||||
c->temp1_input = NO_TEMPERATURE_DATA;
|
||||
c->temp1_lcrit = NO_TEMPERATURE_DATA;
|
||||
c->temp1_lowest = NO_TEMPERATURE_DATA;
|
||||
c->temp1_max = NO_TEMPERATURE_DATA;
|
||||
c->temp1_min = NO_TEMPERATURE_DATA;
|
||||
c->temp1_monitored_wipe_max = NO_TEMPERATURE_DATA;
|
||||
c->temp1_monitored_wipe_min = NO_TEMPERATURE_DATA;
|
||||
c->temp1_monitored_wipe_avg = NO_TEMPERATURE_DATA;
|
||||
c->temp1_flash_rate = 0;
|
||||
c->temp1_flash_rate_counter = 0;
|
||||
c->temp1_path[0] = 0;
|
||||
c->temp1_time = 0;
|
||||
@@ -189,6 +191,7 @@ int nwipe_init_temperature( nwipe_context_t* c )
|
||||
}
|
||||
/* Copy the hwmon path to the drive context structure */
|
||||
strcpy( c->temp1_path, dirpath_hwmonX );
|
||||
c->templ_has_hwmon_data = 1;
|
||||
}
|
||||
}
|
||||
closedir( dir2 );
|
||||
@@ -197,13 +200,88 @@ int nwipe_init_temperature( nwipe_context_t* c )
|
||||
}
|
||||
closedir( dir );
|
||||
}
|
||||
/* if no hwmon data available try scsi access (SAS Disks are known to be not working in hwmon */
|
||||
if( c->templ_has_hwmon_data == 0 && ( c->device_type == NWIPE_DEVICE_SAS || c->device_type == NWIPE_DEVICE_SCSI ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "no hwmon data for %s, try to get SCSI data", c->device_name );
|
||||
if( nwipe_init_scsi_temperature( c ) == 0 )
|
||||
{
|
||||
c->templ_has_scsitemp_data = 1;
|
||||
nwipe_log( NWIPE_LOG_INFO, "got SCSI temperature data for %s", c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
c->templ_has_scsitemp_data = 0;
|
||||
nwipe_log( NWIPE_LOG_INFO, "got no SCSI temperature data for %s", c->device_name );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float timedifference_msec( struct timeval tv_start, struct timeval tv_end )
|
||||
{
|
||||
/* helper function for time measurement in msec */
|
||||
return ( tv_end.tv_sec - tv_start.tv_sec ) * 1000.0f + ( tv_end.tv_usec - tv_start.tv_usec ) / 1000.0f;
|
||||
}
|
||||
|
||||
void* nwipe_update_temperature_thread( void* ptr )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Set up the structs we will use for the data required. */
|
||||
nwipe_thread_data_ptr_t* nwipe_thread_data_ptr;
|
||||
nwipe_context_t** c;
|
||||
nwipe_misc_thread_data_t* nwipe_misc_thread_data;
|
||||
|
||||
/* Retrieve from the pointer passed to the function. */
|
||||
nwipe_thread_data_ptr = (nwipe_thread_data_ptr_t*) ptr;
|
||||
c = nwipe_thread_data_ptr->c;
|
||||
nwipe_misc_thread_data = nwipe_thread_data_ptr->nwipe_misc_thread_data;
|
||||
|
||||
/* mark start second of update */
|
||||
time_t nwipe_timemark = time( NULL );
|
||||
|
||||
/* update immediately on entry to thread */
|
||||
for( i = 0; i < nwipe_misc_thread_data->nwipe_enumerated; i++ )
|
||||
{
|
||||
nwipe_update_temperature( c[i] );
|
||||
if( terminate_signal == 1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while( terminate_signal != 1 )
|
||||
{
|
||||
/* Update all drive/s but never repeat checking the
|
||||
* set of drive/s faster than once every 2 seconds */
|
||||
if( time( NULL ) > ( nwipe_timemark + 1 ) )
|
||||
{
|
||||
nwipe_timemark = time( NULL );
|
||||
|
||||
for( i = 0; i < nwipe_misc_thread_data->nwipe_enumerated; i++ )
|
||||
{
|
||||
nwipe_update_temperature( c[i] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sleep( 1 );
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nwipe_update_temperature( nwipe_context_t* c )
|
||||
{
|
||||
/* For the given drive context obtain the path to it's hwmon temperature settings
|
||||
/* Warning !! This function should only be called by nwipe_update_temperature_thread()
|
||||
* Due to delays of upto 2 seconds with some drives, especially SAS in obtaining
|
||||
* temperatures while wiping, the delays being worse the more drives you are wiping. Updating
|
||||
* temperatures are performed within it's own thread so it doesn't cause momentary freezes
|
||||
* in the GUI interface.
|
||||
*
|
||||
* For the given drive context obtain the path to it's hwmon temperature settings
|
||||
* and read then write the temperature values back to the context. A numeric ascii to integer conversion is
|
||||
* performed. The temperaures should be updated no more frequently than every 60 seconds
|
||||
*/
|
||||
@@ -225,38 +303,79 @@ void nwipe_update_temperature( nwipe_context_t* c )
|
||||
FILE* fptr;
|
||||
int idx;
|
||||
int result;
|
||||
struct timeval tv_start;
|
||||
struct timeval tv_end;
|
||||
float delta_t;
|
||||
|
||||
for( idx = 0; idx < NUMBER_OF_FILES; idx++ )
|
||||
/* avoid being called more often than 1x per 60 seconds */
|
||||
time_t nwipe_time_now = time( NULL );
|
||||
if( nwipe_time_now - c->temp1_time < 60 )
|
||||
{
|
||||
/* Construct the full path including filename */
|
||||
strcpy( path, c->temp1_path );
|
||||
strcat( path, "/" );
|
||||
strcat( path, &( temperature_label[idx][0] ) );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Open the file */
|
||||
if( ( fptr = fopen( path, "r" ) ) != NULL )
|
||||
/* measure time it takes to get the temperatures */
|
||||
gettimeofday( &tv_start, 0 );
|
||||
|
||||
/* try to get temperatures from hwmon, standard */
|
||||
if( c->templ_has_hwmon_data == 1 )
|
||||
{
|
||||
for( idx = 0; idx < NUMBER_OF_FILES; idx++ )
|
||||
{
|
||||
/* Acquire data until we reach a newline */
|
||||
result = fscanf( fptr, "%[^\n]", temperature );
|
||||
/* Construct the full path including filename */
|
||||
strcpy( path, c->temp1_path );
|
||||
strcat( path, "/" );
|
||||
strcat( path, &( temperature_label[idx][0] ) );
|
||||
|
||||
/* Convert numeric ascii to binary integer */
|
||||
*( temperature_pcontext[idx] ) = atoi( temperature );
|
||||
|
||||
/* Divide by 1000 to get degrees celcius */
|
||||
*( temperature_pcontext[idx] ) = *( temperature_pcontext[idx] ) / 1000;
|
||||
|
||||
if( nwipe_options.verbose )
|
||||
/* Open the file */
|
||||
if( ( fptr = fopen( path, "r" ) ) != NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: %s %dC", path, *( temperature_pcontext[idx] ) );
|
||||
/* Acquire data until we reach a newline */
|
||||
result = fscanf( fptr, "%[^\n]", temperature );
|
||||
|
||||
/* Convert numeric ascii to binary integer */
|
||||
*( temperature_pcontext[idx] ) = atoi( temperature );
|
||||
|
||||
/* Divide by 1000 to get degrees celsius */
|
||||
*( temperature_pcontext[idx] ) = *( temperature_pcontext[idx] ) / 1000;
|
||||
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: %s %dC", path, *( temperature_pcontext[idx] ) );
|
||||
}
|
||||
|
||||
fclose( fptr );
|
||||
}
|
||||
|
||||
fclose( fptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.verbose )
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Unable to open %s", path );
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Unable to open %s", path );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* alternative method to get temperature from SCSI/SAS disks */
|
||||
if( c->device_type == NWIPE_DEVICE_SAS || c->device_type == NWIPE_DEVICE_SCSI )
|
||||
{
|
||||
if( c->templ_has_scsitemp_data == 1 )
|
||||
{
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_crit %dC", c->device_name, c->temp1_crit );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_highest %dC", c->device_name, c->temp1_highest );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_input %dC", c->device_name, c->temp1_input );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_lcrit %dC", c->device_name, c->temp1_lcrit );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_lowest %dC", c->device_name, c->temp1_lowest );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_max %dC", c->device_name, c->temp1_max );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_min %dC", c->device_name, c->temp1_min );
|
||||
}
|
||||
if( nwipe_get_scsi_temperature( c ) != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "get_scsi_temperature error" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,5 +385,111 @@ void nwipe_update_temperature( nwipe_context_t* c )
|
||||
* every 60 seconds */
|
||||
c->temp1_time = time( NULL );
|
||||
|
||||
gettimeofday( &tv_end, 0 );
|
||||
delta_t = timedifference_msec( tv_start, tv_end );
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "get temperature for %s took %f ms", c->device_name, delta_t );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void nwipe_log_drives_temperature_limits( nwipe_context_t* c )
|
||||
{
|
||||
/* See header for description of function
|
||||
*/
|
||||
|
||||
char temperature_limits_txt[500];
|
||||
|
||||
int idx = 0;
|
||||
|
||||
/*
|
||||
* Initialise the character string, as we are building it a few
|
||||
* characters at a time and it's important there it is populated
|
||||
* with all zeros as we are using strlen() as we build the line up.
|
||||
*/
|
||||
memset( &temperature_limits_txt, 0, sizeof( temperature_limits_txt ) );
|
||||
|
||||
if( c->temp1_crit != NO_TEMPERATURE_DATA )
|
||||
{
|
||||
snprintf( temperature_limits_txt,
|
||||
sizeof( temperature_limits_txt ),
|
||||
"Temperature limits for %s, critical=%ic, ",
|
||||
c->device_name,
|
||||
c->temp1_crit );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( temperature_limits_txt,
|
||||
sizeof( temperature_limits_txt ),
|
||||
"Temperature limits for %s, critical=N/A, ",
|
||||
c->device_name );
|
||||
}
|
||||
|
||||
idx = strlen( temperature_limits_txt );
|
||||
|
||||
if( c->temp1_max != NO_TEMPERATURE_DATA )
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx], ( sizeof( temperature_limits_txt ) - idx ), "max=%ic, ", c->temp1_max );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx], ( sizeof( temperature_limits_txt ) - idx ), "max=N/A, " );
|
||||
}
|
||||
|
||||
idx = strlen( temperature_limits_txt );
|
||||
|
||||
if( c->temp1_highest != NO_TEMPERATURE_DATA )
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx],
|
||||
( sizeof( temperature_limits_txt ) - idx ),
|
||||
"highest=%ic, ",
|
||||
c->temp1_highest );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx], ( sizeof( temperature_limits_txt ) - idx ), "highest=N/A, " );
|
||||
}
|
||||
|
||||
idx = strlen( temperature_limits_txt );
|
||||
|
||||
if( c->temp1_lowest != NO_TEMPERATURE_DATA )
|
||||
{
|
||||
snprintf(
|
||||
&temperature_limits_txt[idx], ( sizeof( temperature_limits_txt ) - idx ), "lowest=%ic, ", c->temp1_lowest );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx], ( sizeof( temperature_limits_txt ) - idx ), "lowest=N/A, " );
|
||||
}
|
||||
|
||||
idx = strlen( temperature_limits_txt );
|
||||
|
||||
if( c->temp1_min != NO_TEMPERATURE_DATA )
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx], ( sizeof( temperature_limits_txt ) - idx ), "min=%ic, ", c->temp1_min );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx], ( sizeof( temperature_limits_txt ) - idx ), "min=N/A, " );
|
||||
}
|
||||
|
||||
idx = strlen( temperature_limits_txt );
|
||||
|
||||
if( c->temp1_lcrit != NO_TEMPERATURE_DATA )
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx],
|
||||
( sizeof( temperature_limits_txt ) - idx ),
|
||||
"low critical=%ic.",
|
||||
c->temp1_lcrit );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( &temperature_limits_txt[idx], ( sizeof( temperature_limits_txt ) - idx ), "low critical=N/A. " );
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s", temperature_limits_txt );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*.
|
||||
/*
|
||||
* temperature.h: The header file for disk drive temperature sensing
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -22,9 +22,40 @@
|
||||
#include <sys/types.h>
|
||||
#include "context.h"
|
||||
|
||||
/**
|
||||
* This function is called after each nwipe_context_t has been created.
|
||||
* It initialises the temperature variables in each context and then
|
||||
* constructs a path that is placed in the context that points to the
|
||||
* appropriate /sys/class/hwmon/hwmonX directory that corresponds with
|
||||
* the particular drive represented in the context structure.
|
||||
* @param pointer to a drive context
|
||||
* @return returns 0 on success < 1 on error
|
||||
*/
|
||||
int nwipe_init_temperature( nwipe_context_t* );
|
||||
|
||||
void nwipe_update_temperature( nwipe_context_t* );
|
||||
|
||||
/**
|
||||
* Workaround for obtaining temperatures from SCSI/SAS drives
|
||||
* @param pointer to a drive context
|
||||
* @return returns 0 on success < 1 on error
|
||||
*/
|
||||
int nwipe_init_scsi_temperature( nwipe_context_t* );
|
||||
int nwipe_get_scsi_temperature( nwipe_context_t* );
|
||||
void nwipe_shut_scsi_temperature( nwipe_context_t* );
|
||||
void* nwipe_update_temperature_thread( void* ptr );
|
||||
|
||||
/**
|
||||
* This function is normally called only once. It's called after both the
|
||||
* nwipe_init_temperature() function and nwipe_update_temperature()
|
||||
* functions have been called. It logs the drives critical, highest, lowest
|
||||
* and lowest critical temperatures. Not all drives report four temperatures.
|
||||
* @param pointer to a drive context
|
||||
*/
|
||||
void nwipe_log_drives_temperature_limits( nwipe_context_t* );
|
||||
|
||||
#define NUMBER_OF_FILES 7
|
||||
|
||||
#define NO_TEMPERATURE_DATA 1000000
|
||||
|
||||
#endif /* TEMPERATURE_H_ */
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
* used by configure to dynamically assign those values
|
||||
* to documentation files.
|
||||
*/
|
||||
const char* version_string = "0.33";
|
||||
const char* version_string = "0.36";
|
||||
const char* program_name = "nwipe";
|
||||
const char* author_name = "Martijn van Brummelen";
|
||||
const char* email_address = "git@brumit.nl";
|
||||
const char* years = "2022";
|
||||
const char* years = "2024";
|
||||
const char* copyright = "Copyright Darik Horn <dajhorn-dban@vanadac.com>\n\
|
||||
Modifications to original dwipe Copyright Andy Beverley <andy@andybev.com>\n\
|
||||
This is free software; see the source for copying conditions.\n\
|
||||
There is NO warranty; not even for MERCHANTABILITY or FITNESS\n\
|
||||
FOR A PARTICULAR PURPOSE.\n";
|
||||
const char* banner = "nwipe 0.33";
|
||||
const char* banner = "nwipe 0.36";
|
||||
|
||||
Reference in New Issue
Block a user