Plumky
Plumky

Reputation: 3

Unexpected end of file on a tar.gz file

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.

Upvotes: 0

Views: 4081

Answers (1)

dvaergiller
dvaergiller

Reputation: 815

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 *.

Upvotes: 1

Related Questions