C Systems Program - Read/Write Issues During Copy - c

I am coding up a C program that extracts from a standard UNIX archive ar and creates the files it stores.
Here is an example of what an ar looks like if I open it in vim:
!<arch>
yo 1382105439 501 20 100644 10 `
test1 lol
yo2 1382105444 501 20 100644 10 `
test2 lol
...where "test1 lol" and "test2 lol" are the contents of each file, "yo" and "yo2" are two different file names, and the rest is metadata stored in a format corresponding to the standard ar.h (read more on it here: http://www.lehman.cuny.edu/cgi-bin/man-cgi?ar.h+3)
Anyway, I am still in the process of writing out the function but here is what I have so far:
static void extract_files (int argc, char *argv[])
{
int fd;
int new_file_fd;
int num_read = 0;
int new_file_size;
struct ar_hdr current_header;
char name_buffer[16];
char date_buffer[12];
char uid_buffer[6];
char gid_buffer[6];
char mode_buffer[8];
char size_buffer[10];
char fmag_buffer[2];
// grab the fd #
fd = open(argv[2], O_RDWR | O_CREAT, 0666);
// go to the first header
lseek(fd, SARMAG, SEEK_CUR);
// store the number of bits read in a struct current_header
// until its size equal to the size of the entire
// header, or in other words, until the entire
// header is read
while ((num_read = read(fd, (char*) &current_header,
sizeof(struct ar_hdr))) == sizeof(struct ar_hdr))
{
// scans the current string in header and stores
// in nameStr array
sscanf(current_header.ar_name, "%s", name_buffer);
sscanf(current_header.ar_date, "%s", date_buffer);
sscanf(current_header.ar_uid, "%s", uid_buffer);
sscanf(current_header.ar_gid, "%s", gid_buffer);
int mode;
sscanf(current_header.ar_mode, "%o", &mode);
sscanf(current_header.ar_size, "%s", size_buffer);
int size = atoi(size_buffer);
sscanf(current_header.ar_fmag, "%s", fmag_buffer);
// Create a new file
new_file_fd = creat(name_buffer, mode);
// Grab new file size
new_file_size = atoi(size_buffer);
int io_size; // buffer size
char buff[size];
int read_cntr = 0;
// from copy.c
while ((io_size = read (fd, buff, new_file_size)) > 0)
{
read_cntr++;
if (read_cntr > new_file_size)
break;
write (new_file_fd, buff, new_file_size);
}
close(new_file_fd);
printf("%s\n", name_buffer);
printf("%s\n", date_buffer);
printf("%s\n", uid_buffer);
printf("%s\n", gid_buffer);
printf("%s\n", mode_buffer);
printf("%s\n", size_buffer);
printf("%s\n", fmag_buffer);
/* Seek to next header. */
lseek(fd, atoi(current_header.ar_size) + (atoi(current_header.ar_size)%2), SEEK_CUR);
}
}
The issue I am having lies in the second while loop in the above code:
// from copy.c
while ((io_size = read (fd, buff, new_file_size)) > 0)
{
read_cntr++;
if (read_cntr > new_file_size)
break;
write (new_file_fd, buff, new_file_size);
}
For some reason, the files written in this while loop don't run to the length specified by write. The third argument for the standard read()/write() should be the number of bytes to write. For some reason though, my code results in the entire archive being read in and written into the first file.
If I open up the resulting "yo" file, I find the entire archive file has been written to it
test1 lol
yo2 1382105444 501 20 100644 10 `
test2 lol
instead of terminating after reading 10 bytes and giving the expected outcome "test1 lol".
I can also confirm that the "new_file_size" value is indeed 10. So my question is: what am I reading wrong about this while loop?
Note: Expected input would be a command line argument that looks something like:
./extractor.c -x name_of_archive_file
The only relevant information I think I need to deal with in this function is the name of the archive file which I get the fd for at the beginning of extract_files.
Added:
Misc -- the output from when this is run:
yo
1382105439
501
20
X
10
`
As you can see, it never sees the yo2 file or prints out its header because it gets written to "yo" before that can happen...because of this stray while loop :(

You read a value, size_buffer, and assign it to size and new_file_size, you also create a buffer[size] of that same size,
int size = atoi(size_buffer);
sscanf(current_header.ar_fmag, "%s", fmag_buffer);
//...
new_file_size = atoi(size_buffer);
//...
char buff[size];
Read returns a ssize_t count of bytes in range [0..new_file_size], which you set into io_size, realize that read(2) may return < new_file_size bytes, which is why you need the while loop. So you need to write everything you have read, until you reach your write limit. I have made some comments to guide you.
// from copy.c
while ((io_size = read (fd, buff, new_file_size)) > 0)
{
read_cntr++;
//perhaps you mean read_cntr += io_size;
//you probably mean to write io_size bytes here, regardless
//write(new_file_fd, buff, io_size);
if (read_cntr > new_file_size) //probably you want >= here
break;
//you may have broke before you write...
write (new_file_fd, buff, new_file_size);
}
A more typical idiom for this copy would be something where you pick a read/write buffer size, say 4*1024 (4K), 16*1024 (16K), etc, and read that blocksize, until you have less than that blocksize remaining; for example,
//decide how big to make buffer for read()
#define BUFSIZE (16*1024) //16K
//you need min(
#define min(x,y) ( ((x)<(y)) ? (x) : (y) )
ssize_t fdreader(int fd, int ofd, ssize_t new_file_size )
{
ssize_t remaining = new_file_size;
ssize_t readtotal = 0;
ssize_t readcount;
unsigned char buffer[BUFSIZE];
for( ; readcount=read(fd,buffer,min(sizeof(buffer),remaining)); )
{
readtotal += readcount;
if( readcount > remaining ) //only keep remaining
readcount = remaining;
write( ofd, buffer, readcount);
remaining -= readcount;
if( remaining <= 0 ) break; //done
}
return readtotal;
}
Try this,
#include<stdio.h>
#include<stdlib.h>
void usage(char*progname)
{
printf("need 2 files\n");
printf("%s <infile> <outfile>\n",progname);
}
//decide how big to make buffer for read()
#define BUFSIZE (16*1024) //16K
//you need min(
#define min(x,y) ( ((x)<(y)) ? (x) : (y) )
ssize_t fdreader(int fd, int ofd, ssize_t new_file_size )
{
ssize_t remaining = new_file_size;
ssize_t readtotal = 0;
ssize_t readcount;
unsigned char buffer[BUFSIZE];
for( ; readcount=read(fd,buffer,min(sizeof(buffer),remaining)); )
{
readtotal += readcount;
if( readcount > remaining ) //only keep remaining
readcount = remaining;
write( ofd, buffer, readcount);
remaining -= readcount;
if( remaining <= 0 ) break; //done
}
return readtotal;
}
int main(int argc,char**argv)
{
int i=0; /* the infamous 'i' */
FILE*infh;
FILE*outfh;
if( argc < 3 )
{
usage(argv[0]);
return 0;
}
printf("%s %s\n",argv[1],argv[2]); fflush(stdout);
if( !(infh=fopen(argv[1],"r")) )
{
printf("cannot open %s\n",argv[2]); fflush(stdout);
return(2);
}
if( !(outfh=fopen(argv[2],"w+")) )
{
printf("cannot open %s\n",argv[3]); fflush(stdout);
return(3);
}
int x = fdreader(fileno(infh), fileno(outfh), 512 );
return 0;
}

Your while() loop should probably have braces ({ ... }) after it, otherwise you're just incrementing read_cntr without doing anything else.

Related

Copy Function in C not creating matching Checksums

I written a simple copy program that copies a file and generates an MD5, It runs and generates the MD5 correctly.
However when verifying the file generated by the copy function it does not match the source MD5. I can't see any reason for this in my code, can anyone help?
#include <stdio.h>
#include <openssl/md5.h>
#include <assert.h>
#define BUFFER_SIZE 512
int secure_copy(char *filepath, char *destpath);
int main(int argc, char * argv[]) {
secure_copy(argv[1], argv[2]);
return 0;
}
int secure_copy(char *filepath, char *destpath) {
FILE *src, *dest;
src = fopen(filepath, "r");
assert(src != NULL);
dest = fopen(destpath, "w");
assert(dest != 0);
MD5_CTX c;
char buf[BUFFER_SIZE];
ssize_t bytes, out_writer;
unsigned char out[MD5_DIGEST_LENGTH];
MD5_Init(&c);
while((bytes = fread(buf, 1, BUFFER_SIZE, src)) != 0) {
MD5_Update(&c, buf, bytes);
out_writer = fwrite(buf, 1, BUFFER_SIZE, dest);
assert(out_writer != 0);
}
MD5_Final(out, &c);
printf("MD5: ");
for (int i=0; i < MD5_DIGEST_LENGTH; i++)
{
printf("%02x", out[i]);
}
printf("\n");
fclose(src);
fclose(dest);
return 0;
}
Output
$ ./md5speed doc.txt /home/doc.txt
MD5: 4c55e4b9185eece3cc000c4023f8f6fe
when verifying the copied file with md5sum I get a completely different hash.
md5sum doc.txt
29cb4da30c3e28fdb81463b5f0a76894 doc.txt
Though the file still opens and content is uncorrupted.
regarding:
while((bytes = fread(buf, 1, BUFFER_SIZE, src)) != 0)
and
out_writer = fwrite(buf, 1, BUFFER_SIZE, dest);
on the last read, the amount read can be less than BUFFER_SIZE so should always use bytes variable for the number of bytes to write.
Also, certain errors can occur when calling fread() and/or fwrite() Such errors are indicated by negative values (and/or values less than the 3rd parameter to those functions) in the returned variables (bytes, outwriter). The code, to be robust, must be checking those values and handling any errors that occur, including EOF
As stated in comments, changing the fwrite function to use bytes as opposed to BUFFER_SIZE combined with changing file operations mode "rb" and "wb" to binary.

Can't print an int to a file

I'm trying to print an int array on a file but it is giving me an error.
write_error:Bad address.
My int array is something like :
1 2 3 4 5 6 7 8 9
And I want to print it on a file as follows :
1 2 3
4 5 6
7 8 9
This is the code I'm using :
void printToFile(int listBoard[]) {
int file_write;
char buffer[100];
char buffer2[10];
if ((file_write = open("./board.txt", O_WRONLY | O_CREAT | O_TRUNC, 0700)) < 0) {
err_sys("error output file");
}
if (write(file_write, snprintf(buffer2, 10, "%d",listBoard[2]), 18) != 18){
err_sys("write_error");
}
if (close(file_write) != 0){
err_sys("error close write");
}
}
I also tried (char) but it converts the int to the ascii char.
Could you tell me what I'm missing?
Edit
My file output is :
3#\00\00펈㰙\00ጠ
Code edited :
void printToFile(int listBoard[]){
int file_write;
char buffer[100];
int value;
int cont = 0;
char buffer2[10];
if ((file_write = open("./board.txt", O_WRONLY | O_CREAT | O_TRUNC, 0700)) < 0) {
err_sys("error output file");
}
int len = snprintf(buffer2, 10, "%d", listBoard[2]);
if (write(file_write, buffer2, len) != len) {
err_sys("write_error");
}
if (close(file_write) != 0) {
err_sys("error close write");
}
}
Output file :
3
Last edit
This is how I did now to print it as the output that I want
if ((file_write = open("./board.txt", O_WRONLY | O_CREAT | O_TRUNC, 0700)) < 0) {
err_sys("error output file");
}
for (int index = 0; index < SIZE_BOARD; index++) {
if (cont == 3) {
int len = snprintf(buffer2, 1, "%d \n", ' ');
if(write(file_write, buffer2, len) != len) {
err_sys("write_error");
cont=0;
}
}
int len = snprintf(buffer2, 10, "%d ", listBoard[index]);
if (write(file_write, buffer2, len) != len) {
err_sys("write_error");
cont++;
}
}
if(close(file_write) != 0) {
err_sys("error close write");
}
But it is not doing the \n correctly. What I'm missing?
The definition of write is as follows:
ssize_t write(int fd, const void *buf, size_t count);
The definition of snprintf is as follows:
int snprintf(char *str, size_t size, const char *format, ...);
Now you're feeding snprintf to where write is expecting void *buf. i.e. the address to where the data is.
So you'll have to do
snprintf(buffer2, 10, "%d", listBoard[2]);
then
write(file_write, buffer2, 18);
EDIT:
That will fix the syntax error. Now semantically you can see that you're writing 10 bytes to buffer2 but you're writing 18 to the file. This will fill the file with junk. So i suggest.
int len = snprintf(buffer2, 10, "%d", listBoard[2]);
write(file_write, buffer2, len);
EDIT 2:
int len = snprintf(buffer2, 1, "%d \n", ' ');
First off your format specifier has 3 bytes while you're only writing 1 byte to the buffer2. Second, why is your argument ' ' when you're supposed to give the listBoard[n]?
Use dprintf() to write formatted strings to files:
dprintf(file_write, "%d", listBoard[2]);
dprintf will handle all the write stuff for you, so this is the only call you need with open and close.
dprintf is the fprintf for file descriptors. More informations here: https://linux.die.net/man/3/dprintf
The snprintf (and family) functions returns an integer.
You use this integer in the write call as a pointer to a buffer. That will lead to undefined behavior.
Call snprintf separately, and then pass buffer2 as the second argument. And use strlen to get the actual length of the string in buffer2, not hard-code the magic number 18 which will lead to reading from out-of-bounds and another case of UB.
First of all snprintf returns an integer that is the number of chars that would have been written if the string were not truncated (as you can read on the snprintf manual)
you cannot then use it in the write command. You can then use:
if ( snprintf(buffer2, 10,"%d",listBoard[2]) >= 10 ) {
/* handle truncation error*/
}
if(write(file_write,buffer2,18)!=18){
err_sys("write_error");
Anyway since buffer2 is maximum 10 characters why do you expect to write 18 bytes?
Other possible error: buffer2 should be at least of 10 + 1 byte for null termination.
You never specify that you must use raw file descriptors, so let's port your code up one level to C's standard library's FILE abstraction. It's easier to work with.
void printToFile(const int listBoard[]) {
FILE * const out = fopen("board.txt", "wt");
if (out == NULL) {
err_sys("error output file");
}
for(int j = 0; j < 3; ++j) {
for (int i = 0; i < 3; ++i)
fprintf(out, "%d ", listBoard[3 * j + i]);
fprintf(out, "\n");
}
fclose(out);
}
Note that this uses loops to iterate over the elements of the board array, this seemed to be missing from your original code and part of the problem you had with it.
This prints:
1 2 3
4 5 6
7 8 9
There's a trailing space on each line due to me being lazy, but hopefully that's fine. Also I omitted some inner error checking.

Using popen("ls -la") produces strange result

I wrote some C code for it to get the result of an "ls -la" command using popen and write the result into an C. The code looks like this:
unsigned int ls(char *destination, const char *username, const char *relative_path)
{
printf("LS IMP\n");
//if(!username || !relative_path) return -1;
FILE *ls_pipe = NULL;
unsigned long ls_pipe_size = -1;
const char ls_command[] = "ls -la ";
char ls_path[255] = "/home/";
char ls_full_command[255];
char buffer[255];
bzero(buffer, 255);
char *entries = NULL;
bzero(ls_full_command, 255);
strcat(ls_path, username);
strcat(ls_path, relative_path);
strcat(ls_full_command, ls_command);
strcat(ls_full_command, ls_path);
printf("AFTER CATS\n");
ls_pipe = popen(ls_full_command, "r");
if(ls_pipe == NULL) return -1;
printf("Pipe ok!");
fseek(ls_pipe, 0, SEEK_END);
ls_pipe_size = ftell(ls_pipe);
rewind(ls_pipe);
printf("Filesize: %lu\n", ls_pipe_size);
int i;
for(i = 0; i < 100; i++)
{
fread(buffer, 1, 255, ls_pipe);
printf("%s", buffer);
}
//entries = (char*) malloc(sizeof(char) * ls_pipe_size);
//if(entries == NULL) return -1;
printf("Entries ok!\n");
//if(ls_pipe_size != fread(destination, sizeof(char), ls_pipe_size, ls_pipe)) return -1;
fclose(ls_pipe);
return strlen(destination);
}
The problem is the size of the pipe is huge (?) and in the result after the proper result three entries start to appear non-stop for like infinity.
Is there any way of reading from it without knowing the exact number of lines of the result using something like another popen with wc -l?
Thanks
P.S there are some modifications in the code when i was trying to test what's going wrong and the malloc didn't work because of the insane size of the pipe.
You can't seek on a pipe — period. Any value you get back from ftell() is immaterial or erroneous. You can't rewind a pipe because you can't seek on a pipe. You can only read data once from a pipe.
So, you need to redesign the code to read an indefinite amount of data.
Here's some reasonably working code — but I needed to adapt it to Mac OS X and my machine, so instead of /home/ it uses /Users/, and the call to ls() uses my user name. The code properly handles buffers full of data that do not end with a null (listing about 570 lines of output for my bin directory). I've left the interface to ls unchanged although it almost doesn't use destination and returning the length of destination is otherwise unrelated to what it is doing. It also uses pclose() to close the pipe. Using pclose() avoids leaving zombies around and returns the exit status of the executed program where fclose() will not.
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static unsigned int ls(char *destination, const char *username, const char *relative_path)
{
printf("LS IMP\n");
assert(destination != 0 && username != 0 && relative_path != 0);
const char ls_command[] = "ls -la ";
char ls_path[255] = "/Users/";
char ls_full_command[255];
snprintf(ls_full_command, sizeof(ls_full_command), "%s %s%s/%s",
ls_command, ls_path, username, relative_path);
FILE *ls_pipe = popen(ls_full_command, "r");
if (ls_pipe == NULL)
return -1;
printf("Pipe ok!\n");
char buffer[255];
int nbytes;
while ((nbytes = fread(buffer, 1, 255, ls_pipe)) > 0)
printf("%.*s", nbytes, buffer);
putchar('\n');
printf("Entries ok!\n");
pclose(ls_pipe);
return strlen(destination);
}
int main(void)
{
unsigned int length = ls("/", "jleffler", "bin");
printf("ls() returned %u\n", length);
return(0);
}

C reading a writing files

The program I wrote gets the size of one file, reads partSize amount of bytes from that file and writes partSize amount of bytes to a newly created file. The problem is that it only works for small text files. If I try to run the program with text file of a few hundred lines or a picture I get a segmentation fault and significantly less than partSize bytes are stored to the new file.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
int main()
{
int createDescriptor;
int openDescriptorOriginal;
int closeCreateDescriptor;
// char fileNameOriginal[] = "picture.jpg";
char fileNameOriginal[] = "myFile.txt";
int parts;
int partSize;
parts=2;
int bytesRemaining;
int partNumber;
char BUFFER[512];
int readDescriptor;
int buffer[1];
oid *pbuffer = &buffer;
int bytes, infile, outfile;
if ((openDescriptorOriginal = open(fileNameOriginal, O_RDONLY )) == -1)
{
printf("Error opening %s", fileNameOriginal);
exit(EXIT_FAILURE);
}
struct stat buf;
int r = fstat(openDescriptorOriginal, &buf);
if (r)
{
fprintf(stderr, "error: fstat: %s\n", (char *) strerror(errno));
exit(1);
}
int originalFileSize = buf.st_size;
printf("The file is %.9f bytes large.\n",(double)originalFileSize);
partSize = ((originalFileSize + parts) - 1)/parts;
printf("Part size: %.9f bytes large\n",(double)partSize);
umask(0000);
//create and open new file
if ( (outfile = open("NewPicture.jpg", O_CREAT|O_WRONLY,0777))==-1 )
{
printf("ERROR %s\n", "NewPicture.jpg");
}
ssize_t count, total;
total = 0;
char *bufff = BUFFER;
while (partSize) {
count = read(openDescriptorOriginal, bufff, partSize);
if (count < 0) {
break;
}
if (count == 0)
break;
bufff += count;
total += count;
partSize -= count;
}
write (outfile, BUFFER, total);
printf("\n");
return 0;
}
You are using buffer with 512 bytes only.
BUFFER[512];
if the content in that file goes beyond this limit seg fault will occurs.
Your buffer is too small. You need a larger buffer variable. If your file size is more than 512 bytes you will have segfault.
Ideally, you should read from the file in fixed chunks. That is, read maybe 30-40 or a constant number of characters in every read and then write it to the new file. Repeat until the complete file has been read.
count = read(openDescriptorOriginal, bufff, partSize); In this line 3rd argument is wrong,
In your code you have defined char BUFFER[512]; use BUFFER to read from file just 511 bytes at a time.
count = read(openDescriptorOriginal, BUFFER, 512);
Reason why not working with big likes:
If partSize > then 512 then there may be buffer overrun(buffer overflow) happen. that's why your does not work for large files. Because the read() function shall attempt to read partSize bytes from the file associated with the open file descriptor openDescriptorOriginal, fildes, into the buffer pointed to by BUFFER that is just of 512 bytes long. This buffer overrun is cause of segmentation fault in your program.
If file size is small then code will work.
I have corrected your code some extend:
ssize_t count=0, total=0;
total = 0;
char *bufff = calloc(partSize+1, sizeof(char));
char *b = bufff;
while (partSize > 0) {
count = read(openDescriptorOriginal, b, 512);
if (count < 0) {
break;
}
if (count == 0)
break;
b = b + count;
total = total + count;
partSize = partSize - count;
}
write (outfile, bufff, total);
close(openDescriptorOriginal);
close(outfile);
this here makes no sense
partSize = ((originalFileSize + parts) - 1)/parts;
you have initialized parts to two then you add two to the original file size and subtract one and then divide with two again even though at the end of the day your buffer size is 512?
what you need to do is to use the buffer size when reading from the file and checking how many bytes were actually read, this value you subtract from the original file size, repeat until the actual read bytes is smaller than buffer size and/or when original file size is 0.
also it would probably be better if you use file buffered I/O i.e. fopen/fread/fwrite/fclose - if you do not have any special reason why you want to use unbuffered I/O.

Unable to copy the contents of file to a buffer

Operating System Used:Ubuntu 11.04
Compiler Used: GCC
Program related files:Git Hub Link
I'm trying a implement program which will do a job, same as that of CPP (The C preprocessor) when I compile a .c file.
In this particular code Copy_file_to_buf function not copying the whole file into the buffer.
Acutal size of the is 117406C,but ftell in the copy_file_to_buf function showing it as 114689.
EDIT:
There is no data loss when I copied the contents of dummyfile to a buffer using same program but I've written copy_file_to_buf program seperately in temp.c file.
temp.c
#include<stdio.h>
main(int argc,char **argv)
{
FILE *inputFile;
int sizeofFile, rc;
char *source_buf;
fprintf(stderr, "In Copy_file_to_buf\n");
sleep(1);
inputFile=fopen(argv[1],"r");
if (!inputFile) {
fprintf(stderr, "Oops, failed to open inputfile \"%s\"\n", argv[1] );
return NULL;
}
fseek(inputFile,0,SEEK_END);
sizeofFile=ftell(inputFile);
fseek(inputFile,0,SEEK_SET);
source_buf=calloc(1,1+sizeofFile);
rc = fread(source_buf,sizeofFile,1,inputFile);
/* now check rc */
fprintf(stderr, "Size of the file=%d; fread returned %d.\n", sizeofFile, rc);
//sleep(5);
fclose(inputFile);
source_buf[sizeofFile] = 0;
puts(source_buf);
return source_buf;
}
Looks like the fseek() and ftell aren't working as expected for the below code.
puts("Copying dummyfile contents");
test_buf=Copy_file_to_buf("dummyfile");
puts(test_buf);
Filename: preprocessor.c
#include"myheader.h"
/* agrv[1]=preprocessor
* argv[2]=test.c
*
* Program on PREPROCESSOR
*
* Steps:
* 1.Removal of comments.
* 2.Inclusion of headerfiles.
* 3.Macro substitution.
* a.function like arguments
* b.Stringification
* c.Concatenation
* 4.Conditional compilation
* a.#Ifdef
* b.#If
* c.#defined
* d.#Else
* e.#Elif
*/
int
main(int argc, char *argv[])
{
char *source_buf,*subBuf,*rmc_buf,*test_buf;
char **main_header_names,**sub_header_names;
int main_header_count,sub_header_count;
source_buf=(char *)Copy_file_to_buf(argv[1]);//...
rmc_buf=removeComments(source_buf);//...
main_header_names=(char **)getMainHeaderNames(rmc_buf);//...
source_buf=(char *)Copy_file_to_buf(argv[1]);//...
rmc_buf=removeComments(source_buf);//...
main_header_count=mainHeaderCounter(rmc_buf);//...
printf("Main Header Count=%d",main_header_count);//...
includeHeaders(main_header_names,main_header_count);
subBuf=(char *)Copy_file_to_buf("pre.i");//...
sub_header_names=(char **)getSubHeadersNames(subBuf);//...
subBuf=(char *)Copy_file_to_buf("pre.i");//...
sub_header_count=subHeadersCounter(subBuf);//...
WriteSubHeadersToFile(sub_header_count,sub_header_names,"dummyfile");//...
puts("Copying dummyfile contents");
test_buf=Copy_file_to_buf("dummyfile");
puts(test_buf);
/*test_buf=removeComments(test_buf);
puts(test_buf);
sub_header_names=(char **)getSubHeadersNames(test_buf);
test_buf=(char *)Copy_file_to_buf("dummyfile");
sub_header_count=subHeadersCounter(test_buf);
WriteSubHeadersToFile(sub_header_count,sub_header_names,"dummyfile2");
printf("Line:%d File:%s",__LINE__,__FILE__);
*/
return 0;
}
Filename:CopyFile.c
#include"myheader.h"
//Copying input file data into source_buf
char * Copy_file_to_buf(char *fileName)
{
FILE *inputFile;
int sizeofFile;
char *source_buf;
puts("In Copy_file_to_buf");
inputFile=fopen(fileName,"r");
fseek(inputFile,0,2);
sizeofFile=ftell(inputFile);
sizeofFile++;
fseek(inputFile,0,0);
source_buf=calloc(1,sizeofFile);
fread(source_buf,sizeofFile,1,inputFile);
printf("SIZE OF THE FILE=%d",sizeofFile);
//sleep(5);
fclose(inputFile);
return source_buf;
}
Check the return value of fseek() (and all other library calls!)
if (fseek(inputFile, 0, SEEK_END)) perror("seek to end");
sizeofFile = ftell(inputFile);
if (sizeofFile == -1) perror("ftell");
You are asking fread to read one block sizeofFile long. If it cannot read a block that size it will fail and return zero. Instead you would do better to request sizeofFile blocks of 1 byte long. Then it will report exactly how may bytes it managed to read, which may be fewer than sizeofFile for a number of reasons.
rc = fread( source_buf, 1, sizeofFile inputFile ) ;
In your case it will always be fewer than sizeofFile because you previously incremented it, so there never were sizeofFile bytes to be read. You should have read the file size not the buffer size, but the reading multiple blocks of one byte is still preferable in any case. In fact I would suggest the following changes:
sizeofFile = ftell( inputFile ) ;
// REMOVED sizeofFile++ ;
fseek( inputFile, 0, SEEK_SET ) ;
source_buf = calloc( 1, sizeofFile + 1 ) ; // Don't confuse file size and buffer size here.
rc = fread( source_buf, 1, sizeofFile, inputFile ) ; // SWAPPED param 2 and 3
It makes sense to use a block size other than 1 if you are reading fixed length records. If reading a byte stream of arbitrary length, the size should generally be 1, and the count used to determine the amount of data read.
char * Copy_file_to_buf(char *fileName)
{
FILE *inputFile;
int sizeofFile, rc;
char *source_buf;
fprintf(stderr, "In Copy_file_to_buf\n");
inputFile=fopen(fileName,"r");
if (!inputFile) {
fprintf(stderr, "Oops, failed to open inputfile \"%s\"\n", fileName );
return NULL;
}
fseek(inputFile,0,SEEK_END);
sizeofFile=ftell(inputFile);
fseek(inputFile,0,SEEK_SET);
source_buf=calloc(1,1+sizeofFile);
rc = fread(source_buf,sizeofFile,1,inputFile);
/* now check rc */
fprintf(stderr, "SIZE OF THE FILE=%d; fread returned %d.\n", sizeofFile, rc);
//sleep(5);
fclose(inputFile);
source_buf[sizeofFile] = 0;
return source_buf;
}
UPDATE: for testing added main + includes...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv)
{
char *lutser;
lutser = Copy_file_to_buf(argv[1] );
fprintf (stderr, "Strlen(lutser)=%u\n", (unsigned) strlen(lutser) );
puts (lutser);
return 0;
}
Output:
-rw-r--r-- 1 Plasser pis 1008 2012-03-31 15:10 lutsbuf.c
-rwxr-xr-x 1 Plasser pis 8877 2012-03-31 15:11 a.out
Plasser#Pisbak$ ./a.out lutsbuf.c
In Copy_file_to_buf
SIZE OF THE FILE=1008; fread returned 1.
Strlen(lutser)=1008
...
<contents of file>
...
CopyNewFile doesn't close its file. WriteSubHeadersToFile may not always (hard to follow the flow). How are you determining the "real" size of the file?

Resources