How to read an HTTP file line by line in C - c

I am wanting to pull from a plain-text file on the internet, and have it read line by line. Similar to how you read a file line by line with fgets(). I don't want to download the file. I know that if you use the read() function, you can specify how many bytes to receive and manually read the file line by line. I was just wondering if there was any way to do this automatically. Thanks for any help!

I have to do that a lot, and wrote the following little function to help. Just call FILE *wwwpopen(), *fp=wwwpopen("http://wherever.com/whatever.html","r"); and then use fp as usual to read whatever.com any way you like. When done, just pclose(fp) yourself. Here's the little function (note: if wget not on your default path, then replace wget[256] initialization below by the full path to wget on your system),
/* ==========================================================================
* Function: wwwpopen ( char *url, char *mode )
* Purpose: popen("wget -O - url",mode)
* --------------------------------------------------------------------------
* Arguments: url (I) char * containing null-terminated string
* with url to be opened
* mode (I) char * containing null-terminated string
* that should always be "r"
* (this arg ignored, always "r"; just there for
* consistency with fopen/popen calling sequence)
* Returns: ( FILE * ) file pointer to popen()'ed url file
* or NULL for any error.
* --------------------------------------------------------------------------
* Notes: o pclose(fileptr) yourself when finished reading file
* ======================================================================= */
/* --- entry point --- */
FILE *wwwpopen ( char *url, char *mode ) {
/* --- Allocations and Declarations --- */
FILE *fileptr = NULL; /* file ptr returned to caller */
char defaultmode[16] = "r", /* default mode, always used */
wgetargs[16] = "-O -", /* command-line args for wget */
wget[256] = "wget", /* replace by path to wget, if any */
command[512]; /* constructed wget command */
/* --- Check input --- */
mode = defaultmode; /* force popen() mode, must be "r" */
if ( url != NULL ) { /* url supplied */
/* --- popen() file --- */
sprintf(command,"%s %s %s", /* construct wget args url */
wget, /* path to wget program */
wgetargs, /* command-line args for wget */
url); /* and url to be wgotten */
fileptr = popen(command,mode); } /* popen() url (mode better be "r")*/
return ( fileptr ); /* back to caller with file ptr */
} /* --- end-of-function wwwpopen() --- */

Related

Cannot open file with fopen(); function - C Programing [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am trying to create a program that using the fopen(); function.
My problem is that fopen(); cannot find the file.
when i am using perror("Error"); the output is Error: No such file or directory.
I have read this articles and they did`not solved my problem:
fopen() returning a NULL pointer, but the file definitely exists
Unable to open a file with fopen()
It means i have tried to use fopen(); with the exec path to the file, and i have checked that the filename is the specific filename that i am looking for.
I have also used exec("pwd"); to see that i am the correct directory.
My OS is ubuntu mate 20.04.
Here is my Code:
/* File Name: firstTransaction.c
* File Mission: scan the input files and make the first transaction.
*/
#include "defines.h"
/*
* first transaction file:
* Allocating new memory for the assembly source file.
* Scanning the assembly source file.
* #param filename - the filename of the file that needs to be converted by the program.
* #return output and files -
* output the assembly source file in a machine code.
* return extern, entry and object files.
*/
/* function prototype */
extern char * readText(FILE * ptr, long ic, long dc); /* the function defined on assistanceFunctions.c file */
int firstTransaction(int * cf, char **av)
{
FILE * fp; /* a pointer for fopen function */
char * filteredFile = NULL;
long ic = 100, dc = 0; /* declaration and initialization of the instruction counter and current data counter */
int i = 0, j = 0; /* indexes */
int cfh = 0; /* compatible file holder */
int fileNameLength = (int)strlen(av[i]); /* computing the first filename length to allocate memory */
char * fileName = (char*) calloc(fileNameLength,sizeof (char)); /* allocating memory for the first filename */
system("pwd");
while(cf[i] != 0) /* while there is more compatible files to open */
{
cfh = cf[i]; /* cfh - compatible file holder, cf - compatible file array, set the next compatible file to cfh */
strcpy(fileName,av[cfh]); /* copy the file name from the argv array */
fp = fopen("fileName","r"); /* open the first compatible file for read */
if(fp == NULL) /* if file does not exists */
{
perror("Error"); /* print the error - why the file not opened */
i++; /* increment i by one and try to open the next filename */
}else /* if the file was opened successfully, start scanning the file */
{
/*filteredFile = */ readText(fp, ic, dc); /* calling readText function with pointer to the start of the file that was opend by fopen function */
/* while(filteredFile[j] != EOF)
{
putchar(filteredFile[j]);
j++;
}
/* DONT FORGET TO CLOSE WITH FCLOSE(); */
}
}
return 0;
}
Here is some screenshots with the tested solutions that failed from the other articles:
Edited after NeonFire answers:
My first code used fp = fopen(fileName,"r"); but my error message was made manually this way: printf("error, %s file does not exists\n", fileName); /* print error message to the user */
this cause that i did`not find my real error.
then i changed to fp = fopen("fileName","r"); and used perror("Error"); instead of the first and right way.
after i read NeonFire answers i got a new error Error: Too many open files.
i removed the backups file from the directory and i still have the same error.
Edited after Ted Lyngmo comment:
i did had to close the file to solve the - "to many file to open error".
your fp = fopen("fileName","r"); is incorrect. Remove the quotes from fileName so it refers to your variable char * fileName , not a string "fileName" :)

How to replace the text into a particular location of a file by passing the argument via command line argument

My intention is to read the second element in the 1st row and replace it with the value which we pass as an command line argument and replace it in the input.txt file
Input file:logic.txt
one=1234
two=3456
I want my file to be changed like this after compiling the code.
./a.out 1567
Currently i am getting output like this
./filelogic 1567
1567=1234
two=5678
Expected Output file should be modified like this after the compilation
logic.txt
one=1567
two=5678
char buf[MAXSIZE] = {};
int num = 0;
int i = 0;
num = atoi(argv[1]);
printf("%d",num);
FILE *fp1;
fp1 = fopen("logic.txt","r");//currently reading the file.
if(fp1 != NULL)
{
fseek(fp1,3,0);//Need to Move the pointer to the 3rd position where i need to replace the num(fseek(fp1,??,0))-->how we can achieve that.
//Using which method i can replace the num value into a file (means need to replace 1234 inplace of 1567)
//Once the changes are done need to replace in the same file.
fread(buf, 1, MAXSIZE, fp1);
printf("%s\n",buf);
fclose(fp1);
}else {
printf("Cannot open file"");
exit(1);
}
Could someone guide me to resolve this issue?Thanks in advance
You can make replacements to a file in-place, but you should not do this in practice. You will likely corrupt the file if you attempt to replace characters and do not make an exact one-to-one replacement of characters already in the file.
To safely change the contents of a file, read the entire file contents into memory, make the changes needed, and then truncate the current file and write the new contents to the truncated file. (if the file is too large for in-memory operations, then use a temporary file)
You do not want to use atoi to convert the string "1567" to an integer. You are replacing characters in a file, not integer values in a binary file, so work with characters instead.
Your project is complicated by only wanting to replace the text after the first '=' sign. This may or may not be on the first line of the file, so you will need some flag to indicate when the first '=' is found and the replacement is made. (once the replacement is made, you can simply break your read loop and close the file -- but below the example output all lines for convenience)
Any time you close a file after writing to it, you should validate the return of fclose to catch any stream errors, or errors that occurred on the last write that will not be apparent until the next file operation.
With those cautions and caveats in mind, you could do something similar to:
#include <stdio.h>
#include <string.h>
#define MAXSIZE 64 /* max line/buffer size */
#define FNAME "logic.txt" /* default file name */
#define REPLACE "1567" /* default replacement text */
int main (int argc, char **argv) {
char buf[MAXSIZE] = ""; /* line buffer */
const char *str = argc > 1 ? argv[1] : REPLACE; /* replacement string */
int replaced = 0; /* flag indicating replacement made */
FILE *fp = fopen (FNAME, "r+"); /* open file reading/writing */
if (!fp) { /* validate file open for reading/writing */
perror ("fopen-FNAME");
return 1;
}
while (fgets (buf, MAXSIZE, fp)) { /* read each line in file */
if (!replaced) { /* if replacement not yet made */
char *p = strchr (buf, '='); /* search for '=' in line */
if (p) { /* if found */
size_t plen = 0; /* var for length to end */
p++; /* advance past '=' sign */
plen = strlen (p); /* get length to end */
if (plen < strlen (str)) { /* check avail length */
fprintf (stderr, "error: not enough space in line.\n");
return 1;
}
strcpy (p, str); /* copy str to p */
if (fseek (fp, -plen, SEEK_CUR)) { /* backup plen chars */
perror ("fseek(fp)");
return 1;
}
fputs (p, fp); /* overwite contents with replacement */
replaced = 1; /* set flag indicating replacement */
} /* (you can break, and remove output */
} /* here if not writing to stdout) */
fputs (buf, stdout); /* output lines to stdout (optional) */
}
if (fclose (fp) == EOF) /* always validate close-after-write */
perror ("fclose-FNAME");
return 0;
}
Using your file logic.txt as an example input, and naming the executable filelogic as you have, the use and operation of the code above yields:
logic.txt File Before
$ cat logic.txt
one=1234
two=3456
Example Use/Output
$ ./filelogic
one=1567
two=3456
logic.txt File After
$ cat logic.txt
one=1567
two=3456
Again, this is fine for a learning endeavor, but in practice, avoid making changes to files in-place as the risk of inadvertent file corruption far outweighs writing a new file with the changes.

Quickest way to check whether or not file exists [duplicate]

This question already has answers here:
What's the best way to check if a file exists in C?
(8 answers)
Closed 5 years ago.
The way I'm using just involves trying to fopen() the file to be checked,
/* --- does file exist??? --- */
char fname[999] = "whatever"; /* constructed during execution */
FILE *fp = NULL; /* try to fopen(fname,"r") */
int isfilefound = 0; /* set true if fopen() succeeds */
if ( (fp = fopen(fname,"r")) /* try to fopen() for read */
!= NULL ) { /* succeeded */
isfilefound = 1; /* set file found flag */
fclose(fp); } /* and just close the file */
Is there a quicker, less resource-intensive, way?... A specific way for unix/linux? A Windows way? And preferably, a portable posix-compliant way (as above presumably is)? It's being done lots (1000's) of times, so I'd prefer not to be unnecessarily opening and closing files for no good reason.
-----------------------------------------------------------------
Edit Okay, based on answers below, I put together the following little function intended to check whether or not file (already:) exists in a posix,windows,other portable way...
/* ==========================================================================
* Function: isfilexists ( path )
* Purpose: check whether file at path exists
* --------------------------------------------------------------------------
* Arguments: path (I) pointer to null-terminated char string
* containing "path/filename.ext" of
* file whose existence is to be determined
* (path is relative to pwd unless explicitly
* absolute by initial '/' or other syntax)
* --------------------------------------------------------------------------
* Returns: ( int ) 1 if file at path exists, or 0 if not
* --------------------------------------------------------------------------
* Notes: o conditional compiles for various systems,
* depending on whether POSIX or WINDOWS is #define'ed...
* o ...method used:
* 1: use access() on Posix systems,
* 2: PathFileExists() on Windows systems,
* 3: fopen() on any other systems.
* ======================================================================= */
/* --- entry point --- */
int isfilexists ( char *path )
{
/* ---
* allocations and declarations
* ------------------------------- */
int isexists = 0; /* set true if file at path exists */
FILE *fp = NULL; /* fopen() for non-posix,windows */
#define POSIX /* just for testing */
/* ---
* determine whether file at path already exists
* ------------------------------------------------ */
#if defined(POSIX) /* posix-compliant system... */
#include <unistd.h>
if ( access(path,F_OK) == 0 ) /* file at path exists */
isexists = 1; /* so set file exists flag */
#else
#if defined(WINDOWS) /* Windows system... */
isexists = PathFileExists(path); /* set flag if file at path exists */
#else
/* --- fopen() for any other non-posix, non-windows system --- */
if ( (fp = fopen(path,"r")) /* try to fopen() for read */
!= NULL ) { /* succeeded */
isexists = 1; /* set file exists flag */
fclose(fp); } /* and just close the file */
#endif
#endif
return ( isexists ); /* back to caller with 1 if file at path exists */
} /* --- end-of-function isfilexists() --- */
The access() and fopen() methods tested and work okay. Unable to test PathFileExists() for windows. And I still want to figure out what #define'ed symbols to automatically and unambiguously check for conditional compiles.
You are thinking about the problem the wrong way. You shouldn't ever "check whether a file already exists", because that has an inherent TOCTOU race — in between the time you check whether the file exists, and the time you act on that information, another process may come along and change whether the file exists, rendering the check invalid.
What you do instead depends on why you want to know. One very common case is that you only want to create the file if it doesn't already exist, in which case you use the lower-level open function in O_EXCL mode:
int fd = open("whatever", O_WRONLY|O_CREAT|O_EXCL, 0666);
if (fd == -1 && errno == EEXIST) {
/* the file already exists */
} else if (fd == -1) {
/* report that some other error happened */
} else {
FILE *fp = fdopen(fd, "w");
/* write data to fp here */
}
Another very common case is that you want to create the file if it doesn't exist, or append new data to the file if it does; this can be done with the "a" mode to fopen or O_APPEND flag to open.
On Windows, there is PathFileExists().
On a POSIX system, you have stat() or access().
That said, if you check for existence of the file because your code needs the file, this is the wrong approach -- file systems are out of your program's control, so this would be a race condition, the only correct way would be to properly handle errors when opening the file.

Program copying files incorrectly

So for an assignment in my Systems class, we have to make a program that takes a file in a given source and copies it to a given destination using one of three copyfile() functions.
When running the program in the command line, it will take in three arguments: ./cptest, the input file location, and the output file location, as well as two optional arguments: the number for which copyfile() function you would like to use as well as the buffer size.
If you choose 1 for the copyfile() function parameter, the program should copy the file using formatted I/O (file handles), and then copy the file one character at a time.
If you choose 2 for the copyfile() function parameter, the program should copy the file using integer file descriptors, and then copy the file one character at a time.
If you choose 3 for the copyfile() function parameter, the program should allocate a buffer of size equal to what size you put in for the buffer size parameter (say 1024), then use read() to read from the input file up to that many bytes at a time.
If you do not put in a third parameter (copyfile() function number), then the program will automatically use copyfile3() with whatever buffer size you decided with the fourth parameter.
If you do not enter a fourth parameter (buffer size), then the program will set it to 1024 by default and use it if necessary (not needed for copyfile1() or 2()).
Before and after each copyfile() function is called, the program uses gettimeofday() to make a timestamp. The program then makes a new timestamp to find how long the copying took using the difference in seconds and microseconds between the after timestamp and the before timestamp, then prints all this information out.
For example if I put in: ./cptest ~/My_Documents/photo.JPG ~/assig6/photo.JPG 3
The program should return:
Timestamp Before Copying:
Seconds: 1425150842, Microseconds: 914511
Timestamp After Copying:
Seconds: 1425150842, Microseconds: 927662
Copying took 0 seconds, 13151 microseconds
So now that you know what the program does, let's get down to the issue. Every time I run the programs with any of the copyfile() functions, be it 1, 2, or 3, technically speaking, the copying works fine, the file ends up in the correct destination, and the program returns all the correct information in terms of the timestamps.
However, in reality, it does not work, as when I use copyfile1(), it copies all of the bytes, but when I try to open the file - say a .jpg - it says that it can't view the file because it appears to be damaged, corrupted, or too large. When I use copyfile2() and copyfile3(), the file in the destination has only 1 KB, and when I don't pass in a third or fourth parameter, the output file has 0 KB. The same thing happens with word documents.
Is there a reason why it copies the files fine but the file is damaged in the process? It seems as though the code is right but the end result is not.
Here's the main file cptest.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include "cptest.h"
/** cptest.cpp
* A file copying program.
* Derived partially from caesar.cpp by Horstmann and Budd from big C++
*/
/** Prints usage instructions.
* #param program_name the name of this program
*/
void usage(char* program_name) {
// Prints out usage instructions if incorrect number of parameters is passed in
printf("Usage: %s infile outfile copy_function_number buffer_size \n", program_name);
}
/** Prints file opening error message
* #param filename the name of the file that could not be opened
*/
void open_file_error(char* filename) {
// Error message if unable to open the file
printf("Error opening file %s\n", filename);
}
/** Main program: copies a file.
* #param argc Number of command-line arguments (including program name).
* #param argv Array of pointers to character arays holding arguments.
* #return 0 if successful, 1 if failure.
*/
int main(int argc, char* argv[]) {
char* infilename; // Name of input file
char* outfilename; // Name of output file
int copy_function_number; // Chooses which copy function is used based on argv[3]
int buffer_size; // Size of buffer
int returnstatus; // 0 or 1 depending on success or failure to copy the file to the destination
struct timeval* before = malloc(sizeof(struct timeval)); // Struct for time before copying is done
struct timeval* after = malloc(sizeof(struct timeval)); // Struct for time after copying is done
if (argc != 3 && argc != 4 && argc != 5) {
usage(argv[0]); // Must have 2, 3, or 4 arguments in addition to ./cptest.
return 1; // Failure!
}
infilename = argv[1]; // Sets first parameter to the input file name
outfilename = argv[2]; // Sets second parameter to the output file name
if(argv[3] == NULL) {
copy_function_number = 3; // Program uses copyfile3 if no third parameter is entered
}
else {
copy_function_number = atoi(argv[3]); // Otherwise program uses whatever function is passed by third parameter
}
if (argv[4] == NULL) {
buffer_size = 1024; // Sets buffer size to 1024 if no fourth parameter is entered
}
else {
buffer_size = atoi(argv[4]); // Otherwise buffer size is whatever user enters as fourth parameter
}
if (copy_function_number == 1) {
gettimeofday(before, NULL); // Get timestamp before the copying
// Perform the copying with copyfile1() if the third parameter is 1
returnstatus = copyfile1(infilename, outfilename);
gettimeofday(after, NULL); // Get timestamp after the copying
}
if (copy_function_number == 2) {
gettimeofday(before, NULL); // Get timestamp before the copying
// Perform the copying with copyfile2() if the third parameter is 2
returnstatus = copyfile2(infilename, outfilename);
gettimeofday(after, NULL); // Get timestamp after the copying
}
if (copy_function_number == 3) {
gettimeofday(before, NULL); // Get timestamp before the copying
// Perform the copying with copyfile3() if the third parameter is 3
returnstatus = copyfile3(infilename, outfilename, buffer_size);
gettimeofday(after, NULL); // Get timestamp after the copying
}
else {
if (copy_function_number != 1 || copy_function_number != 2 || copy_function_number != 3 || argv[3] == NULL) {
gettimeofday(before, NULL); // Get timestamp before the copying
// Perform the copying with copyfile3() if no third parameter is entered
returnstatus = copyfile3(infilename, outfilename, buffer_size);
gettimeofday(after, NULL); // Get timestamp after the copying
}
}
struct timeval *copytime = difference_in_time(before, after); // Struct for time after copying is done
// Print out information of the timestamp before copying
printf("Timestamp Before Copying: \n Seconds: %d, Microseconds: %d\n", before->tv_sec, before->tv_usec);
// Print out information of the timestamp after copying
printf("Timestamp After Copying: \n Seconds: %d, Microseconds: %d\n", after->tv_sec, after->tv_usec);
// Print out information of the difference between the timestamps (how long the copying took)
printf("Copying took %d seconds, %d microseconds\n", copytime->tv_sec, copytime->tv_usec);
return returnstatus; // 0 if successful copy, 1 if unsuccessful.
}
/** Copies one file to another using formatted I/O, one character at a time.
* #param infilename Name of input file
* #param outfilename Name of output file
* #return 0 if successful, 1 if error.
*/
int copyfile1(char* infilename, char* outfilename) {
FILE* infile; //File handle for source.
FILE* outfile; // File handle for destination.
infile = fopen(infilename, "r"); // Open the input file.
if (infile == NULL) {
open_file_error(infilename); // Error message if there was a problem opening the input file.
return 1; // Failure!
}
outfile = fopen(outfilename, "w"); // Open the output file.
if (outfile == NULL) {
open_file_error(outfilename); // Error message if there was a problem opening the output file.
return 1; // Failure!
}
int intch; // Character read from input file. must be an int to catch EOF.
unsigned char ch; // Character stripped down to a byte.
// Read each character from the file, checking for EOF.
while ((intch = fgetc(infile)) != EOF) {
ch = (unsigned char) intch; // Convert to one-byte char.
fputc(ch, outfile); // Write out.
}
fclose(infile); // Close the input file.
fclose(outfile); // Close the output file.
return 0; // Success!
}
/** Copies one file to another using integer file descriptors instead of file handles, one character at a time.
* #param infilename Name of input file
* #param outfilename Name of output file
* #return 0 if successful, 1 if error.
*/
int copyfile2(char* infilename, char* outfilename) {
int infile; //File handle for source.
int outfile; // File handle for destination.
// Allocates a buffer for the chars that will be read from the input and written to the output.
char buffer[1024];
infile = open(infilename, O_RDONLY); // Open the input file.
if (infile < 0) {
open_file_error(infilename); // Error message if there was a problem opening the input file.
return 1; // Failure!
}
outfile = open(outfilename, O_WRONLY | O_CREAT); // Open the output file.
if (outfile < 0) {
open_file_error(outfilename); // Error message if there was a problem opening the output file.
return 1; // Failure!
}
int intchin; // Character read from input file. must be an int to catch EOF.
int intchout; // Character written to the output file. must be an int to catch EOF.
// Size of the buffer so that when you are copying extremely large files, it does not have to go through 200000 loop iterations
int buffer_size = 1024;
unsigned char ch; // Character stripped down to a byte.
// Read each character from the file, checking for 0.
while ((intchin = read(infile, buffer, buffer_size)) != 0) {
ch = (unsigned char) intchin; // Convert to one-byte char.
intchout = write(outfile, buffer, ch); // Write out.
}
close(intchin); // Close the input file.
close(intchout); // Close the output file.
return 0; // Success!
}
/** Copies one file to another using integer file descriptors, buffer_size characters at a time.
* #param infilename Name of input file
* #param outfilename Name of output file
* #param buffer_size Size of the buffer for reading and writing
* #return 0 if successful, 1 if error.
*/
int copyfile3(char* infilename, char* outfilename, int buffer_size) {
int infile; //File handle for source.
int outfile; // File handle for destination.
// Allocates a buffer of size buffer_size for the chars that will be read from the input and written to the output.
char* buffer = (char*) malloc(sizeof(char)* buffer_size);
infile = open(infilename, O_RDONLY); // Open the input file.
if (infile < 0) {
open_file_error(infilename); // Error message if there was a problem opening the input file.
return 1; // Failure!
}
outfile = open(outfilename, O_WRONLY | O_CREAT); // Open the output file.
if (outfile < 0) {
open_file_error(outfilename); // Error message if there was a problem opening the output file.
return 1; // Failure!
}
int intchin; // Character read from input file. must be an int to catch EOF.
int intchout; // Character written to the output file. must be an int to catch EOF.
unsigned char ch; // Character stripped down to a byte.
// Read each character from the file, checking for 0.
while ((intchin = read(infile, buffer, buffer_size)) != 0) {
ch = (unsigned char) intchin; // Convert to one-byte char.
intchout = write(outfile, buffer, ch); // Write out.
}
close(intchin); // Close the input file.
close(intchout); // Close the output file.
free(buffer); // Free the buffer that was allocated.
return 0; // Success!
}
/** Makes a new timeval struct that determines the difference between two timestamps
* #param time1 Struct containing the information for the first timestamp
* #param time2 Struct containing the information for the second timestamp
* #return The struct made using the two parameters
*/
struct timeval* difference_in_time(struct timeval* time1, struct timeval* time2) {
struct timeval* copytime = malloc(sizeof(struct timeval)); // Allocates a struct to hold the difference between the two timestamps.
if ((time2->tv_sec - time1->tv_sec) < 0) {
// Error message for if the first timestamp entered was before the second timestamp.
printf("Seconds value is negative! time1 should be before time2!\n");
}
if ((time2->tv_usec - time1->tv_usec) < 0) {
// Handles if the difference in microseconds between the second and first timestamps would be negative, subtracting 1 from the seconds.
copytime->tv_sec = (time2->tv_sec - time1->tv_sec) - 1;
// Handles if the difference in microseconds between the second and first timestamps would be negative, subtracting the difference from 1000000.
copytime->tv_usec = 1000000 - (time2->tv_usec - time1->tv_usec);
}
else {
// Otherwise the seconds for the third timestamp is the difference between the seconds of the second and first timestamps.
copytime->tv_sec = (time2->tv_sec - time1->tv_sec);
// Otherwise the microseconds for the third timestamp is the difference between the microseconds of the second and first timestamps.
copytime->tv_usec = (time2->tv_usec - time1->tv_usec);
}
return copytime; // Return the new timestamp created.
}
Here's the header file cptest.h:
#ifndef CPTEST_H
#define CPTEST_H
// function prototypes
void usage(char* program_name);
void open_file_error(char* filename);
int copyfile1(char* infilename, char* outfilename);
int copyfile2(char* infilename, char* outfilename);
int copyfile3(char* infilename, char* outfilename, int buffer_size);
struct timeval* difference_in_time(struct timeval* time1, struct timeval* time2);
#endif
And here's the makefile:
cptest: cptest.o
gcc -g cptest.o -o cptest
cptest.o: cptest.c cptest.h
gcc -c -g cptest.c
clean:
rm -f *.o cptest
docs:
doxygen
chmod a+r html/*
cp -p html/* ~/public_html/cs2303assig6
EDIT: Thought it might be easier to show you what happens using the readme.txt we need to include with our program as an example. Shortened it down to the useful information so you don't have to through more walls of text.
Original:
Name: *My name*
Section: CS2303 C01
What Program Does: *Explanation of what program does*
Example: *Example of what should show up when running program in the command line*
Results: *Test data for time it took for each function and using different buffer sizes to find most efficient function and buffer size*
Compiling:
To compile the code, use 'make' in the command line. The makefile should already link all of the .o files to the executable, so the work is done for you.
Result when using copyfile1():
so the work is done for you.S2303 C01
What Program Does: *Explanation of what program does*
Example: *Example of what should show up when running program in the command line*
Results: *Test data for time it took for each function and using different buffer sizes to find most efficient function and buffer size*
Compiling:
To compile the code, use 'make' in the command line. The makefile should already link all of the .o files to the executable, so the work is done for you.
Result when using copyfile2() and 3():
so the work is done for you.
copyfile2 and 3 are completely broken because they cast the number of characters read into a char. As the buffer size is often 1024, this cast gives a result of 0 so nothing is written.
For copyfile 1, I'd recommend opening the files with a binary flag ("rb" or "wb") although I'm not convinced that is the issue.

calling fclose on a memstream FILE causes segmentation fualt

I have an interface that only prints strings to a file and Im working on a embedded system so opening a file is not an option
I created a virtual file in a memory using open_memstream , and after using the file and parsing the string the program fails on fclose causing a segmentation fault
here's the code :
/*
* Creating a temp file in memory
*/
FILE * mem_stream;
char * mem_buf;
size_t mem_len;
mem_stream = open_memstream(mem_buf,&mem_len);
XMLDoc_print(doc, mem_stream, NULL, NULL, 0, 0 ,0);
XMLDoc_free(doc);
/*
* Reading the temp file
*/
fseek(mem_stream,0,SEEK_END);
long file_size = ftell(mem_stream);
rewind(mem_stream);
char * contents = malloc( (file_size+1) * sizeof(char) );
fread(contents, sizeof(char), file_size, mem_stream);
/*
* closing the file
*/
fclose(mem_stream);
contents[file_size] = 0;
printf("\n THE RESULT XML IS : %s \n" , contents);
If i comment the fclose(mem_stream); line the program works fine , is this an option ? if not how can i fix this.
mem_stream = open_memstream(mem_buf,&mem_len); this line should be like this :
mem_stream = open_memstream(&mem_buf,&mem_len);
as said in the function's documentation
/* Open a stream that writes into a malloc'd buffer that is expanded as
necessary. *BUFLOC and *SIZELOC are updated with the buffer's location
and the number of characters written on fflush or fclose. */
extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __THROW __wur;
the char ** __bufloc is an address to a char * buffer.

Resources