How to do proper error handling with the fopen function - c

I wrote a program that asks the user to enter the full pathname of a file. It will then attempt to open that file from the pathname string provided. I used the standard error checking that most books have recommended, which is to close the program if fopen() returns NULL (which it will do in the case that the file does not exist). When I run the program and enter some random characters when prompted (obviously not a valid filename) my program hangs with a runtime error because it's trying to open that file that doesn't exist.
What is the point of the standard error check (pfile == NULL) if your program has already crashed when it calls fopen()? See below code.
I'm using LabWindows CVI 2017 as my enfironment which uses the clang compiler. See image of run time error.
#include <stdio.h>
#include <string.h>
#define MAX 200
int main (void){
char buffer[MAX];
int len = 0;
FILE *pfile = NULL;
printf("please enter the full pathname of the file you wish to process.\n");
fgets(buffer, MAX, stdin);
len = strlen(buffer);
buffer[len - 1] = '\0';
pfile = fopen(buffer, "r");
if(pfile == NULL){
printf("not a valid filename, press any key to exit.");
getchar();
return -1;
}
int sum = 0;
int c = 0;
while((c = fgetc(pfile)) != EOF){
sum += sizeof(c);
}
printf("the size of your file is %d\n", sum);
getchar();
return 0;
}

You are doing the proper error handling. Your program is valid in that respect. However, your IDE does some extra error checking, which is the cause of the behavior you're seeing.

The usual rules for error checking in these sorts of situations are:
Do check for error returns. (You're doing that.)
Do print a useful error message. (You're doing that.)
Print error messages to stderr.
If the error involves a file, do include the filename in the error message.
If the error involves a function that sets errno, do print the "perror" text" ("No such file or directory", etc.).
If you're writing a tool that will be combined into larger scripts, do include the program's name in the error message.
If the error occurs due to an input file you're reading, do print the name of that file and the line number.
Adopting rules 1 through 6, an improved version of your error check would be
if(pfile == NULL) {
fprintf(stderr, "%s: can't open %s: %s\n", progname, buffer, strerror(errno));
return EXIT_FAILURE;
}
For this to work you'll need both of:
#include <string.h>
#include <errno.h>
If that's too much work, a simpler way is just to call
perror(buffer);
although this falls down somewhat on rules 2, 6, and 7.

Related

C - Print lines from file with getline()

I am trying to write a simple C program that loads a text-file, prints the first line to screen, waits for the user to press enter and then prints the next line, and so on.
As only argument it accepts a text-file that is loaded as a stream "database". I use the getline()-function for this, according to this example. It compiles fine, successfully loads the text-file, but the program never enters the while-loop and then exits.
#include <stdio.h>
#include <stdlib.h>
FILE *database = NULL; // input file
int main(int argc, char *argv[])
{
/* assuming the user obeyed syntax and gave input-file as first argument*/
char *input = argv[1];
/* Initializing input/database file */
database = fopen(input, "r");
if(database == NULL)
{
fprintf(stderr, "Something went wrong with reading the database/input file. Does it exist?\n");
exit(EXIT_FAILURE);
}
printf("INFO: database file %s loaded.\n", input);
/* Crucial part printing line after line */
char *line = NULL;
size_t len = 0;
ssize_t read;
while((read = getline(&line, &len, database)) != -1)
{
printf("INFO: Retrieved line of length %zu :\n", read);
printf("%s \n", line);
char confirm; // wait for user keystroke to proceed
scanf("%c", &confirm);
// no need to do anything with "confirm"
}
/* tidy up */
free(line);
fclose(database);
exit(EXIT_SUCCESS);
}
I tried it with fgets() -- I can also post that code --, but same thing there: it never enters the while-loop.
It might be something very obvious; I am new to programming.
I use the gcc-compiler on Kali Linux.
Change your scanf with fgetline using stdin as your file parameter.
You should step through this in a debugger, to make sure your claim that it never enters the while loop is correct.
If it truly never enters the while loop, it is necessarily because getline() has returned -1. Either the file is truly empty, or you have an error reading the file.
man getline says:
On success, getline() and getdelim() return the number of
characters
read, including the delimiter character, but not including the termiā€
nating null byte ('\0'). This value can be used to handle embedded
null bytes in the line read.
Both functions return -1 on failure to read a line (including end-of-
file condition). In the event of an error, errno is set to indicate
the cause.
Therefore, you should enhance your code to check for stream errors and deal with errno -- you should do this even when your code works, because EOF is not the only reason for the function
to return -1.
int len = getline(&line, &len, database);
if(len == -1 && ferror(database)) {
perror("Error reading database");
}
You can write more detailed code to deal with errno in more explicit ways.
Unfortunately handling this thoroughly can make your code a bit more verbose -- welcome to C!

create a file in c programming and write hello world in the file

#include<stdio.h>
int main()
{
FILE *opening;
opening = fopen("hello.usr","w");
fprintf(opening,"Hello world!");
fclose(opening);
printf("Writing to the file was successful.\n");
printf("Closing the program");
return 0;
}
I have tried this code to create a file in c programming and write the text "Hello world!" in it. What's wrong with this code?
If you want to know what is wrong check the result of fopen
opening = fopen("hello.usr","w");
if (opening == NULL) {
perror("fopen");
}
As of now, you don't know whether you managed to write to the file or not, so here's a suggestion which checks for it.
FILE *opening;
opening = fopen("hello.usr", "w");
if (opening == NULL){
perror("fopen");
return 0;
}
By returning 0 here you remove the option for segmentation fault as the code will still try to write to the file even if it doesn't exist.
The error message you are getting most certainly is NOT produced by a compiler. It looks to me as a message of some automatic checker that tests correctness of the submited solutions.
Make sure that the output matches exactly the required one.
The message:
Your program's output is shorter than the expected
may indicate that there is something wrong with new line characters ('\n'). Check for those.
For example if the required output is:
Writing to the file was successful. Closing the program.
... printed in one line, your output obviously doesn't match as it has a new line after the first sentence. And if the checker testes for the first occurrence of a new line character it sees only
Writing to the file was successful.
which could be one of many possible explanations. If this is the case try simply:
#include<stdio.h>
int main()
{
FILE *opening;
opening = fopen("hello.usr","w");
fprintf(opening,"Hello world!");
fclose(opening);
// printf("Writing to the file was successful.\n");
// printf("Closing the program");
printf("Writing to the file was successful. Closing the program\n");
return 0;
}
Note also that this sort of error messages (in automatic testing environments) are usually triggered by ommited, added extra or confused non-printable characters (spaces, tabs, new lines) or punctuation marks which is hard to notice.
You may also want to check in this respect the text you print to the file.
Try to Instead "w" use "wt" in fopen
Try the following
#include <stdio.h>
int main() {
FILE *opening = fopen("hello.usr", "w");
if(opening == NULL){
printf("An error occurred when opening the file!");
return 0;
}
else{
fprintf(opening, "Hello world!\n");
fclose(opening);
printf("Writing to the file was successful.\nClosing the program.\n");
}
return 0;
}

write file read code with overflow

Well, I try to play a bit with stack overflow and security cookies,
But its seem that most of the tutorial programs that people with POC tutorial with them are not compile with security cookies.
So i decide to create a program that take input from file and create a buffer overflow.
This is what I come out with:
#include <stdio.h>
#include <string.h>
void manipulate(char *buffer)
{
char newbuffer[80];
strcpy(newbuffer, buffer);
}
int main()
{
char ch, buffer[4096];
char filename[] = "exploit.txt";
int i = 0;
FILE *inFile;
inFile = fopen(filename, "rb");
if (inFile == NULL)
{
fprintf(stderr, "Can't open input file !\n");
getchar();
return 1 ;
}
while (buffer[i] != EOF)
{
buffer[i++] = fgetc(inFile);
manipulate(buffer);
printf("The value of i is : %d\n", i);
getchar();
return 0;
}
}
My problem is that I am always get Can't open input file !\n. even when i created "exploit.txt" in the same location and put some "aaaa" in it.
The basics of opening a file are correct. You can improve your program by using errno and strerror to inform the user of why the attempt to open the file failed.
#include <errno.h>
fprintf(stderr, "Error opening \"%s\": %s\n", filename, strerror(errno));
I was able to successfully run your example program (ignoring the stack overflow portion) with no changes.
The issue is with the value of the current or present working directory which is used as the basis for the completing file path used to open any file.
You can check the program's working directory using either getcwd() from <unixstd.h> for Linux, BSD, and POSIX systems or _getcwd() from <direct.h> for some other type.
Nitpicking: The "txt" file extension is misleading when compared with the fopen opening in binary mode, as specificed by rb.

sh: 1: Syntax error: "(" unexpected with a C file

I'm getting a confusing error message. I'm running MinGW on Windows XP 32-bit. When I attempt to compile the following code, I get an error message "./hello.c: line 4: Syntax error near unexpected token '('". Line 4 is at int main(...), I can't figure out what unexpected token is "near '('". I've tried using int main(void), but I get the same message. However, if I compile it without the "char string..." and "data = fputs(...)" and have it read from a given text file, it compiles without issue.
What I'm trying to accomplish is to read from a file where the filename is given by an external source, i.e. php. Eventually I'm going to be working this into an Apache module with a parser that I've made, hence the call from php, but I wanted to fool around and build some template code to work with before I got to that part.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
FILE *fp;
//char string = "JD"; commented out
char data;
//printf("Type in your filename: "); also commented out
//scanf("%s", &argv); also commented out
if(argc >= 2)
{
fp = fopen("sample.txt", "r"); //switched to reading a given file
}
while((data = getchar()) != EOF)
{
fgets(data, sizeof(data), fp);
// data = fputs(string, fp);
}
if (fp==NULL) /* error opening file returns NULL */
{
printf("Could not open player file!\n"); /* error message */
return 1; /* exit with failure */
}
/* while we're not at end of file */
while (fgets(data, sizeof(string), fp) != NULL)
{
printf(data); /* print the string */
}
fclose(fp); /* close the file */
return 0; /* success */
}
Okay, I tried writing a simple "Hello World" program, but I'm still getting the same error message with it which makes me think the error message isn't being caused by my code at all.
#include <stdio.h>
int main(void) //still getting a syntax error before unexpected token '('
{
printf("Hello, world!");
return 0;
}
There is problem with your logic . the "exploit" array would contain "./myotherAAAAAAAAAAAAAAAAAAAA:" which you are passing to system ..so problem are bound to happen
strncpy(command, "./myotherfile ", 9);
only copies the first 9 chars. Replace that with
strcpy(command, "./myotherfile ");
which should do what you want.
P.S. I suspect that you originally had
strncpy(command, "./myfile ", 9);
which would have worked, and you didn't change the 9 when you changed the length of the file name. There are entire books written on why couplings like this are a bad idea and what to do instead. In this case the simplest solution is to use strcpy so you don't need to mention the length.
I think you are trying to run ./motherfile...Then when you concatenate it with "exploit" name becomes "./myotherAAAAAAAAAAAAAAAAAAA " and not "./myotherfile AAAAAAAAAAAAAAAAAAAA", to give space concatenate it with a space first.

Why does "w" in fopen here not create a new file?

The program always ends up exiting. I seem to be running in to this problem frequently and I think I somehow previously fixed it but I'm not sure how. Why does it not create a file?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main (void){
FILE *fp;
int c;
char file_w[100];
char string[100];
printf("Enter filename\n");
fgets(file_w, 100, stdin);
fp = fopen(file_w, "w");
if (fp == NULL){
printf("Can't open file\n");
exit(0);
}
printf("Enter a string");
fgets(string, 100, stdin);
for(c = 0; c <= sizeof(string); c++)
{
fprintf(fp, "%s\n", string);
}
printf("file written");
fclose(fp);
return 0;
}
Try to print the name of the file you have entered:
printf("%s\n", file_w);
just after the line you get file_w, just to be sure to enter what you want. I same cases the terminal could be wrongly configured.
Try to enter an absolute name path, if your computer is a Linux or Unix:
/tmp/newfile.txt
If your computer is Windows... Well try to see if C:\temp\ exist (or create it) and then enter:
C:\temp\newfile.txt
In any case, remember that you can specify an absolute path, and not only the file name. So double check if you have the rights (i.e. the permissions) to write into the directory where the file should be written.
In case you want check the error and have a better description of the problem try to use the following lines instead of your code, just under the fopen
if( fp == NULL ) {
// Error, as expected.
perror( "Error opening file" );
printf( "Error code opening file: %d\n", errno );
printf( "Error opening file: %s\n", strerror( errno ) );
exit(-1);
}
strerror it is a wonderful function just because return you a description of the problem instead of an error code.
I bet the problem is "invisible character after actual name from fgets()". I'll let you figure out exactly what that character is, where it comes from and how to fix it, as "struggling to solve a problem" is part of the learning process when it comes to programming. If it was easy, everyone could do it.
If the return value of fopen is NULL it means some error occurred. I suggest you look into the errno global to see what error has occurred to help you debug why it's not opening the file.
The w flag does the following:
write: Create an empty file for output operations. If a file with the same name already exists, its contents are discarded and the file is treated as a new empty file.
So it should create a file when none exists, or when it does exist, overwrite its content.
If it does not do that, you have another problem, but from the little information you've given, it's hard to tell what it is.
I tried as a name of file the following:
C:\\temp\\test_file.txt
or
fopen("C:\\temp\\employees.txt", "w");
and it works fine, without errors (I made it in Windows 10. GCC win32, Version: 6.3.0).
I think that you have to use an absolute path to create the file.
use gets() instead of fgets()...it will work
.
.
gets(file_w);
.
.

Resources