ccc
ccc

Reputation: 93

archive file extracting in c

I'm just trying write c code like tar command in unix. my problem is extracting of archive file. you will see close end of file comment "problem here" . im trying extract archive file. this is binary file. first byte is give us number of files. second byte is first file's names length. example "file.c" length is 6. third byte is first file's name string.so "file.c". and start second file's informations......going last file's informations. so finally start each file contain after and after.

archive file = N-I1-I2....-Ik-B1-B2....-Bk I = L-S-Z

N is number of files.1 byte I is information about files. B is file contains.

L is length of filename. 1 byte S is filename string Z is file size

so , i can read N,L,S from binary file but not Z! i couldnt find it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFSIZE 4096



struct stat st;

struct inputfiles{
  int numchar;
  char *filename;
  unsigned int filesize;
}file[255];

struct outputfiles{
  int num_char;
  char *file_name;
  unsigned int file_size;
}outfile[255];


int main(int argc,char *argv[])
{

  int copyfile(char *,char *);

  int i,j,k,m,h;
  int input_file,output_file;
  int fd;  
  int infile,outfile,arcfile;
  char buffer[BUFSIZE];
  char n;
  char flength;
 unsigned int file_len;
  char *f_name;

  char tempsize;
 unsigned  int sizeoffile;

  ssize_t nread,xread;




  input_file=argc-3;

  if(argc<=2)
    {
      fprintf(stderr,"Error: you must enter least 3 argument\n");
    exit(1);
    }
  else if(strcmp(argv[1],"-c")==0)
    {
      if((outfile=open(argv[2],O_WRONLY | O_CREAT,0644))==-1)
      {
      fprintf(stderr,"Error: Archive file can't open %s\n",argv[2]);
       remove(argv[2]);
      exit(1);
      }

      /*** write number of files into the archive file ***/
        write(outfile,(char*)&input_file,sizeof(char)); //UPDATED 


      j=0;    
      for(i=3;i<argc;i++)
    {
         file[j].numchar=strlen(argv[i]);


         /**** write filename size into archive file ****/ 
         write(outfile,(char*)&file[j].numchar,sizeof(char)); //UPDATED 



         file[j].filename=malloc(sizeof(file[j].numchar));
         strcpy(file[j].filename,argv[i]);

         /**** write filename into the archive file ****/
         write(outfile,file[j].filename,file[j].numchar);

         stat(argv[i],&st);
         file[j].filesize=st.st_size;     

         /**** write size of file into the archive file ****/
         write(outfile,&file[j].filesize,sizeof(int));               //UPDATED  HERE IS 4 BYTES

         j++;
    }   

      for(m=3;m<argc;m++)
    {
      if((infile=open(argv[m],O_RDONLY))==-1)
        {
          fprintf(stderr,"Error: File can't open %s\n",argv[m]);
          exit(1);
        }

      while((nread=read(infile,buffer,BUFSIZE))>0)
        {
          if(write(outfile,buffer,nread)<nread)
        {
          fprintf(stderr,"Error : input file size too much\n");
        }

          if(nread==-1)
        {
          fprintf(stderr,"Error occurred while reading.\n");
          exit(1);
        }
        }

    }
    }


/******* Extracting Archive File  *********/ 


  else if((strcmp(argv[1],"-x")==0))
    {
      if(argc!=3)
    {
      fprintf(stderr,"Error : you must enter 3 argument for extract \n");
      exit(1);
    }
      else
    {
     if((arcfile=open(argv[2],O_RDONLY))==-1)
       {
          fprintf(stderr,"Error:File can't open %s\n",argv[2]);
          remove(argv[2]);
          exit(1);
        }

     read(arcfile,&n,sizeof(char)); //read first byte of archive file
     output_file=(int)n;  // get number of output files
     printf("there is a %d files.\n",output_file);
     for(m=0;m<n;m++)   //loop for get information about each output file
       {
         read(arcfile,&flength,sizeof(char)); //read second byte
         file_len=((int)flength);   //get filename length


         f_name=malloc(file_len+1);   //malloc for filename
         read(arcfile,f_name,file_len);  //read size of filename length bytes and get filename string

         read(arcfile,&tempsize,sizeof(char)); //read size of file  <--- problem here
         sizeoffile=(int)tempsize;

     printf("file name length: %d\n",file_len);    
     printf("file name: %s\n",f_name);
     printf("file size: %d\n",sizeoffile);
       }

    }

    }
  else {
    fprintf(stderr,"invalid command line\n");
    exit(1);
  }
}

Upvotes: 0

Views: 838

Answers (2)

Xymostech
Xymostech

Reputation: 9850

When you write out the filename and file sizes, you are writing them as ints, taking up 4 bytes:

write(outfile,&file[j].numchar,sizeof(file[j].numchar) /* = sizeof(int) */);
...
write(outfile,&file[j].filesize,sizeof(file[j].filesize) /* = sizeof(int) */);

but when you read them back out, you expect them to be chars, taking up a single byte:

read(arcfile,&flength,sizeof(char));
...
read(arcfile,&tempsize,sizeof(char));

Try either writing out the size as a single byte, or better, just use 4 bytes for the filename and file sizes. (better because then you don't have to worry about files and filenames being too long)


To write out the file name and lengths as single bytes, cast them to chars:

char to_write = file[j].numchar;
write(outfile, &to_write, sizeof(char));
...
to_write = file[j].filesize;
write(outfile, &to_write, sizeof(char));

Upvotes: 1

ccc
ccc

Reputation: 93

i got it.problem is my struct definiton. i gotta define unsigned char numchar, not int numchar!. finally. thanks your help my friend.

Upvotes: 0

Related Questions