I would write a program as follows
int main ()
{
FILE *fp = fopen("test.txt", "r")
if (fp == NULL)
{
printf("Sorry, file doesn't exist.");
return 0;
}
return 0;
}
Is there any other check that I would need to make sure before or after opening a file?
What if the opening of a file can damage the system(virus)? is there any check for that?
What if the file is not a .txt file, user just renamed mp3 file to a txt file?
No other check needed.
I always also make it a practice of calling fclose, however, when done with the FILE*.
The mode r should be used to open text files only. Different systems have different ways of storing text, and this mode will automatically translate the file accordingly. For instance, DOS/Windows use \r\n to represent new lines, UNIX-like systems use \n, and MAC uses \r among other possible differences.
To open and read a file truly as it is, in binary-safe mode, you should use rb.
This mode gives you full control of what you're writing to binary level, and is the only safe way to read and write binary data such as struct dumps, encrypted information etc.
after opening a file
As careful as you are when opening the file, you should as well be when reading, writing and closing it. So always check the outcome of the calls involved to do so.
I see it is an old question. However:
You may do some additional security checks to validate you are opening a real file, not a symbolic link.
Reason: replacing file by a link to another file is one of the known attack technics (related to CWE-362).
The file can be replaced by a link pointing to an engineered file containing a sequence that should hack/crash your application instead of the expected file.
So, the best practice is to add code like this:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/* Return: 0 if file is a regular file, -1 if not */
static int test_file_type(const char *file)
{
struct stat st;
if (0 != lstat(file, &st)) {
fprintf(stderr, "lstat failed, probably no such a file\n");
perror("lstat");
return (-1);
}
if (S_IFREG != (st.st_mode & S_IFMT)) {
fprintf(stderr, "Error on file [%s] opening: not a regular file, but ", file);
switch (st.st_mode & S_IFMT) {
case S_IFSOCK:
fprintf(stderr, "socket\n");
break;
case S_IFLNK:
fprintf(stderr, "symbolic link\n");
break;
case S_IFBLK:
fprintf(stderr, "block device\n");
break;
case S_IFDIR:
fprintf(stderr, "directory\n");
break;
case S_IFCHR:
fprintf(stderr, "character device\n");
break;
case S_IFIFO:
fprintf(stderr, "FIFO\n");
break;
}
return (-1);
}
return (0);
}
If this function return < 0, the file is not a regular file. Don't open it.
Also, read here
you might prefer using fopen_s. fopen_s is a newer variant of fopen that has a parameter for validation and hands back an error code instead of a pointer for the case if something goes wrong during the open process. It is safer than the base variant because it accounts for more edge conditions.
I hope you find it helpful!
Related
How do you make a file, but only if it doesn't already exist? Like.. I want to read a text file, but if it doesn't exist, I want to create one with some default text.
I can create the file with the default text easy enough. And I can append or overwrite it if it already exists.
But if it already contains some text, I want to READ FROM it. Not WRITE TO it. Like you might do with a dot file or configuration file, to set a default configuration in the event the file is missing.
This is quite simple with Python, but I'm trying to make the transition to C, and It's more challenging than I'd anticipated.
So my function basically looks something like this so far. The text is just a placeholder for whatever the real text might be.
main() {
FILE *fp;
fp = fopen("./filename.txt", "w");
fprintf(fp, "some default text\n");
fclose(fp);
}
So just to clarify: If ./file.txt already exists, it shouldn't be written to. It should be read from.
When I say "read from", it could be printed to stdout, or stored in an array for instance, but that's probably beyond the scope of the question.
Considering your example there are two main mistakes:
You don't check the result of fopen thus you don't know whether your file has been successfully opened (here is the key to the answer).
printf function prints directrly to stdout and you have to use fprintf one for printing to your configuration file.
I propose the following: try to fopen your configuration file (e.g. ./filename.txt) for r and check the result of this call. Upon successful completion fopen return a FILE pointer to your existing configuration file. If the file doesn't exist fopen returns NULL and errno is set to ENOENT. In this case you can create a new configuration file and write a default config into it.
Please see man 3 section for the corresponding docs.
UPD:
Here is PoC for the proposal
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
FILE *fp = fopen(".rc", "r");
if (!fp)
switch (errno) {
case ENOENT:
fprintf(stderr, "No config found, creating the default one\n");
fp = fopen(".rc", "w");
if (!fp) {
perror("Failed to create default config: ");
return EXIT_FAILURE;
}
/* write default config here */
break;
default:
perror("Failed to open existing config: ");
return EXIT_FAILURE;
}
/* read existing config here */
return EXIT_SUCCESS;
}
Use stat before opening your file. If the stat is successful then the file exists, if it is not, check for ENOENT in errno.
Example
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main()
{
struct stat file_infos;
char file_path[] = "/whatever"
if (stat(file_path, &file_infos) != 0)
{
if (errno == ENOENT)
{
// Do whatever when the file wasn't found
}
else
{
// Error accessing the file, check the errno for more infos
}
}
else
{
// File exists, do whatever you like with it.
}
}
Enjoy :)
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c[1000];
FILE *fptr;
if ((fptr = fopen("program.txt", "r")) == NULL)
{
printf("Error! opening file");
// Program exits if file pointer returns NULL.
exit(1);
}
// reads text until newline
fscanf(fptr,"%[^\n]", c);
printf("Data from the file:\n%s", c);
fclose(fptr);
return 0;
}
Output is Error! opening file
I have program and txt file in same dir.
How can I direct access to that file?
To diagnose, use the system command to issue a ls or dir depending on your platform. That will tell you where you are running from. Odds are it is a different location than the files you are trying to open.
As suggested in the comment, try replacing printf with perror
if ((fptr = fopen("program.txt", "r")) == NULL)
{
perror("Error");
// Program exits if file pointer returns NULL.
exit(1); // Exiting with a non-zero status.
}
perror prototype is
void perror(const char *str)
where str is the C string containing a custom message to be printed before the error message itself.
However some causes of the of the file not being read are
File is not present in the current working directory. If this is the case, rectifying the path should fix the issue.
The program might not have the permissions to read from the file usually because of a setting related to discretionary access control. Perhaps do a chmod with file?
I made a quick run of your program on TURBOC++ by Borland and it executed without complaining any sort of Warning or Error
As mentioned in the earlier posted answers, you should replace printf by perror
CURRENT REPLACE BY
printf("Error! opening file"); perror("Error! Opening File.");
As in your case of file not found printf("Error! opening file"); will result in :
Error! Opening file.
However in case of perror("Error! Opening File."); if the file program.txt does not exist, something similar to this may be expected as program output
The following error occurred: No such file or directory
The difference is obvious from above explanations.
Regarding your program, I am making an assumption that either your path to the file is wrong or there is some problem with your compiler.
Try to open your file in w+ mode also to ensure that the file exist.
Im supposed to write a program that opens an excel file, reads the numbers on the file, multiplies them by 9.8 and the shows the answer in another excel gile.
I wrote this, and I did not get any errors in the compiler, but when I run it, it does not open any files. How do I make it open the files?
#include <stdio.h>
int main() {
FILE *archivo;
FILE *archivoSalida;
int masa;
float peso;
archivo = fopen("C:/Users/nacho/Documents/UNAM/Informatica/proyecto/archivoEntrada.txt", "r");
archivoSalida = fopen("C:/Users/nacho/Documents/UNAM/Informatica/proyecto/archivoSalida.txt", "r");
if (archivo != NULL)
{
printf("The file was opened succesully");
while (fscanf(archivo,"%d", &masa)!= EOF)
{
peso=masa*9.81;
fprintf(archivoSalida, "%f\n", peso);
}
}
else
{
printf ("Error");
}
fclose(archivo);
fclose(archivoSalida);
return 0;
}
You'll want to fopen the output file ("archivoSalida") with mode "w" (for write) instead of "r" (for read). See e.g. http://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html.
You do check if the input file could be opened (if (archivo != NULL)). Why don't you do the same for the output file?
Upon an error, you should output which error occured from errno, e.g. via perror(...). That should help in finding the actual problem.
Your file denominated by archivoSalida is opened in read mode ('r').
You should also check the return codes of read/writes functions to be sure everything happen as wanted.
The file names look Windows-ish. Is it possible that all of the forward slashes (/) that you have in both file names should really be back slashes (\)?
Okay so this is probably has an easy solution, but after a bit of searching and testing I remain confused.. :(
Here is a snippet of the code that I have written:
int main(int argc, char *argv[]){
int test;
test = copyTheFile("test.txt", "testdir");
if(test == 1)
printf("something went wrong");
if(test == 0)
printf("copydone");
return 0;
}
int copyTheFile(char *sourcePath, char *destinationPath){
FILE *fin = fopen(sourcePath, "r");
FILE *fout = fopen(destinationPath, "w");
if(fin != NULL && fout != NULL){
char buffer[10000];//change to real size using stat()
size_t read, write;
while((read = fread(buffer, 1, sizeof(buffer), fin)) > 0){
write = fwrite(buffer, 1, read, fout);
if(write != read)
return 1;
}//end of while
}// end of if
else{
printf("Something wrong getting the file\n");
return 0;}
if(fin != NULL)
fclose(fin);
if(fout != NULL)
fclose(fout);
return 0;
}
Some quick notes: I am very new to C, programming, and especially file I/O. I looked up the man pages of fopen, fread, and fwrite. After looking at some example code I came up with this. I was trying to just copy a simple text file, and then place it in the destination folder specified by destinationPath.
The folder I want to place the text file into is called testdir, and the file I want to copy is called test.txt.
The arguments I have attempted to use in the copyFile function are:
"test.txt" "testdir"
".../Desktop/project/test.txt" ".../Desktop/project/testdir"
"/Desktop/project/test.txt" "/Desktop/project/testdir"
I just get the print statement "Something wrong getting the file" with every attempt. I am thinking that it may be because 'testdir' is a folder not a file, but then how would I copy to a folder?
Sorry if this a really basic question, I am just having trouble so any advice would be awesome!
Also, if you wanted to be extra helpful, the "copyTheFile" function is supposed to copy the file regardless of format. So like if its a .jpg or something it should copy it. Let me know if any of you guys see a problem with it.
This is with ISO/POSIX/C89/C99 on Linux.
At the start, you'll want to include stdio.h to provide FILE and the I/O function declarations:
#include <stdio.h>
Aside from this, your program compiles and works properly for me. Unfortunately you can't copy to a directory without using stat() to detect if the destination is a directory, and if so, appending a file name before opening the file.
Some other minor suggestions:
A buffer with a power of two bytes such as 4096 is probably more efficient due to it lining up with filesystem and disk access patterns
Conventionally, C functions that return a status code use 0 for success and other values such as 1 for failure, so swapping your return values may be less confusing
When a standard library function such as fopen, fread or fwrite fails, it is a good idea to use perror(NULL); or perror("error prefix"); to report it, which may look something like:
$ ./a.out
...
error prefix: No such file or directory
if you are trying to write a new file in a directory, you should be giving the full path of the file to be written. in your case
"C:...\Desktop\project\testdir\testfile"
I'm trying to make a program to open a file, called "write.txt".
#include <stdio.h>
main() {
FILE *fp;
fp = fopen("write.txt", "w");
return 0;
}
Should this work? Because it returns nothing.
Other than an old variant of main, there's not really much wrong with that code. It should, barring errors, create the file.
However, since you're not checking the return value from fopen, you may get an error of some sort and not know about it.
I'd start with:
#include <stdio.h>
#include <errno.h>
int main (void) {
FILE *fp;
fp = fopen ("write.txt","w");
if (fp == NULL) {
printf ("File not created okay, errno = %d\n", errno);
return 1;
}
//fprintf (fp, "Hello, there.\n"); // if you want something in the file.
fclose (fp);
printf ("File created okay\n");
return 0;
}
If you're adamant that the file isn't being created but the above code says it is, then you may be a victim of the dreaded "IDE is working in a different directory from what you think" syndrome :-)
Some IDEs (such as Visual Studio) will actually run your code while they're in a directory like <solution-name>\bin or <solution-name>\debug. You can find out by putting:
system ("cd"); // for Windows
system ("pwd") // for UNIXy systems
in to your code to see where it's running. That's where a file will be created if you specify a relative path line "write.txt". Otherwise, you can specify an absolute path to ensure it tries to create it at a specific point in the file system.
What did you expect it to 'return' - it opens a file, on most platforms creating one if it doesn't exist.
You should probably fclose(fp) the file at the end.
I think you want to print the contents of file write.txt. (Assume it contains characters).
#include <stdio.h>
int main()
{
FILE *fp,char ch;
fp=fopen("write.txt","r");
if(fp==NULL)
{
printf("Some problem in opening the file");
exit(0);
}
else
{
while((ch=fgetc(fp))!=EOF)
{
printf("%c",ch);
}
}
fclose(fp);
return 0;
}
I think you should study some more fundamentals in C before you start attempting to work with files. A return means some data is passed back to the calling code from the called function.In this case you return 0 at the end of your program. You did not do anything with your FILE pointer except cause a new file to be created...