I want sign a tar.gz file and verify the signature for do this i put a signature (in char) in my file. Then i have an another executable who check the sign and if she is good delete this, and to do that i get the content of the file whitout my signature and copy on an other file that a create.
But here is the problem, When a do this my tar.gz original file make a size of 141 and my newly created file make a size of 140. Then when a decompress them i have this error message:
gzip: stdin: unexpected end of file tar:
Child returned status 1 tar:
Error is not recoverable: exiting now
I think when i get the content i forgot a charactere. I tried to use clearerr or feof whitout success.
This is my code for get the content of the signed file:
#define SIZE_SIGNATURE (423)
int get_size(char *file)
{
struct stat sb;
int size = 0;
if (stat(file, &sb) == -1) {
fprintf(stderr, "Cant access the %s file\n", file);
return (-1);
}
size = sb.st_size - SIZE_SIGNATURE;
size = size / 4;
if (size <= 0) {
fprintf(stderr, "The content of the file is invalid\n");
return (-1);
}
return (size);
}
int *get_content(char *file, int size)
{
FILE *fp = NULL;
int *content = NULL;
int i = 0;
content = malloc(sizeof(int) * size);
if (!content) {
fprintf(stderr, "Error, malloc fail\n");
return (NULL);
}
fp = fopen(file,"rb");
if (!fp) {
fprintf(stderr, "Cant open %s file\n", file);
return (NULL);
}
fread(content, sizeof(int), size, fp);
fclose(fp);
return (content);
}
And when i have created my new file i put the content on them like this:
fp = fopen(new_name, "a");
if (!fp) {
fprintf(stderr, "A problem has occured during file creation.\n Cant delete signature\n");
free(new_name);
return;
}
fwrite(content, sizeof(int), size, fp);
Why i do: size = size / 4 (i dont know if is the thing to do)
He is a little code for understanding the thing i simply put three int in non lisible charactere
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
void ecriture1()
{
FILE* F;
int a = 5;
int b = 6;
int d = 42;
F = fopen("test.bin","wb");
fwrite(&a,sizeof(int),1,F);
fwrite(&d,sizeof(int),1,F);
fwrite(&b,sizeof(int),1,F);
fclose(F);
}
void lecture1()
{
int *tab;
int i = 0;
int size;
struct stat sb;
FILE* F;
stat("test.bin", &sb);
F = fopen("test.bin","rb");
size = sb.st_size;
tab = malloc(sizeof(int) * size);
while (i < size) {
fread(&tab[i], sizeof(int), 1, F);
i++;
}
for (i = 0; i < size; i++)
printf("[i] = %d,", tab[i]);
printf("\n");
fclose(F);
}
int main()
{
ecriture1();
lecture1();
return 0;
}
He is the resultat when i dont put the / 4:
[i] = 5,[i] = 42,[i] = 6,[i] = 0,[i] = 0,[i] = 0,[i] = 0,[i] = 0,[i] = 0,[i] = 0,[i] = 0,[i] = 0,
And when i put / 4:
[i] = 5,[i] = 42,[i] = 6,
EDIT:
In my programe when i delete the / 4 and i decompresse the new .tar.gz i have this error message:
gzip: stdin: invalid compressed data--length error
tar: Child returned status 1
tar: Error is not recoverable: exiting now
So i think without error on my part that i should put the / 4 but i cant explain this.
You have a rounding error because you divide the size by 4.
I think the reason why you do size / 4 is because you later do sizeof(int) * size and if you have 4 byte integers then that will cause your size to be 4 times larger than you want. So I think you wrote two bugs there that cancel each other out.
I would suggest you remove the / 4 as well as also removing the sizeof(int) * and thus always just let size be the byte count.
As a bonus, this will remove the rounding error that you might have which is probably the whole reason for your problem. Because 141/4 = 35,25 which will be rounded to 35. Then 35 * sizeof(int) = 35 * 4 = 140.
Also I would not recommend storing arbitrary binary data of arbitrary size in an array of int because an int array should have a size evenly divisible by 4. I would probably go for a char * or just a void * rather than int *.
Related
I have an array, which holds 6 words and a secret word
char boardInputs[7][6];
I need to autosave to binary file this array every time when user entered the word. After restarting the program, I need to read the saved array of words from the binary file and install it into the input data array of the board
void readArray(int rows, int cols, char array[rows][cols]) {
FILE *data;
data = fopen("autosave.bin", "rb");
fread(array, sizeof(char[rows][cols]), 1, data);
}
void autoSave() {
int result = EXIT_SUCCESS;
char file_name[] = "autosave.bin";
FILE *fp = fopen(file_name, "wb");
if (fp == NULL) {
result = EXIT_FAILURE;
fprintf(stderr, "fopen() failed for '%s'\n", file_name);
} else {
size_t element_size = sizeof *boardInputs;
size_t elements_to_write = sizeof boardInputs;
size_t elements_written = fwrite(boardInputs, element_size, elements_to_write, fp);
if (elements_written != elements_to_write) {
result = EXIT_FAILURE;
fprintf(stderr, "fwrite() failed: wrote only %zu out of %zu elements.\n",
elements_written, elements_to_write);
}
fclose(fp);
}
}
int main() {
int cols = 7;
int rows = 6;
char (*myArray)[cols] = allocArray(rows, cols);
readArray(rows, cols, myArray);
strcpy(boardInputs, myArray);
free(myArray);
}
I created this code, but the words from the binary file are set incorrectly. How to fix it?
There are multiple problems in your code:
you do not test for fopen() failure in readArray;
you do not close the file in read_array;
result is unused in autoSave;
strcpy is incorrect to copy the whole board. You should test if readArray succeeded and use memcpy;
the sizes in autoSave are incorrect: size_t element_size = sizeof *boardInputs evaluates to the size of a word, ie 6 bytes, and size_t elements_to_write = sizeof boardInputs is the size in bytes of the whole array. fwrite will attempt to write 6 * 42 bytes, causing undefined behavior as it accesses boardInputs beyond its boundaries. The length of an array is its size divided by the element size. In this case, it is probably best to use bytes, not words as the unit;
to ensure consistency between boardInputs and myArray, they should be defined with the same size by construction.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_COUNT 7
#define WORD_LEN 6
char boardInputs[WORD_COUNT][WORD_LEN];
const char *autoSaveFilename = "autosave.bin";
int readArray(int rows, int cols, char array[rows][cols]) {
FILE *fp = fopen(autoSaveFilename, "rb");
if (fp == NULL)
return -1;
int n = fread(array, sizeof(char[rows][cols]), 1, fp);
fclose(fp);
return n == 1 ? 0 : -1;
}
int autoSave(void) {
int result = EXIT_SUCCESS;
FILE *fp = fopen(autoSaveFilename, "wb");
if (fp == NULL) {
result = EXIT_FAILURE;
fprintf(stderr, "fopen() failed for '%s': %s\n",
autoSaveFilename, strerror(errno));
} else {
size_t element_size = 1;
size_t elements_to_write = sizeof(boardInputs);
size_t elements_written = fwrite(boardInputs, 1, elements_to_write, fp);
if (elements_written != elements_to_write) {
result = EXIT_FAILURE;
fprintf(stderr, "fwrite() failed: wrote only %zu bytes out of %zu.\n",
elements_written, elements_to_write);
}
fclose(fp);
}
return result;
}
int main() {
char myArray[WORD_COUNT][WORD_LEN];
if (!readArray(WORD_COUNT, WORD_LEN, myArray))
memcpy(boardInputs, myArray, sizeof boardInputs);
return 0;
}
autoSave() is calling fwrite() with incorrect arguments, sizeof boardInputs is the total size of the 2d array so number of elements is 1. This was the key issue.
autoSave() doesn't return anything so eliminate result.
autoSave() and readArray() hard-code the same path, so make it a define instead of duplication.
readArray() relies on a global variable, so elevated rows and cols to macro constants and simplified number of arguments.
readArray() should close the data file handle.
main() should return an int.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 7
#define COLS 6
#define PATH "autosave.bin"
char boardInputs[ROWS][COLS];
void autoSave() {
FILE *fp = fopen(PATH, "wb");
if(!fp) {
fprintf(stderr, "fopen() failed for '%s'\n", PATH);
return;
}
size_t elements_to_write = sizeof boardInputs;
size_t elements_written = fwrite(boardInputs, 1, elements_to_write, fp);
if (elements_written != elements_to_write) {
fprintf(stderr, "fwrite() failed: wrote only %zu out of %zu elements.\n",
elements_written, elements_to_write);
}
fclose(fp);
}
void printArray(char array[ROWS][COLS]) {
for(int i = 0; i < ROWS; i++) {
printf("%d: %s\n", i, array[i]);
}
}
void readArray(char array[ROWS][COLS]) {
FILE *data = fopen(PATH, "rb");
fread(array, sizeof(char[ROWS][COLS]), 1, data);
fclose(data);
}
int main() {
for(unsigned i = 0; i < 7; i++) {
char s[7];
sprintf(s, "%u", i);
strcpy(boardInputs[i], s);
}
printArray(boardInputs);
autoSave();
char myArray[ROWS][COLS];
readArray(myArray);
printArray(myArray);
return 0;
}
The output demonstrate the read and write have the same values:
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
I have a large file containing floating point numbers and I want to read them.
52.881 49.779 21.641 37.230 23.417 7.506 120.190 1.240 79.167 82.397 126.502 47.377 112.583 124.590 103.339 5.821 24.566 38.916 42.576
This is just the beggining of the file. It has 10000000 numbers.
I got this code but I don't know how to print the numbers.
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
int main()
{
int fd;
size_t bytes_read, bytes_expected = 1000000*sizeof(double);
double *data;
char *infile = "file.dat";
if ((fd = open(infile,O_RDONLY)) < 0)
err(EX_NOINPUT, "%s", infile);
if ((data = malloc(bytes_expected)) == NULL)
err(EX_OSERR, "data malloc");
bytes_read = read(fd, data, bytes_expected);
if (bytes_read != bytes_expected)
err(EX_DATAERR, "Read only %d of %d bytes",
bytes_read, bytes_expected);
/* print all */
free(data);
exit(EX_OK);
}
You are attempting to read a text file as if the data was binary, so you will read some bytes but the double values stored in the array will not be the values that you wanted to read from the file, you can probably do this
FILE *file;
double *array;
size_t count;
const char *infile = "file.dat";
file = fopen(infile, "r");
if (file == NULL)
return -1;
count = 0;
while (fscanf(file, "%*lf") == 1)
count += 1;
rewind(file);
array = malloc(count * sizeof(*array));
if (array == NULL) {
fprintf(stderr, "cannot allocate %zu bytes!\n", count * sizeof(*array));
fclose(file);
return -1;
}
// Read the values into the array
for (size_t i = 0; i < count; ++i) {
fscanf(file, "%lf", &array[i]);
}
// Print the array
for (size_t i = 0; i < count; ++i) {
fprintf(stdout, "%f\n", array[i]);
}
// Release memory
free(array);
Since you want a fast solution, maybe you have to sacrifice memory.
The faster manner of reading a file is in binary form.
Thus, I would obtain the file size with an efficient method,
then I would allocate memory accordingly,
with the idea of uploading the entire file to memory.
There, since memory reading is faster than file reading,
the data can be quickly read by using sscanf(...).
We can also observe that each floating point number
needs at least 3 characters to be stored in a text file:
1 char for the dot ('.'),
1 char for some digit,
and 1 char for
a space (' ') used to separating a value from its succesor in the
file.
Thus, the file size divided by 3 will be the upper bound for the size of the array of doubles.
#include <stdio.h>
int main(void) {
char *filename = "file.dat";
FILE *F = fopen(filename, "rb");
fseek(F, 0L, SEEK_END);
long int filesize = ftell(F);
rewind(F);
char *data = malloc(filesize+1);
fread(data, filesize, 1, F);
data[filesize] = '\0'; // End of string, just in case
fclose(F);
// The desired data will be stored in array:
double *array = malloc(sizeof(double) * filesize/3);
int ret;
int n; // represents the no chars in a sscanf(...) reading
double *a = array;
while (1) { // Infinite loop...
ret = sscanf(data, " %lg%n", a, &n);
if (ret == EOF) break; // <<---- EXIT POINT of the loop
a++;
data += n;
}
long int array_size = a - array + 1;
}
I've written a program to mess around with writing pointers into files(fwrite) and reading into pointers from files(fread). However the program doesn't seem to write a single thing into the file, nor does it seem to read anything from the file; it just prints the final incrementation of my pointer 5 times and exits. Can anyone spot the error/mistake in my syntax that seems to be doing this?
#include <stdio.h>
int main() {
FILE *fTest;
int *testPtr;
int x = 10;
if ((fTest = fopen("test.c", "wb")) == NULL) {
printf("Error!");
}
testPtr = &x;
int i;
for (i = 0; i < 5; i++) {
fwrite(testPtr, sizeof(int), 1, fTest);
*testPtr += 1;
}
for (i = 0; i < 5; i++) {
fread(testPtr, sizeof(int), 1, fTest);
printf("%d", *testPtr);
}
fclose(fTest);
}
Steps to take:
Write the data to the file.
Close the file.
Open the file again in read mode.
Read the data from the file.
That should work.
Also, the output file name, test.c, seems a bit strange. Is that on purpose?
#include <stdio.h>
int main() {
FILE *fTest;
int *testPtr;
int x = 10;
char const* file = "test.data"; // Using .data instead of .c
testPtr = &x;
int i;
// Write the data.
if ((fTest = fopen(file, "wb")) == NULL) {
printf("Error!");
}
for (i = 0; i < 5; i++) {
fwrite(testPtr, sizeof(int), 1, fTest);
*testPtr += 1;
}
fclose(fTest);
// Read the data.
if ((fTest = fopen(file, "rb")) == NULL) {
printf("Error!");
}
for (i = 0; i < 5; i++) {
fread(testPtr, sizeof(int), 1, fTest);
printf("%d", *testPtr);
}
fclose(fTest);
}
Left aside the fact that you don't check thre return value of fwrite() I would assume that you do write into "test.c", after you run the program the file should exist with a size of 5 * sizeof(int) bytes. But you can't read from it for two reasons:
you open the file write-only. Change "wb" to "w+b" to allow reading
after writing, you must reset the read-write pointer to the beginning of the file: call fseek(fTest, 0, SEEK_SET ); before reading
The problem is that you're reading from the file while it's opened in write mode.
Add this code between your write loop and read loop and it will work:
fclose(fTest);
if ((fTest = fopen("test.c", "rb")) == NULL) {
printf("Error!");
}
I am trying to get the data from an array of longs that I have just created but I got different data.
please see code below :
#include <string.h>
#include "readfile.h"
int main()
{
long wr_data [6] ;
wr_data[0] = 11;
wr_data[1] = 1100;
wr_data[2] = 1122323;
wr_data[3] = 11333;
wr_data[4] = 11434243;
wr_data[5] = 1166587;
writeFile(wr_data);
readFile();
return(0);
}
int readFile()
{
FILE *file;
long * data
printf("Error Reading File\n");;
/* Open file for both reading and writing */
file = fopen(fileName, "r");
if (file == NULL)
{
printf("Error Reading File\n");
return -1;
}
for (int i = 0; i < 5; i++)
{
fscanf(file, "%ld", &data[i] );
printf("data[%d]: %ld \n",i, data[i]);
}
fclose(file);
return 0;
}
int writeFile(long * data)
{
FILE *fp;
if (data != NULL)
{
if ((fp = fopen(fileName,"w")) == NULL)
return -1;
if (*data !=0 )
fwrite(data,sizeof(long),6,fp);
printf("Write data\n");
fclose(fp);
}
return 0;
}
the result I get is as follows :
Write data
data[0]: 140526045102081
data[1]: 47
data[2]: 197764
data[3]: 140526045102080
data[4]: 4096
I want to preserve the write function as it is as it comes from an existing code. I tried also the function fread but without success
fread(data, sizeof(long ), 6, file);
Thanks in advance for help.
It's working here. I made the following changes to your code:
//needed for malloc
#include <stdio.h>
//needed for output
#include <stdlib.h>
...
char *fileName = "so";
...
//allocate memory to store the values
long *data = (long *)malloc(sizeof(long)*6);
...
//read the stored longs
fread(data, sizeof(long ), 6, file);
int i;
for(i=0; i<6; i++)
printf("%ld\n", data[i]);
what do you think?
edit:
Well the main change was the memory allocation. When you want to store values of any kind, your program needs to be granted by the operating system a memory zone to store those values.
In this case we had two options, either create a staticly allocated array with a fixed size, or allocate the needed memory in a dynamic fashion with the malloc function or equivalent.
Don't forget, if you want to store something, first make sure you have a place for it to be stored (i.e. allocated memory). If you don't you will most likely get an error "Segmentation Fault" aka "SIGSEGV" which means that you tried to access memory that didn't belong to you.
Also, the "fscanf(file, "%ld", &data[i] );" will read "file" as text and will try to parse floats out of that same text. Since you're storing the longs as longs and not as text, this will not work, since you're writing and reading different things.
You are writing the binary content of the array to the file and afterwards try to interpret this as a long value which can obviously not work. If you want to store the numbers as text you must convert them to text before writing or print them to file by using the fprintf(FILE *, const char *, ...) function.
It is working as expected using the following code using a text file (you might want to change the filename). Otherwise you could just fwrite and fread the whole content, depending on your needs.
#include <stdio.h>
const char *filename = "yourfile";
int readFile()
{
FILE *file;
long data[6];
int i;
printf("Error Reading File\n");;
/* Open file for both reading and writing */
file = fopen(filename, "r");
if (file == NULL)
{
printf("Error Reading File\n");
return -1;
}
for (i = 0; i < 6; i++)
{
fscanf(file, "%ld", &data[i] );
printf("data[%d]: %ld \n",i, data[i]);
}
fclose(file);
return 0;
}
int writeFile(long * data)
{
FILE *fp;
int i;
if (data != NULL)
{
if ((fp = fopen(filename,"w")) == NULL)
return -1;
if (*data !=0 )
{
for(i = 0; i != 6; ++i)
fprintf(fp, "%ld ", data[i]);
}
printf("Write data\n");
fclose(fp);
}
return 0;
}
int main()
{
long wr_data [6] ;
wr_data[0] = 11;
wr_data[1] = 1100;
wr_data[2] = 1122323;
wr_data[3] = 11333;
wr_data[4] = 11434243;
wr_data[5] = 1166587;
writeFile(wr_data);
readFile();
return(0);
}
I am asked to split files into fixed-size blocks to do the file encryption. More specifically, I have lots of files, which could be binary or text.
I am asked to write a user program that takes as input these files, splits each file into say many 32-bit blocks, and then sends out the 32-bit blocks.
The scenario is that the user backups their files in a remote server by splitting their files into blocks, encrypting the blocks (using RSA), and then sending the ciphertexts to the server.
Consider two files, one is a 33-bit text file A and another is a 34-bit binary file B.
A can be partitioned into two 32-bit blocks A1 and A2 (the last 31 bis of A2 are all 0's).
B can be partitioned into two 32-bit blocks B1 and B2 (the last 30 bis of B2 are all 0's).
If I obtain A1 (or A2, B1, B2), then I regard A1 as a 32-bit integer and can do the RSA encryption.
I am able to write code for RSA encryption, but unfortunately I have no idea about how to write the C code for obtaining A1, A2, B1, B2.
Can anyone help me write a sample code or give me some reference?
Below is the high-level algorithm which you can easily convert to C code:
char* get_Next_Block_From_File(FILE *fp, int seek_offset, int blockSize)
{
// Open file
// lseek to seek_offset
len = blockSize / 8;
bit_pos = blockSize % 8;
for (i=0; i<len; i++) {
copy_from_file_to_local_buffer_byte_by_byte();
}
if (bit_pos) {
byte[i] <<= (8 - bit_pos);
append_byte_to_local_buffer();
}
return local_buffer;
}
C Program for splitting the given file into fixed size blocks
// split.cpp : main project file.
#include "stdafx.h"
using namespace System;
#include <stdio.h>
#include <string.h>
#include <conio.h>
#define SEGMENT 600 //approximate target size of small file
long file_size(char *name);//function definition below
int splitFile(char *fp1, size_t maxSize);
long file_size(char *name)
{
FILE *fp = fopen(name, "rb"); //must be binary read to get bytes
long size=-1;
if(fp)
{
fseek (fp, 0, SEEK_END);
size = ftell(fp)+1;
fclose(fp);
}
return size;
}
/*
** splitFile
** Splits an existing input file into multiple output files with a specified
** maximum file size.
**
** Return Value:
** Number of created result files, or 0 in case of bad input data or a negative
** value in case of an error during file splitting.
*/
int splitFile()
{
int result = 0;
char buffer[1024];//change see //2098 * 16
size_t size;
size_t read;
size_t written;
int segments=0, i, len, accum;
//FILE *fp1, *fp2;
char filename[260]={""};
//char filename[260]={"D:\\smallFileName_"};//base name for small files.
char largeFileName[]={"D:\\Payload_data\\Datafile_to_split.txt"};//change to your path
long sizeFile = file_size(largeFileName);
char smallFileName[260];
char line[1024];
long maxSize= sizeFile/SEGMENT + 1;
int filecounter=1;
FILE *fIn;
FILE *fOut;
fIn = fopen(largeFileName, "rb");
if ((fIn != NULL) && (maxSize > 0))
{
// fIn = fopen(fIn, "rb");
if (fIn != NULL)
{
fOut = NULL;
result = 1; /* we have at least one part */
// Splitting Data from pchar into multiple files
for(i=1; i<25 ;i++)
{
sprintf(smallFileName, "%s%d.txt", filename, i);
printf("\n File number %d",i);
while (!feof(fIn))
{
/* initialize (next) output file if no output file opened */
if (fOut == NULL)
{
filecounter++;
sprintf(buffer, "smallFileName_%d", filecounter);
fOut = fopen(buffer, "wb");
if (fOut == NULL)
{
result *= -1;
break;
}
size = 0;
}
/* calculate size of data to be read from input file in order to not exceed maxSize */
read = sizeof(buffer);
if ((size + read) > maxSize)
{
read = maxSize - size;
}
/* read data from input file */
read = fread(buffer, 1, read, fIn);
if (read == 0)
{
result *= -1;
break;
}
/* write data to output file */
written = fwrite(buffer, 1, read, fOut);
if (written != read)
{
result *= -1;
break;
}
/* update size counter of current output file */
size += written;
if (size >= maxSize) /* next split? */
{
fclose(fOut);
fOut = NULL;
result++;
}
}
/* clean up */
if (fOut != NULL)
{
fclose(fOut);
}
fclose(fIn);
}
}
}
return (result);
}
int main(void)
{
//segments = sizeFile/SEGMENT + 1;//ensure end of file
//fp1 = fopen(largeFileName, "r");
////if(fp1)
////{
// for(i=0;i<segments;i++)
// {
// accum = 0;
// sprintf(smallFileName, "%s%d.txt", filename, i);
// fp2 = fopen(smallFileName, "w");
// if(fp2)
// {
// while(fgets(line, 1080, fp1) && accum <= SEGMENT)
// {
// accum += strlen(line);//track size of growing file
// fputs(line, fp2);
// }
// fclose(fp2);
// }
// }
// fclose(fp1);
//}
//maxSize =sizeFile/SEGMENT + 1;
//ensure end of file
splitFile();
getch();
printf("\n File splitted Successfully");
return 0;
}