Bad file descriptor error by working on files - c

C.
bad file descriptor error by working on files.
This is an assignment for college. I need to compress file txt and then to uncompress it. The compress method working fine
and it compresses by the idea that the last binary digit (Msb) is zero always in any ASCII char.
Does anybody know why it happens?
The problem happens when I do fgetc(input_file_8to7) in the uncompress method
The mainly problem is that i get -1 from the 2 fgetc(input_file_8to7) in uncompresd method
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdint.h>
the input for the uncompress is the output of the compress , the input is txt file that conatain the next 2 lines:
A hex dump is a hexadecimal view of computer data, from memory or from a computer file.
***compres method***
void compress8to7(FILE *input,FILE* output8to7)
{
// 0x00 87 00 87 00 87 00 87 ll
uint64_t magic=0x87008700870087ll;
uint64_t inputsize=0;
fwrite(&magic,sizeof (magic),1,output8to7);
fwrite(&inputsize,sizeof(inputsize),1,output8to7);
unsigned char st;
unsigned char st2;
char check;
char check2;
char shift=7;
char shift_st=0;
unsigned char inbfile;
// will contain the resullt of the asked new binary lines comprees
int breakflag=0;
int breakflag2=0;
int cnt=-1;
//this parameter will help to know when we dont need to move 1 back in
the pointer of input file
while(1) {
cnt++;
if (ftell(input)>1 && cnt%7!=0) //
{
fseek(input,-1 ,SEEK_CUR) ;
}
check = fgetc(input);
st=check;
if(check2==EOF){breakflag2=1;}
check2 = fgetc(input);
> //if the length is odd number check2 will get the eof
st2=check2;
if(check==EOF){breakflag=1;}
st2=st2<<shift;
> //move the digit to the right position
bit manipulation
st=st>>shift_st;
shift_st++;
if(shift_st==7)
{shift_st=0;}
shift=shift-1;
if(shift==0)
shift=7;
if(breakflag2!=1)
{inbfile=st2|st;
}else{ inbfile=st; }
fwrite(&inbfile, sizeof(inbfile),1,output8to7);
write to the file
if(feof(input))
{
inputsize= ftell(input);
fseek(output8to7,8,SEEK_SET);
fwrite(&inputsize,sizeof (inputsize),1,output8to7);
// if(breakflag==1)
break;}
}
}
*** uncompress method***
the problem is in this method
void uncompress8to7 (FILE *input_file_8to7 ,FILE *output_file_txt){
char st;
char st2;
char check;
char check2;
char shift2 = 7;
char shift_st = 0;
char shift_helper=7;
char shift_helper2=6;
char sthelper;
char sthelper2;
char inbfile; // will contain the resullt of the asked new binary lines comprees
int breakflag = 0;
int breakflag2 = 0;
int cnt = -1;//this parameter will help to know when we dont need to move 1 back in the pointer of input file
rewind(input_file_8to7);
printf("%d",ftell(input_file_8to7));
fseek(input_file_8to7,16,SEEK_SET);
printf("\n%d",ftell(input_file_8to7));
int a=0;
while(1) {
cnt++;
if(cnt>1) //
{fseek(input_file_8to7,-1 ,SEEK_CUR);}
printf("\n%d",ftell(input_file_8to7));
from that fgetc i get the bad file descriptor erorr
check = fgetc(input_file_8to7);
if(ferror(input_file_8to7)){
perror("eror by perror");
printf("file erorr");}
// printf("\n%d",ftell(input_file_8to7));
st = check;
check2 = fgetc(input_file_8to7);
st2 = check2;
if(cnt<2)
fseek(input_file_8to7,0,SEEK_SET);
if(check2==EOF){
breakflag2 = 1;
}
sthelper2=st2;
sthelper2=sthelper2>>shift_helper2;
st2=st2<<shift2;
st2=st2>>shift2;
sthelper=st;
sthelper=sthelper>>shift_helper;
sthelper=shift_helper<<shift_helper-1;
st=st<<shift_st;// to make all zero after the msb
st=st>>shift_st;// to make all zero after the msb
shift_helper2--;
if(shift_helper==-1)
{shift_helper2=6;}
shift_helper--;
if(shift_helper==-1){
shift_helper=7;
}
shift_st++;
if(shift_st==7)
{shift_st=0;}
shift2=shift2-1;
if(shift2==0)
shift2=7;
if(breakflag2==1)
{break;}
if(cnt%7==0){
inbfile=st;
}else{
inbfile=sthelper|st2;
}
writing to the file
fwrite(&inbfile,sizeof(inbfile),1,output_file_txt);
break the loop when we got to the end of file
if(feof(input_file_8to7))
{ break;}
}
}
***main***
int main(int argc, char **argv) {
char* input=NULL;
char* output8to7=NULL;
input=argv[1];
output8to7=argv[2];
open files
FILE* inputfile = fopen(input, "r");
if(inputfile==NULL)
{
printf("couldnt open input file ");
exit(-1);
}
FILE* file8to7=fopen(output8to7, "wb");
if(file8to7==NULL)
{
printf("couldnt open output file");
printf(output8to7);
exit(-1);
}
compress
compress8to7(inputfile,file8to7);
FILE* file8to7input=fopen("exampleout.bin", "ab");
FILE* output_file=fopen("UNoutput_file2.txt", "wb");
if(output_file==NULL)
{printf("couldnt open output file");
exit(-1);
}
uncompress8to7(file8to7input,output_file);
fclose(output_file);
fclose(file8to7input);
fclose(inputfile);
fclose(file8to7);
return 0;
}

This is the code to open the file:
FILE* file8to7input=fopen("exampleout.bin", "ab");
This opens it as an output file in append mode. You're trying to read from it in the uncompress8to7() function. You need to open it as in input file in read mode. Change that line to:
FILE* file8to7input=fopen("exampleout.bin", "rb");

Related

How to print a substring in C

simple C question here!
So I am trying to parse through a string lets say: 1234567W
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
//pointer to open file
FILE *op;
//open file of first parameter and read it "r"
op = fopen("TestCases.txt", "r");
//make an array of 1000
char x[1000];
char y[1000];
//declare variable nums as integer
int nums;
//if file is not found then exit and give error
if (!op) {
perror("Failed to open file!\n");
exit(1);
}
else {
while (fgets(x, sizeof(x), op)) {
//pounter to get the first coordinate to W
char *p = strtok(x, "W");
//print the first 3 digits of the string
printf("%.4sd\n", p);
}
}
return 0;
My output so far shows: "123d" because of the "%.4sd" in the printf function.
I now need to get the next two numbers, "45". Is there a regex expression I can use that will allow me to get the next two digits of a string?
I am new to C, so I was thinking more like "%(ignore the first 4 characters)(print next 2 digits)(ignore the last two digits)"
input: pic
output: pic
Please let me know.
Thanks all.
printf("Next two: %.2s\n", p + 4); should work.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
//pointer to open file
FILE *op;
//open file of first parameter and read it "r"
op = fopen("TestCases.txt", "r");
//make an array of 1000
char x[1000];
char y[1000];
//declare variable nums as integer
int nums;
//if file is not found then exit and give error
if (!op) {
perror("Failed to open file!\n");
exit(1);
}
else {
while (fgets(x, sizeof(x), op)) {
//pounter to get the first coordinate to W
char *p = strtok(x, "W");
//print the first 3 digits of the string
printf("%.4sd\n", p);
printf("Next two: %.2s\n", p + 4);
}
}
return 0;
}
Side note: I added a missing stdio.h include. Please turn on compiler warnings, since this error would've been caught by them.

How can I carve out one binary file from a concatenated binary

Basically I'm combining two binaries using the "cat" command on Linux.
And I want to be able to separate them again using C
this is the code I got so far
int main(int argc, char *argv[]) {
// Getting this file
FILE *localFile = fopen(argv[0], "rb");
// Naming a new file to save our carved binary
FILE *newFile = fopen(argv[1], "wb+");
// Moving the cursor to the offset: 19672 which is the size of this file
fseek(localFile, 19672, SEEK_SET);
// Copying to the new file
char ch;
while ( ( ch = fgetc(localFile) ) != EOF ) {
fputc(ch, newFile);
}
}
Assuming that you already know where the second file starts. You can proceed as follows. (This is bare minimal)
#include <stdio.h>
#include <unistd.h>
int main()
{
FILE* f1 = fopen("f1.bin", "r");
FILE* f2 = fopen("f2.bin", "w");
long file1_size = 1;
lseek(fileno(f1), file1_size, SEEK_SET);
char fbuf[100];
int rd_status;
for( ; ; ) {
rd_status = read(fileno(f1), fbuf, sizeof(fbuf));
if (rd_status <= 0)
break;
write(fileno(f2), fbuf, rd_status);
}
fclose(f1);
fclose(f2);
return 0;
}
Input File -- f1.bin
1F 2A
Output File -- f2.bin
2A
Please, modify the file names and file sizes according to your example.

source code skipping in C function, every LOC is executed but a few lines of code

I've designed a function in C that takes two files, XORs the contents of the first file with a 10 byte key and puts the result in a separate file. My program is based on enhancing LSB stenography using encryption. The XOR function mentioned above is meant to encrypt the plain text file and generate the cipher text file. The generated cipher text file is then used by another function which encodes it into the image. In this instance the XOR function works as intended, but the problem occurs during decoding. I've designed my program to decode the data from the image and place it in a text file (this will contain the cipher text previously encoded). Now when I use the same XOR function to decrypt the cipher text into plain text in the decoding phase, nothing but the print statements get executed in the function. The program logic is sound as I've tested the logic using a standalone program.
include contains all the function prototypes and the header files required for execution.
XOR Function:
#include<header.h>
void enc(FILE *source, FILE *destination)
{
char text_buff, key[11];
int i;
printf("\nenter the key (max lenght 10): ");
for(i = 0; ((key[i] = getchar()) != '\n'); i++);
key[i] = '\0';
char new;
printf("\nThe string obtained: \t");
i = 0;
while((text_buff = fgetc(source)) != EOF)
{
new = text_buff ^ key[i];
fputc(new, destination);
i++;
printf("%c",new);
if(i==10)
i=0;
}
printf("\nsuccessful\n");
}
Main function:
#include <header.h>
int main(int argc, char *argv[])
{
//declaring variables and file pointers
char *option = argv[1];
FILE *source; //source bmp image
FILE *secretfile; //secret text file
FILE *newbmp; //new bmp image
FILE *secretmsg; //decrypted data text file
FILE *plain_text; //Plain text1
FILE *result_text; //Plain text2
//encode operations
if(argc == 6)
{
//if argument passed is '-e'
if(!strcmp(option, "-e"))
{
if((plain_text = fopen(argv[2], "r")) == NULL)
{
FILE_ERROR(argv[2]);
EXIT;
}
if((source = fopen(argv[3], "r")) == NULL)
{
FILE_ERROR(argv[3]);
EXIT;
}
if((secretfile = fopen(argv[4], "r+")) == NULL)
{
FILE_ERROR(argv[4]);
EXIT;
}
if((newbmp = fopen(argv[5], "w")) == NULL)
{
FILE_ERROR(argv[5]);
EXIT;
}
enc(plain_text,secretfile);
encodeImg(source, secretfile, newbmp);
}
else
{
INVALID_ARGUMENTS;
EXIT;
}
}
//decode operations
else if(argc == 5)
{
//if argument passed is '-d'
if(!strcmp(option, "-d"))
{
if((newbmp = fopen(argv[2], "r")) == NULL)
{
FILE_ERROR(argv[2]);
EXIT;
}
if((secretmsg = fopen(argv[3], "r+")) == NULL)
{
FILE_ERROR(argv[3]);
EXIT;
}
if((result_text = fopen(argv[4], "w")) == NULL)
{
FILE_ERROR(argv[4]);
EXIT;
}
decodeimg(newbmp, secretmsg);
enc(secretmsg,result_text);
fclose(secretmsg);
fclose(result_text);
}
else
{
INVALID_ARGUMENTS;
EXIT;
}
}
//if no other argument is passed
else
{
INVALID_ARGUMENTS;
EXIT;
}
}
Header file contents:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "errorHandle.c"
//encode image main function
void encodeImg(FILE *source, FILE *secretfile, FILE *newbmp);
//size of image file(called from encodeImg)
int sizeImgFile(FILE *s1);
//size secret text file(called from encodeImg)
int sizeTxtFile(FILE *s2);
//string encode(called from encodeImg)
void stringEncode(char *String, FILE *source, FILE *newbmp);
//get character bits(called from stringEncode)
int get_bit(char byte, int bit);
//size encode(called from encodeImg)
void sizeEncode(int val, FILE *source, FILE *newbmp);
//secret encode(called from encodeImg)
void secretEncode(FILE *source, FILE *secretfile, FILE *newbmp);
//decode image main function
void decodeimg(FILE *newbmp, FILE *secretmsg);
//size decode(called from decodeimg)
void sizeDcp(FILE *newbmp, int *size);
//string decode(called from decodeimg)
void strDcp(FILE *newbmp, char *str, int size);
//secret decode(called from decodeimg)
void secretDcp(FILE *newbmp, FILE *secretmsg, int secretSize);
//Xor encryption(called from xor)
void enc(FILE *source, FILE *destination);
#define INVALID_ARGUMENTS printf("./a.out: missing file(s) operand\nTry - ./a.out <-e or -d> <plain text> <source bmp image> <secret text file> <new bmp image>\n")
#define EXIT exit(1)
#define FILE_ERROR(file_name) printf("couldn't open file: %s\n", file_name)
#define FILE_SIZE_ERROR printf("cannot perform operation: size of secret message is greater than the imagefile\n")
while((text_buff = fgetc(source)) != EOF)
The fgetc function returns an int. But you chop it to a char, assign that to text_buff, and then compare that to EOF. That won't work. You are supposed to compare the return value of fgetc to EOF, not any other value.
There are two possibilities. Either some value of char maps to EOF or no value of char maps to EOF. If some value of char maps to EOF, then when you read that character in the middle of the file, you'll treat at as the end of the file. If no value of char maps to EOF, then you'll never detect the end of the file.
So this can't possibly work right.

File is getting created but data is not pushed into the file

I have written this C program, where it takes system calls as input like ps -f or ls /tmp, etc and output from the system call is pushed to a file and then from the file it reads and displays the output.
Here output file is getting created /tmp/j but there is no data present inside it. Can some one please help me with this issue and Thanks in advance.
My program.
#include<stdio.h>
#include<sys/syscall.h>
#include <stdlib.h>
main()
{
enum msgtype {PROCESS_LIST_REQUEST=1, PROCESS_LIST_RESPONSE, DIRECTORY_LIST_REQUEST, DIRECTORY_LIST_RESPONSE, ERROR_REQUEST};
struct head{
int version;
int msg_length;
int header_length;
enum msgtype msg_type;
char data;
char *reqtype;
};
struct head *buf;
char buff[10];
buf = malloc((sizeof(struct head)));
buf->reqtype=malloc(40);
char req[10];
printf("type ps -f on the console \n");
fgets(req, sizeof(req),stdin);
buf->reqtype = req;
printf("%s" , buf->reqtype);
snprintf(buff, sizeof(buff), "%s>/tmp/j", buf->reqtype);
printf("%s \n",buff);
system(buff);
{
FILE *fp;
char c;
fp = fopen("/tmp/j", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else
{
do {
c = getc(fp); /* get one character from the file*/
putchar(c); /* display it on the monitor*/
} while (c != EOF); /* repeat until EOF (end of file) */
}
fclose(fp);
}
}
There are a couple of errors in your code.
1) Allocate some memory greater than 10 for your buff. 10 is not enough. Your string is exceeding the size of 10. I made it 20 in my machine and checked.
2) fgets(req, sizeof(req),stdin); is reading a \n at the end of the string. Delete the last character. req[strlen(req) - 1] = '\0';
See this for man page of fgets

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);
}
}
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));
i got it.problem is my struct definiton. i gotta define unsigned char numchar, not int numchar!. finally. thanks your help my friend.

Resources