Opening and Reading from a "large" gzip compressed file in C - c

I have been trying to open and read a gzip compressed file using gzip-based file IO functions in C. The compressed file that I have with me is quite large of size 12 GB. The uncompressed file was ~260 GB and hence I am not prepared to uncompress the file using gunzip and go ahead from there.
I am specifically using the below code to read and write into the buffers available to us-
#define windowBits 15
#define ENABLE_ZLIB_GZIP 32
#define CHUNK 0x4000
#define CALL_ZLIB(x) { \
int status; \
status = x; \
if (status < 0) \
{ \
fprintf(stderr, "%s:%d: %s returned a bad status of %d.\n", __FILE__, __LINE__, #x, status); \
exit(EXIT_FAILURE);\
} \
} \
int main ()
{
const char * file_name = "test.gz";
FILE * file;
z_stream strm = {0};
unsigned char in[CHUNK];
unsigned char out[CHUNK];
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.next_in = in;
strm.avail_in = 0;
CALL_ZLIB (inflateInit2 (& strm, windowBits | ENABLE_ZLIB_GZIP));
/* Open the file. */
file = fopen (file_name, "rb");
while (1) {
int bytes_read;
bytes_read = fread (in, sizeof (char), sizeof (in), file);
strm.avail_in = bytes_read;
do {
unsigned have;
strm.avail_out = CHUNK;
strm.next_out = out;
CALL_ZLIB (inflate (& strm, Z_NO_FLUSH));
have = CHUNK - strm.avail_out;
fwrite (out, sizeof (unsigned char), have, stdout);
}
while (strm.avail_out == 0);
if (feof (file)) {
inflateEnd (& strm);
break;
}
}
return 0;
}
The code accurately reads and writes from the zlib file based on a buffer that you specify initially. The buffer size is being fixed to a certain value (in the above case to 0x4000).
The problem now is that I cannot increase the size of this buffer beyond a certain value ( I can use 3276008 as buffer size, but not 32760008 ). To read a 12 GB compressed value, would need me to use a very big buffer. As specified in my edits, this looks like some kind of a DATA_ERROR not a BUFFERerror... so it is not a buffer error after all!
Is there any way how I can be able to record the whole 12 GB compressed file using the zlib functions above ?
EDIT #1
The error code returned by the function inflate is encapsulated by the CALL_ZLIB function which I am sorry to have not included. So I get the below error code when I run with the buffer size of 0x4000. I have added the CALL_ZLIB function to the code for your reference also.
Error msg :
parser.c:96: inflate(&strm, Z_NO_FLUSH) returned a bad status of -3. This obviously looks like a **DATA_ERROR.
EDIT #2
I have tried adding a negative value of windowBits to InflateInit2() but that did not solve any of my problems. The inflate() function initially reads my file correctly -- displaying all of my data the way I want it to..
0x55b0 [0x40]: event: 3
.
. ... raw event: size 64 bytes
. 0000: 03 00 00 00 00 00 40 00 18 03 00 00 18 03 00 00 ......#.........
. 0010: 4d 6f 64 65 6d 4d 61 6e 61 67 65 72 00 00 00 00 ModemManager....
. 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
. 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0 0 0x55b0 [0x40]: PERF_RECORD_COMM: ModemManager:792/792
0x55f0 [0x40]: event: 7
.
. ... raw event: size 64 bytes
. 0000: 07 00 00 00 00 00 40 00 19 03 00 00 01 00 00 00 ......#.........
. 0010: 19 03 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
. 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
. 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0 0 0x55f0 [0x40]: PERF_RECORD_FORK(793:793):(1:1)
0x5630 [0x40]: event: 3
.
But after some time, the displayed output becomes garbled and I cannot read from it anymore..
0x4d68 [0x38]: ........... 001 0..
0 0 00 00 00 0 00 000 00 ze 64s
. 0000: 07 00 00 00 00 00 40 00 19 03 00 00 01 00 00 00 .. 00 0 event: size 64 bytes
. 0000: 03 00 00 00 si sisizsiz4s
. 0000: 07 00 00 00 00 00 40 00 19 0....
. 0030: 00 00 00 00 00 00 00 00 00 00 00 00 ..#.#. 0010: 19 03 00 00 [0x38]: ........... 001 0..
0 0 00 00 00 0 00 000 00 ze 64s
. 0000: 07 00 00 00 00 00 40 00 100 00 00 00 00 ..............0 0 0x4d28 [0x40]: PERF_RECORD_FORK(135:135):(2:62)
0x4d68 [0x38]: ........... 001 0..
0 0 00 00 00 0 00 000 00 00 00 00: PERORD_FORK(135:135):(2:2)
This finally terminates with the error message I described in the Edit #1

I have resolved the problem.
The basic problem was that I was not initializing the strm.next_in member of z_stream in my code inside the loop. Hence after doing 1 iteration, the buffer got corrupted and I was getting the above errors.
I modified my code to --
strm.next_in = in;
strm.avail_in = 0;
CALL_ZLIB(inflateInit2 (&strm, windowBits | ENABLE_ZLIB_GZIP));
file = fopen(filename, "rb");
while(1)
{
int bytes_read;
strm.next_in = in; // added this line
bytes_read = fread(in, sizeof(char), sizeof(in), file);
strm.avail_in = bytes_read;
do
{
unsigned have;
strm.avail_out = CHUNK;
strm.next_out = out;

Related

C hexadecimal formatting giving me extra digits

I've been working on a small program to dump the hex values of a file, similar to od or hexdump, and I've ran into an issue when printing the values. For certain hex values, mostly ones with alphabetical characters as their second digit, it prints with 6 extra f digits before printing the actual number, instead of just printing a 2-width value like I had specified. I have confirmed that the values themselves are not unexpected in any way, it's the printing that's messing it up.
Code:
int main(int argc, char* argv[]) {
FILE* dataFile = fopen(argv[1], "rb");
int byteCount = 0;
char currentByte = fgetc(dataFile);
while (currentByte != EOF) {
printf("%08d", byteCount);
do {
//print as hex
printf(" %02x ", currentByte);
//set up for next loop
currentByte = fgetc(dataFile);
byteCount++;
} while (currentByte != EOF && (byteCount) % 16 != 0);
printf("\n");
}
printf("%08d\n", byteCount);
}
Output:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
00000016 03 00 3e 00 01 00 00 00 10 6b 00 00 00 00 00 00
00000032 40 00 00 00 00 00 00 00 08 23 02 00 00 00 00 00
00000048 00 00 00 00 40 00 38 00 0d 00 40 00 1f 00 1e 00
00000064 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00
00000080 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
00000096 ffffffd8 02 00 00 00 00 00 00 ffffffd8 02 00 00 00 00 00 00
00000112 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00
00000128 18 03 00 00 00 00 00 00 18 03 00 00 00 00 00 00
00000144 18 03 00 00 00 00 00 00 1c 00 00 00 00 00 00 00
00000160 1c 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
00000176 01 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00
00000192 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000208 fffffff8 34 00 00 00 00 00 00 fffffff8 34 00 00 00 00 00 00
Does anyone know what's going on here?
There are several problems here.
char is entirely unsuitable to hold raw binary data, because it has implementation-defined signedness and it often a signed type, see Is char signed or unsigned by default?. In fact char should only ever be used for text strings. Instead, you would normally use uint8_t. However... :
The EOF constant is of type int, so if you intend to compare something against EOF, it must be type int. fgetc is guaranteed to return characters as if they were unsigned char but converted to int - as it happens, int is large enough to hold all values of an unsigned char so int can be used here.
%x specifier for printf expects an unsigned int.
Fixes:
char currentByte -> int currentByte
printf(" %02x ", currentByte); -> printf(" %02x ", (unsigned int)currentByte);.
You must always check if fopen was successful and also fclose the file pointer when done. Also note that calling fopen directly on argv with no input sanitation is not acceptable in a professional program. You don't even know if argv[1] exists - the program needs a whole lot more error handling overall.

Trying to read bitmap file as hexadecimals

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NBRCOLOURS 16
#define COLOURSIZE 8
typedef struct
{
char colours[COLOURSIZE];
}BITMAP;
//Main Function
void main(void)
{
int count, count2;
char bm_file[] = "C:\\Coding\\Bitmap Program\\Sample.bmp";
FILE *fptr;
char ch;
int i = 0;
BITMAP bm_data[NBRCOLOURS];
fptr = fopen(bm_file, "rb");
if (fptr != NULL)
{
while ((ch = fgetc(fptr)) != EOF)
{
printf("%02X ", ch);
if (!(++i % 16)) putc('\n', stdout);
}
}
fclose(fptr);
system("pause");
return;
}
I am using this code which I found mostly online to try and read the contents of a bitmap file as its hexadecimal values. For some reason, this code stops right at the end of the header, and unfortunately ultimately I need to count the number of times each colour appears so that I can figure out which occurs most and which occurs least.
If anyone could tell me why this code stops at the end of the header for the bitmap, or lead me towards being able to pull the rest of the hexadecimal data out of the file, I would really appreciate it.
Here is the hex code:
42 4D C6 00 00 00 00 00 00 00 76 00 00 00 28 00
00 00 0A 00 00 00 0A 00 00 00 01 00 04 00 00 00
00 00 50 00 00 00 12 0B 00 00 12 0B 00 00 10 00
00 00 10 00 00 00 FF 00 00 00 00 FF 00 00 00 00
42 00 5A 5A 84 00 00 00 FF 00 FF 00 FF 00 00 FF
FF 00 08 FF FF 00 5A FF FF 00 FF FF FF 00 FF FF
FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF FF
FF 00 FF FF FF 00 92 59 00 16 47 00 00 00 25 90
01 64 61 00 00 00 59 90 11 64 61 00 00 00 99 00
16 48 11 00 00 00 90 01 64 61 11 00 00 00 00 16
64 61 00 00 00 00 01 16 46 10 09 00 00 00 11 64
41 00 99 00 00 00 16 64 11 09 95 00 00 00 66 48
10 09 53 00 00 00
And here is what prints:
42 4D FFFFFFC6 00 00 00 00 00 00 00 76 00 00 00 28 00
00 00 0A 00 00 00 0A 00 00 00 01 00 04 00 00 00
00 00 50 00 00 00 12 0B 00 00 12 0B 00 00 10 00
00 00 10 00 00 00
Long post, I'm sorry. Any help is greatly appreciated.
fgetc returns an int, not a char. You can't represent EOF with a char, as all of the possible values of a char are valid. EOF is (I think) -1 represented as an int, or 0xfffffff, so if you read 0xff as a char it's the same as EOF.
Change this:
char ch;
to:
int ch;
The number before a format specifier in printf, like %02X only guarantees a minimum number of characters outputted, not a maximum. fgetc returns an int, not a char. If the int is negative two's complement then the entire bitstring representing the int will get printed, including the FF bytes at the start. EOF is not representable as a char; only as an int.
In your case we know that the file we're working with is small enough that loading the entire file into a buffer will probably succeed, so we can just use malloc and free instead:
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char byte;
int main(int argc, char *argv[])
{
FILE *fp = fopen("C:\\Coding\\Bitmap Program\\Sample.bmp", "rb");
byte *buffer = NULL;
size_t len;
int i;
fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);
buffer = malloc(len);
if(!buffer)
{
perror("malloc");
exit(EXIT_FAILURE);
}
fread(buffer, 1, len, fp);
fclose(fp);
for(i = 0; i < len; i++)
{
if(i%16==0) putchar('\n');
printf("%.2X ", buffer[i]&0xFF);
}
free(buffer);
return 0;
}

Save audio stream in file using C libwebsockets

I have a C server that uses libwebsockets and I want to save a received audio stream in a file on disk.
Here is my code snippet:
#define FILENAME "/home/ubuntu/Desktop/file.wav"
FILE *received_file;
struct lws_context *Audiocontext;
static int callback_audio(
struct lws *wsi,
enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
{
printf("client is connected\n");
received_file = fopen(FILENAME, "w+");
if (received_file == NULL)
{
printf("Failed to open file\n");
exit(EXIT_FAILURE);
}
}
break;
case LWS_CALLBACK_RECEIVE: {
if(strcmp((char*)in,"EOS")==0)
{
printf("End of stream!\n");
fclose(received_file);
}
else
{
fwrite(in, 1, len, received_file);
}
}
}
}
I got the message "client is connected" and also the file, but the content isn't ok, I cannot play it. I think there is a problem regarding the way I save the stream on file using fwrite().
The client is sending audio chunks encoded as wav, 16Khz, mono. Here is a snippet from client (it's a javascript client, the full code is here:http://kaljurand.github.io/dictate.js/).
if (recorder) {
recorder.stop();
config.onEvent(MSG_STOP, 'Stopped recording');
// Push the remaining audio to the server
recorder.export16kMono(function(blob) {
socketSend(blob);
socketSend(TAG_END_OF_SENTENCE);
recorder.clear();
}, 'export16kMono');
config.onEndOfSpeech();
} else {
config.onError(ERR_AUDIO, "Recorder undefined");
}
The client is working well, I use it for exactly the same task, but using a Java server. I would appreciate if someone could indicate me how to save these audio chunks in a valid file.
I think that you do not write header in your wav file. To do so,
you can write some function to do so see specification here
or you can use a dedicaded library, like libsndfile, which is not so complicated to use:
// instead of fopen, write something like
SF_INFO info;
SNDFILE * sf;
info.samplerate = sample_rate;
info.channels = 1;
info.sections = 1;
info.seekable = 0;
info.frames = 0;
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
sf = sf_open(filename, SFM_WRITE, &info);
// instead of fwrite, something like
sf_write_short(sf, in, len / sizeof(short));
// and instead of fclose
sf_close(sf);
I didn't use libsndfile, but I change something on the client side. This is the current hexdump output:
00000000 52 49 46 46 20 60 00 00 57 41 56 45 66 6d 74 20 |RIFF `..WAVEfmt |
00000010 10 00 00 00 01 00 02 00 44 ac 00 00 10 b1 02 00 |........D.......|
00000020 04 00 10 00 64 61 74 61 00 60 00 00 00 00 00 00 |....data.`......|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00006020 00 00 00 00 00 00 00 00 00 00 00 00 52 49 46 46 |............RIFF|
00006030 20 60 00 00 57 41 56 45 66 6d 74 20 10 00 00 00 | `..WAVEfmt ....|
00006040 01 00 02 00 44 ac 00 00 10 b1 02 00 04 00 10 00 |....D...........|
00006050 64 61 74 61 00 60 00 00 00 00 00 00 00 00 00 00 |data.`..........|
00006060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
0000c050 00 00 00 00 00 00 00 00 52 49 46 46 20 60 00 00 |........RIFF `..|
0000c060 57 41 56 45 66 6d 74 20 10 00 00 00 01 00 02 00 |WAVEfmt ........|
0000c070 44 ac 00 00 10 b1 02 00 04 00 10 00 64 61 74 61 |D...........data|
0000c080 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.`..............|
0000c090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
It seems to be wav encoded, but i don't have a content.

How can I write a structure to a file ?

I have tried to look this up in multiple places and I cannot understand why fwrite doesn't work.
If I had a structure with 100 fields I would not want to use fprintf with 100 format specifiers.
struct emp
{
char name[15];
int age;
int salary;
char address[30];
};
int main()
{
char str[60];
struct emp emp1[5] = {{"Yoda",23,45000,"Asia"},{"Darth",34,2344,"NAmerica"},{"Jabba",22,5566,"Africa"},{"Luke",33,3399,"SAmerica"},{"Laya",44,6677,"Europe"}};
FILE *fp;
fp = fopen("C:/.../sampleText.txt","w");`
int i=0;
for(i=0; i<5; i++)
{
fwrite(&emp1[i],sizeof(emp1[i]),1,fp);
//fprintf(fp,"%s, %d, %d, %s\n",&emp1[i].name,emp1[i].age,emp1[i].salary,emp1[i].address);
}
fclose(fp);
getch();
}
There are two answers:
It does work, if everything is set correctly and porting the written data to other machines is not an issue.
It doesn't work if you have any of a large number of common features in data structures, or if you need to move the data from one type of machine (say an Intel machine) to another type (say PowerPC or SPARC).
In your example structure, you have no pointers, so you could write the structure verbatim to a file, and then in another invocation of the program running on the same (type of) machine, you could read it back in, and you would see the same data.
However, if your structure contained pointers, you could not meaningfully write the structure to disk. The pointers in one invocation of the program need not have any significance in another invocation of the program. If you needed to port the data between a little-endian (Intel) and big-endian (PowerPC, SPARC) machine, you'd have to use a platform-neutral way of accessing the data; simply writing the data to disk would not work.
So, where portability is not an issue, this code should work — Unix or Windows. It uses the "wb" and "rb" arguments to fopen() because the data is binary data, not plain text. The b is optional but harmless on Unix; it is crucial on Windows. The code also fixes the file name to sampledata.bin so it can be run on either platform, writing in the current directory. It writes the data; it then reads the data; it then compares the read data with the written data, reporting any problems. If the program says nothing, all is OK.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct emp
{
char name[15];
int age;
int salary;
char address[30];
};
int main(void)
{
char const filename[] = "sampledata.bin";
struct emp emp1[5] =
{
{ "Yoda", 23, 45000, "Asia" },
{ "Darth", 34, 2344, "N America" },
{ "Jabba", 22, 5566, "Africa" },
{ "Luke", 33, 3399, "S America" },
{ "Leia", 44, 6677, "Europe" },
};
struct emp emp2[5];
FILE *ifp;
FILE *ofp;
int i;
ofp = fopen(filename, "wb");
if (ofp != 0)
{
if (fwrite(emp1, sizeof(emp1), 1, ofp) != 1)
{
fprintf(stderr, "Failed to write to %s\n", filename);
exit(1);
}
fclose(ofp);
}
ifp = fopen(filename, "rb");
if (ifp != 0)
{
if (fread(emp2, sizeof(emp2), 1, ifp) != 1)
{
fprintf(stderr, "Failed to read from %s\n", filename);
exit(1);
}
fclose(ifp);
}
for (i = 0; i < 5; i++)
{
if (emp1[i].age != emp2[i].age ||
emp1[i].salary != emp2[i].salary ||
strcmp(emp1[i].name, emp2[i].name) != 0 ||
strcmp(emp1[i].address, emp2[i].address) != 0)
printf("Difference in record %d\n", i);
}
return 0;
}
Content of the file sampledata.bin:
0x0000: 59 6F 64 61 00 00 00 00 00 00 00 00 00 00 00 00 Yoda............
0x0010: 17 00 00 00 C8 AF 00 00 41 73 69 61 00 00 00 00 ........Asia....
0x0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030: 00 00 00 00 00 00 00 00 44 61 72 74 68 00 00 00 ........Darth...
0x0040: 00 00 00 00 00 00 00 00 22 00 00 00 28 09 00 00 ........"...(...
0x0050: 4E 20 41 6D 65 72 69 63 61 00 00 00 00 00 00 00 N America.......
0x0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0070: 4A 61 62 62 61 00 00 00 00 00 00 00 00 00 00 00 Jabba...........
0x0080: 16 00 00 00 BE 15 00 00 41 66 72 69 63 61 00 00 ........Africa..
0x0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00A0: 00 00 00 00 00 00 00 00 4C 75 6B 65 00 00 00 00 ........Luke....
0x00B0: 00 00 00 00 00 00 00 00 21 00 00 00 47 0D 00 00 ........!...G...
0x00C0: 53 20 41 6D 65 72 69 63 61 00 00 00 00 00 00 00 S America.......
0x00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00E0: 4C 65 69 61 00 00 00 00 00 00 00 00 00 00 00 00 Leia............
0x00F0: 2C 00 00 00 15 1A 00 00 45 75 72 6F 70 65 00 00 ,.......Europe..
0x0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0110: 00 00 00 00 00 00 00 00 ........
0x0118:
You don't specify what you mean by fwrite doesn't work, but I'll assume you're working on Windows, in which case you need to specify "wb" to fopen. By default on Windows, it's writing in text mode (i.e. "wt").
not a good idea to write struct to file or sockets as it is. It is inviting complex to solve problems. the best approach is to use serialization before writing. Also, as Jim pointed out above, make sure to open the file in binary.
Take a look in this question and the answers. there is a pretty good answer and explanation for your question.
Passing a structure through Sockets in C
Data serialization is a non-trivial task. As some others have pointed out, it is possible in some cases to write the contents of your struct to disk as binary data. It's the simplest to write, but it is unlikely to be stable. Each time you recompile your code, it can potentially change the format the data is written and read in.
Your best option is to use a standard data interchange format, such as CSV, XML, or JSON. There are many existing tools to utilize these formats, so you should look into using one of them.

strcat giving unexpected result

This is a very small portion of a large project...
These are typedefs defined in standard header file for the project.
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
typedef uint8_t u_int8_t;
Now this is the actual function causing problem ...
void function(u_int8_t *data1, u_int32_t data1len,
u_int8_t *data2, u_int32_t data2len)
{
FILE *fq,*fr,*fs;
char *data3;
int data3len;
data3len=data1len+data2len;
printf("\n%d",data1len);
printf("\n%d",data2len);
printf("\n%d",data3len);
fq=fopen("data1.txt","wb");
fwrite((char *)data1,data1len,1,fq);
fr=fopen("data2.txt","wb");
fwrite((char *)data2,data2len,1,fr);
data3=(char *)data1;
strcat(data3,(char *)data2);
fs=fopen("data3.txt","wb");
fwrite((char *)data3,data3len,1,fs);
}
Some output Snapshots ...
40
14
54
udit#udit-Dabba ~$ hexdump -C data1.txt
00000000 60 00 00 00 00 8c 06 00 00 00 00 00 00 00 00 00 |`...............|
00000010 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 02 |........|
00000028
udit#udit-Dabba ~$ hexdump -C data2.txt
00000000 00 26 00 26 00 00 00 01 00 00 00 02 34 12 00 65 |.&.&........4..e|
00000010 00 34 00 00 61 62 63 64 |.4..abcd|
00000018
udit#udit-Dabba ~$ hexdump -C data3.txt
00000000 60 00 00 00 00 8c 06 00 00 00 00 00 00 00 00 00 |`...............|
00000010 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 02 00 78 f8 65 00 00 00 02 |.........x.e....|
00000030 f4 1f 96 00 18 34 a6 bf 1c 03 96 00 88 f1 90 08 |.....4..........|
00000040
Why contents of data2.txt are not copied to data3.txt ??? If there is any other possible way then please tell me !!!! Thanx in advance ...
Why contents of data2.txt are not copied to data3.txt?
strcat is specifically for concatenating C strings and only copies up until the null terminator character. So it stops copying from the source once it encounters 00 which it considers the end of the string. Notice how data2 begins with a 00, so it stops immediately.
You'll instead need to memcpy with the destination being 1 past the last byte in data3 and the source being data2. You'll also need to fail gracefully if data3 (which is really data1) does not have enough space to hold data2.
I think you could do it much easier, saving you from ensuring that the respective memory block is large enough.
void function(u_int8_t *data1, u_int32_t data1len,
u_int8_t *data2, u_int32_t data2len)
{
FILE *fq,*fr,*fs;
char *data3;
fq=fopen("data1.txt","wb");
fwrite((char *)data1, data1len, 1, fq);
fclose(fq);
fr=fopen("data2.txt","wb");
fwrite((char *)data2, data2len, 1, fr);
fclose(fr);
fs=fopen("data3.txt","wb");
fwrite((char *)data1, data1len, 1, fs);
fwrite((char *)data2, data2len, 1, fs);
fclose(fs);
}
You try to append data2 to the end of data1.
You intend to put the result into a third string (data3), but in fact data3 is just data1; they point to the same location.
Your code is equivalent to
strcat (data1, data2);
which of course writes beyond data1's end.
(there is another problem: if the caller of the function uses a "string_literal" as argument#1,
data1 will not be writable. )
You probably have to allocate some memory for the resulting string and make point data3 to it.

Resources