Reputation: 93
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
Reputation: 9850
When you write out the filename and file sizes, you are writing them as int
s, 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 char
s, 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 char
s:
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
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