FAT16 copy/export command line tool implementation - c++

I'm working on a command line tool that allows you to copy and export data from a loaded FAT16 file system to your own native file system. For instance, right now, my program works like this:
./a.out Adisk16.raw FOO.TXT
FAT start at 00001000, root dir at 0003E000, data at 00042000
File found!
Copied 342 bytes
And I want it to work like this:
./a.out Adisk16.raw
:/> cpout FOO.TXT
FAT start at 00001000, root dir at 0003E000, data at 00042000
File found!
Copied 342 bytes
:/>
My code is below. Can anyone help me with this?
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>
typedef struct {
unsigned char first_byte;
unsigned char start_chs[3];
unsigned char partition_type;
unsigned char end_chs[3];
unsigned long start_sector;
unsigned long length_sectors;
} __attribute((packed)) PartitionTable;
typedef struct {
unsigned char jmp[3];
char oem[8];
unsigned short sector_size;
unsigned char sectors_per_cluster;
unsigned short reserved_sectors;
unsigned char number_of_fats;
unsigned short root_dir_entries;
unsigned short total_sectors_short; // if zero, later field is used
unsigned char media_descriptor;
unsigned short fat_size_sectors;
unsigned short sectors_per_track;
unsigned short number_of_heads;
unsigned long hidden_sectors;
unsigned long total_sectors_long;
unsigned char drive_number;
unsigned char current_head;
unsigned char boot_signature;
unsigned long volume_id;
char volume_label[11];
char fs_type[8];
char boot_code[448];
unsigned short boot_sector_signature;
} __attribute((packed)) Fat16BootSector;
typedef struct {
unsigned char filename[8];
unsigned char ext[3];
unsigned char attributes;
unsigned char reserved[10];
unsigned short modify_time;
unsigned short modify_date;
unsigned short starting_cluster;
unsigned long file_size;
} __attribute((packed)) Fat16Entry;
void fat_read_file(FILE * in, FILE * out,
unsigned long fat_start,
unsigned long data_start,
unsigned long cluster_size,
unsigned short cluster,
unsigned long file_size) {
unsigned char buffer[4096];
size_t bytes_read, bytes_to_read,
file_left = file_size, cluster_left = cluster_size;
// Go to first data cluster
fseek(in, data_start + cluster_size * (cluster-2), SEEK_SET);
// Read until we run out of file or clusters
while(file_left > 0 && cluster != 0xFFFF) {
bytes_to_read = sizeof(buffer);
// don't read past the file or cluster end
if(bytes_to_read > file_left)
bytes_to_read = file_left;
if(bytes_to_read > cluster_left)
bytes_to_read = cluster_left;
// read data from cluster, write to file
bytes_read = fread(buffer, 1, bytes_to_read, in);
fwrite(buffer, 1, bytes_read, out);
printf("Copied %d bytes\n", bytes_read);
// decrease byte counters for current cluster and whole file
cluster_left -= bytes_read;
file_left -= bytes_read;
// if we have read the whole cluster, read next cluster # from FAT
if(cluster_left == 0) {
fseek(in, fat_start + cluster*2, SEEK_SET);
fread(&cluster, 2, 1, in);
printf("End of cluster reached, next cluster %d\n", cluster);
fseek(in, data_start + cluster_size * (cluster-2), SEEK_SET);
cluster_left = cluster_size; // reset cluster byte counter
}
}
}
void parse(char *line, char **argv)
{
while (*line != '\0') {//until the end of the line...
while (*line == ' ' || *line == '\t' || *line == '\n')//...while the character in memory is any of these...
*line++ = '\0'; //...replace it with a 0.
*argv++ = line;//change the given argument to the changed line.
while (*line != '\0' && *line != '\t' && *line != '\n' && *line != ' ')//while the line is not at one of these symbols...
line++;//...skip the argument
}
*argv = '\0'; //mark the end of the argument list
printf("%s\n", line);
}
int main(int args, char *argv[]) {
FILE *in, *out;
in = fopen(argv[1], "rb");
int i, j;
unsigned long fat_start, root_start, data_start;
PartitionTable pt[4];
Fat16BootSector bs;
Fat16Entry entry;
char filename[9] = " ", file_ext[4] = " "; // initially pad with spaces
if(args < 3) {
printf("Usage: read_file <fs_image> <FILE.EXT>\n");
return 0;
}
if((in = fopen(argv[1], "rb")) == NULL) {
printf("Filesystem image file %s not found!\n", argv[1]);
return -1;
}
// Copy filename and extension to space-padded search strings
for(i=0; i<8 && argv[2][i] != '.' && argv[2][i] != 0; i++)
filename[i] = argv[2][i];
for(j=1; j<=3 && argv[2][i+j] != 0; j++)
file_ext[j-1] = argv[2][i+j];
printf("Opened %s, looking for [%s.%s]\n", argv[1], filename, file_ext);
fseek(in, 0x000, SEEK_SET);
fread(&bs, sizeof(Fat16BootSector), 1, in);
// Calculate start offsets of FAT, root directory and data
fat_start = ftell(in) + (bs.reserved_sectors-1) * bs.sector_size;
root_start = fat_start + bs.fat_size_sectors * bs.number_of_fats *
bs.sector_size;
data_start = root_start + bs.root_dir_entries * sizeof(Fat16Entry);
printf("FAT start at %08X, root dir at %08X, data at %08X\n",
fat_start, root_start, data_start);
fseek(in, root_start, SEEK_SET);
for(i=0; i<bs.root_dir_entries; i++) {
fread(&entry, sizeof(entry), 1, in);
if(memcmp(entry.filename, filename, 8) == 0 &&
memcmp(entry.ext, file_ext, 3) == 0) {
printf("File found!\n");
break;
}
}
if(i == bs.root_dir_entries) {
printf("File not found!");
return -1;
}
out = fopen(argv[2], "wb"); // write the file contents to disk
fat_read_file(in, out, fat_start, data_start, bs.sectors_per_cluster * bs.sector_size, entry.starting_cluster, entry.file_size);
fclose(out);
fclose(in);
return 0;
}
Edit: Also, if someone could point me to a tutorial on how to write files into the fat, that would be awesome.

Related

u-law compression returns invalid file c++

I'm trying to apply the u-law algorithm to a wav file file.wav, and then create a new file file2.wav.
file.wav has 16 bits/sample, and I want to obtain a file2.wav that has 8 bits/sample.
This is my code:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
using std::string;
using std::fstream;
typedef struct WAV_HEADER {
char RIFF[4];
unsigned long ChunkSize;
char WAVE[4];
char fmt[4];
unsigned long Subchunk1Size;
unsigned short AudioFormat;
unsigned short NumOfChan;
unsigned long SamplesPerSec;
unsigned long bytesPerSec;
unsigned short blockAlign;
unsigned short bitsPerSample;
char Subchunk2ID[4];
unsigned long Subchunk2Size;
} wav_hdr;
int headerSize = 0;
string path = "file.wav";
wav_hdr wavHeader;
FILE* openFile() {
const char* filePath;
FILE *wavFile;
headerSize = sizeof(wav_hdr);
filePath = path.c_str();
wavFile = fopen(filePath, "rb");
if (wavFile == NULL) {
printf("Error\n");
}
fread(&wavHeader, headerSize, 1, wavFile);
return wavFile;
}
int8_t MuLaw_Encode(int16_t number)
{
const uint16_t MULAW_MAX = 0x1FFF;
const uint16_t MULAW_BIAS = 33;
uint16_t mask = 0x1000;
uint8_t sign = 0;
uint8_t position = 12;
uint8_t lsb = 0;
if (number < 0)
{
number = -number;
sign = 0x80;
}
number += MULAW_BIAS;
if (number > MULAW_MAX)
{
number = MULAW_MAX;
}
for (; ((number & mask) != mask && position >= 5); mask >>= 1, position--)
;
lsb = (number >> (position - 4)) & 0x0f;
return (~(sign | ((position - 5) << 4) | lsb));
}
int fileSize(FILE *file) {
int fileSize = 0;
fseek(file, 0, SEEK_END);
fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
return fileSize;
}
double bitsPerSample() {
double bitsPerE;
bitsPerE = wavHeader.bitsPerSample;
return bitsPerE;
}
int main() {
FILE *wavFile;
wavFile = openFile();
FILE* fptr2;
fptr2 = fopen("file2.wav", "wb");
int samples_count = fileSize(wavFile) / bitsPerSample();
short int *value = new short int[samples_count];
for (int16_t i = 0; i < samples_count; i++)
{
fread(&value[i], samples_count, 1, wavFile);
cout << value[i] << " "; // the output is in the attached picture
MuLaw_Encode(value[i]);
}
fwrite(value, sizeof(char), samples_count, fptr2);
return 0;
}
I took the u-law algorithm from here (2.1. µ-Law Compression (Encoding) Algorithm)
Am I doing something wrong? Because I obtain a corrupt file.
No header is ever written to the result file, so the first part of the data would get interpreted as a header, and it would be wrong. You can see in the file that it does not start with RIFFþR�WAVEfmt or something sufficiently similar.
The data written to the result file is value, the original data read from the input file, not the µ-law encoded data (which is only cout'ed and not saved).
The loop that reads the samples reads some wrong samples, because the computation of samples_count puts the current position back at the start, where the header is.

I want, How to read dlt binary File without dlt viwer, using c++ fstream

I want to make simple console program.
the program is dead checking program
Sometimes the point of death on the log is different from where it actually happened.
The format of the dlt file is as follows.
I want to parse the following binary files through c ++.
I tried many times to read the binary file but it failed.
I would appreciate it if you could upload a simple example source.\
Thank you
#include <stdio.h>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <io.h>
#include <vector>
#include <string>
#include <conio.h>
using namespace std;
struct dltLogFormat
{
char dltPattern[100];
unsigned int TimeStamp_sec;
int TimeStamp_mic;
char ECU_ID[4];
};
void main()
{
FILE *fp;
vector<string> dltList;
char dltPattern[5] = "";
unsigned int TimeStamp_sec = 0;
int TimeStamp_mic = 0;
char ECU_ID_CHARACTER[5] = "";
char infoHeader;
unsigned short messageLength;
int ECU_ID = 0;
unsigned int sessionID = 0;
int extHeaderInfo = 0;
unsigned int numberOfArguments = 0;
unsigned int applicationID = 0;
unsigned int ContextID = 0;
char payload[17];
_finddata_t fd;
long handle;
int result = 1;
handle = _findfirst(".\\*.dlt", &fd);
if (handle == -1)
{
printf("There were no dlt files.\n");
return;
}
while (result != -1)
{
dltLogFormat dltFormant;
dltList.push_back(fd.name);
printf("File: %s\n", fd.name);
result = _findnext(handle, &fd);
std::ifstream input(fd.name, std::ios::binary | std::ios::in);
while (true)
{
input >> dltPattern;
input.read((char*)&TimeStamp_sec, sizeof(unsigned int));
input.read((char*)&TimeStamp_mic, sizeof(int));
input >> ECU_ID_CHARACTER;
input.read((char*)&infoHeader, sizeof(char));
input.read((char*)&messageLength, sizeof(unsigned short));
input.read((char*)&ECU_ID, sizeof(int));
input.read((char*)&sessionID, sizeof(unsigned int));
input.read((char*)&extHeaderInfo, sizeof(unsigned int));
input.read((char*)&numberOfArguments, sizeof(unsigned int));
input.read((char*)&applicationID, sizeof(unsigned int));
input.read((char*)&ContextID, sizeof(unsigned int));
input.read(payload, sizeof(char)*messageLength);
//header
//input
//extend header
//payload
}
}
}

direct access to HDD

I want to print out boot sector using code below, but there is mistake.
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
using namespace std;
short ReadSect
(const char * _dsk, // disk to access
char *&_buff, // buffer where sector will be stored
unsigned int _nsect // sector number, starting with 0
)
{
DWORD dwRead;
HANDLE
hDisk=CreateFile(_dsk,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
if(hDisk==INVALID_HANDLE_VALUE) // this may happen if another program is
already reading from disk
{
CloseHandle(hDisk);
return 1;
}
SetFilePointer(hDisk,_nsect*512,0,FILE_BEGIN); // which sector to read
ReadFile(hDisk,_buff,512,&dwRead,0); // read sector
CloseHandle(hDisk);
return 0;
}
int main()
{
char * drv="\\\\.\\C:";
char *dsk=" \\\\.\\PhysicalDrive0";
int sector=0;
int b = 1;
char *buff=new char[512];
ReadSect(dsk,buff,sector);
if((unsigned char)buff[510]==0x55 && (unsigned char)buff[511]==0xaa) cout
<<"Disk is bootable!"<<endl;
else printf("%02hhX\n",(unsigned int)(unsigned char)buff[511]);
printf("\n");
while (b<513)
{
if (b%16==0)
printf(" %02hhX\n",(unsigned int)(unsigned char)buff[b-1]);
else
printf (" %02hhX ",(unsigned int)(unsigned char)buff[b-1]);
b++;
}
getchar();
}
Instead of printing hexadecimal digits of boot sectors, microsoft visual studio prints out stream of "CDs". What is the mistake and how to fix the problem? Can anyone help?
Photo of output
First of all, start it as Administrator
remove space from
char *dsk=" \\\\.\\PhysicalDrive0";
must be
char *dsk="\\\\.\\PhysicalDrive0";
And, if you use char *dsk, make modification in:
hDisk=CreateFile(_dsk,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
must be:
CreateFileA (......)
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
using namespace std;
short ReadSect
(const char * _dsk, // disk to access
char *&_buff, // buffer where sector will be stored
unsigned int _nsect // sector number, starting with 0
)
{
DWORD dwRead;
HANDLE
hDisk = CreateFileA( _dsk, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
//CreateFile()
if (hDisk == INVALID_HANDLE_VALUE) // this may happen if another program is already reading from disk
{
CloseHandle(hDisk);
return 1;
}
SetFilePointer(hDisk, _nsect * 512, 0, FILE_BEGIN); // which sector to read
ReadFile(hDisk, _buff, 512, &dwRead, 0); // read sector
CloseHandle(hDisk);
return 0;
}
int main()
{
char * drv = "\\\\.\\C:";
char *dsk = "\\\\.\\PhysicalDrive0";
int sector = 0;
int b = 1;
char *buff = new char[512];
ReadSect(dsk, buff, sector);
if ((unsigned char)buff[510] == 0x55 && (unsigned char)buff[511] == 0xaa) cout
<< "Disk is bootable!" << endl;
else printf("%02hhX\n", (unsigned int)(unsigned char)buff[511]);
printf("\n");
while (b<513)
{
if (b % 16 == 0)
printf(" %02hhX\n", (unsigned int)(unsigned char)buff[b - 1]);
else
printf(" %02hhX ", (unsigned int)(unsigned char)buff[b - 1]);
b++;
}
getchar();
}
WinAPI Unicode and ANSI functions

GDB in a programming in C

I have a problem with a program in C. I need the absolute memory address of the local variables to the function main. I am debugging with the gdb.
How to know if there is an overflow in the variables.
Thank you
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
typedef int16_t int16;
#include "mulaw.h"
void decodeFile(FILE * fIn, FILE * fOut, uint32_t samples) {
uint32_t i;
uint8_t * inSamples = malloc(samples * sizeof(uint8_t));
int16_t * outSamples = malloc(samples * sizeof(int16_t));
fread(inSamples, sizeof(uint8_t), samples, fIn);
for (i = 0; i < samples; i++) {
outSamples[i] = 4 * muLaw[inSamples[i]];
}
fwrite(outSamples, sizeof(int16_t), samples, fOut);
free(inSamples);
free(outSamples);
}
#define MAX_FILE_SIZE 256
int main(int argc, char **argv)
{
char inputFile[MAX_FILE_SIZE];
char outputFile[MAX_FILE_SIZE];
FILE * fIn = NULL, * fOut = NULL;
struct header_t {
char ChunkID[4];
int32_t ChunkSize;
char Format[4];
} header;
char SubchunkID[4];
uint32_t SubchunkSize;
struct subheader_t {
int16_t AudioFormat;
int16_t NumChannels;
int32_t SampleRate;
int32_t ByteRate;
int16_t BlockAlign;
int16_t BitsPerSample;
int16_t ExtraParamSize;
int16_t Padding;
} subheader;
/* Usage */
if (argc != 3) {
puts("Usage is: mulaw INFILE OUTFILE\n");
exit(EXIT_FAILURE);
}
/* Careful here!!!!! */
strncpy(inputFile, argv[1], MAX_FILE_SIZE);
strncpy(outputFile, argv[2], MAX_FILE_SIZE);
/* Open input file */
fIn = fopen (inputFile, "rb");
/* Read main header */
fread(&header, sizeof(struct header_t), 1, fIn);
if (memcmp(header.ChunkID, "RIFF", 4) != 0
|| memcmp(header.Format, "WAVE", 4) != 0) {
fprintf(stderr, "Unknown input format\n");
exit(EXIT_FAILURE);
}
/* Read sub header */
while (fread(SubchunkID, sizeof(SubchunkID), 1, fIn)) {
fread(&SubchunkSize, sizeof(SubchunkSize), 1, fIn);
printf("Reading chunk of type %c%c%c%c (%d bytes)\n",
isprint(SubchunkID[0]) ? SubchunkID[0] : '?',
isprint(SubchunkID[1]) ? SubchunkID[1] : '?',
isprint(SubchunkID[2]) ? SubchunkID[2] : '?',
isprint(SubchunkID[3]) ? SubchunkID[3] : '?',
(int) SubchunkSize);
if (memcmp(SubchunkID, "fmt ", 4) == 0) {
/* read a fmt_ header */
fread(&subheader, SubchunkSize, 1, fIn);
/* we are going to adjust this header now to change the audio format */
if (subheader.AudioFormat != 7) {
fprintf(stderr, "Only mu-law audio input is supported\n");
exit(EXIT_FAILURE);
}
/* adjust audio format and bit depth */
subheader.AudioFormat = 1;
subheader.BitsPerSample = 16;
/* fix derivative fields */
subheader.ByteRate = subheader.SampleRate * subheader.NumChannels * subheader.BitsPerSample / 8;
subheader.BlockAlign = subheader.NumChannels * subheader.BitsPerSample / 8;
/* we don't write ExtraParamSize, because for AudioFormat == 1 it is not needed */
SubchunkSize -= 2;
/* Open file and write the header for our updated fmt_ chunk */
fOut = fopen (outputFile, "wb");
fwrite(&header, sizeof(struct header_t), 1, fOut); /* Main header */
fwrite(SubchunkID, sizeof(SubchunkID), 1, fOut); /* Subheader */
fwrite(&SubchunkSize, sizeof(SubchunkSize), 1, fOut);
fwrite(&subheader, SubchunkSize, 1, fOut);
} else if (memcmp(SubchunkID, "data", 4) == 0) {
/* here is our mu-law data */
/* write the header for our new chunk (it is twice as large) */
int32_t tSubchunkSize = SubchunkSize * 2;
fwrite(SubchunkID, sizeof(SubchunkID), 1, fOut);
fwrite(&tSubchunkSize, sizeof(SubchunkSize), 1, fOut);
/* process the data */
(fIn, fOut, SubchunkSize);
} else {
/* unknown chunk, skipping */
fseek(fIn, SubchunkSize, SEEK_CUR);
}
}
/* Cleanup and exit */
fclose(fIn);
fclose(fOut);
exit(EXIT_SUCCESS);
}
}
Just run gdb yourexe
Then in gdb:
break main
run
p &inputFile
That will give you the address of inputFile: ex $2 = (char (*)[256]) 0x62fd60
To get the size of a variable you can use p sizeof(variable) or p sizeof(type_of_the_variable>)
That said, not sure if it will help you to track down your problem.

Why is MD5Sum so fast

I've been studying hashing in C/C++ and tried to replicate the md5sum command in Linux. After analysing the source code, it seems that md5sum relies on the md5 library's md5_stream. I've approximated the md5_stream function from the md5.h library into the code below, and it runs in ~13-14 seconds. I've tried to call the md5_stream function directly and got ~13-14 seconds. The md5sum runs in 4 seconds. What have the GNU people done to get the speed out of the code?
The md5.h/md5.c code is available in the CoreUtils source code.
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <iostream>
#include <iomanip>
#include <fstream>
#include "md5.h"
#define BLOCKSIZE 32784
int main()
{
FILE *fpinput, *fpoutput;
if ((fpinput = fopen("/dev/sdb", "rb")) == 0) {
throw std::runtime_error("input file doesn't exist");
}
struct md5_ctx ctx;
size_t sum;
char *buffer = (char*)malloc (BLOCKSIZE + 72);
unsigned char *resblock = (unsigned char*)malloc (16);
if (!buffer)
return 1;
md5_init_ctx (&ctx);
size_t n;
sum = 0;
while (!ferror(fpinput) && !feof(fpinput)) {
n = fread (buffer + sum, 1, BLOCKSIZE - sum, fpinput);
if (n == 0){
break;
}
sum += n;
if (sum == BLOCKSIZE) {
md5_process_block (buffer, BLOCKSIZE, &ctx);
sum = 0;
}
}
if (n == 0 && ferror (fpinput)) {
free (buffer);
return 1;
}
/* Process any remaining bytes. */
if (sum > 0){
md5_process_bytes (buffer, sum, &ctx);
}
/* Construct result in desired memory. */
md5_finish_ctx (&ctx, resblock);
free (buffer);
for (int x = 0; x < 16; ++x){
std::cout << std::setfill('0') << std::setw(2) << std::hex << static_cast<uint16_t>(resblock[x]);
std::cout << " ";
}
std::cout << std::endl;
free(resblock);
return 0;
}
EDIT: Was a default mkspec problem in Fedora 19 64-bit.
fread() is convenient, but don't use fread() if you care about performance. fread() will copy from the OS to a libc buffer, then to your buffer. This extra copying cost CPU cycles and cache.
For better performance use open() then read() to avoid the extra copy. Make sure your read() calls are multiples of the block size, but lower than your CPU cache size.
For best performance use mmap() map the disk directly to RAM.
If you try something like the below code, it should go faster.
// compile gcc mmap_md5.c -lgcrypt
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gcrypt.h>
#include <linux/fs.h> // ioctl
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
char *addr;
int fd;
struct stat sb;
off_t offset, pa_offset;
size_t length;
ssize_t s;
unsigned char digest[16];
char digest_ascii[32+1] = {0,};
int digest_length = gcry_md_get_algo_dlen (GCRY_MD_MD5);
int i;
if (argc < 3 || argc > 4) {
fprintf(stderr, "%s file offset [length]\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
handle_error("open");
if (fstat(fd, &sb) == -1) /* To obtain file size */
handle_error("fstat");
offset = atoi(argv[2]);
pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
if (sb.st_mode | S_IFBLK ) {
// block device. use ioctl to find length
ioctl(fd, BLKGETSIZE64, &length);
} else {
/* offset for mmap() must be page aligned */
if (offset >= sb.st_size) {
fprintf(stderr, "offset is past end of file size=%zd, offset=%d\n", sb.st_size, (int) offset);
exit(EXIT_FAILURE);
}
if (argc == 4) {
length = atoi(argv[3]);
if (offset + length > sb.st_size)
length = sb.st_size - offset;
/* Canaqt display bytes past end of file */
} else { /* No length arg ==> display to end of file */
length = sb.st_size - offset;
}
}
printf("length= %zd\n", length);
addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
MAP_PRIVATE, fd, pa_offset);
if (addr == MAP_FAILED)
handle_error("mmap");
gcry_md_hash_buffer(GCRY_MD_MD5, digest, addr + offset - pa_offset, length);
for (i=0; i < digest_length; i++) {
sprintf(digest_ascii+(i*2), "%02x", digest[i]);
}
printf("hash=%s\n", digest_ascii);
exit(EXIT_SUCCESS);
}
It turned out to be an error in the Qt mkspecs regarding an optimization flag not being set properly.