• Advertisement
Sign in to follow this  

check extensions

This topic is 3222 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Why does ifstream successfully open a directory? Sometimes I want infile.open(whatever) to fail if it's fed a non-existent file name. But if I pass it something like "home/icecube/" it opens successfully even though it didn't open a file. So then it tries infile>>inum or something and my program crashes. I guess I can make sure that that function is never called unless it's given valid file. Or maybe within the function I can check to see if the extension is correct in addition to checking if the file opened correctly? I know I only I only want to open .ani files. I guess I could do something like this: temp=anifile[anifile.length()-4]; temp+=anifile[anifile.length()-3]; temp+=anifile[anifile.length()-2]; temp+=anifile[anifile.length()-1]; infile.open(anifile.c_str()); if(temp==".ani"&&infile.fail()==false) { //do stuff } But that's sort of crazy. I'm changing a lot of stuff, in the near future this won't matter because I won't be sending the function bad filenames. But still this seems like something I should know the answer to.

Share this post


Link to post
Share on other sites
Advertisement
#include <fstream>
#include <iostream>

int main()
{
std::ifstream foo("blah.txt"); // That file does not exist.

std::cout << "open: " << foo.is_open() << std::endl;

}


That prints open: 0 for me, proving that the file was in fact, no open.
If you were to try and perform read operations on it, only then would foo.fail() become true.

Share this post


Link to post
Share on other sites
Actually I tried that right before you posted. It doesn't work for me. My problem isn't sending it a file that does not exist. My problem is if I sent it a DIRECTORY that does exist. Below if anifile=="Data/Anibox/" which is a directory then infile.is_open==true!

I want to keep from entering the if statement if a directory is passed.


infile.open(anifile.c_str());

if(infile.is_open())
{
Death();

name=anifile;

infile>>itype;
infile>>isize;
infile>>iloop;
ipics=new GLuint[isize];

for(ix=0;ix<isize;ix++)
{
infile>>temp;
temp="Data/Images/"+temp;
picbox->ImageLoader(temp,ipics[ix]);
}
}

Share this post


Link to post
Share on other sites
Quote:
Original post by icecubeflower
Below if anifile=="Data/Anibox/" which is a directory then infile.is_open==true



#include <iostream>
#include <fstream>

int main()
{
std::cout << std::ifstream("somedir").is_open() << std::endl;
}


That does not happen for me with VS8 (though it would with gcc under *NIX, as a directory is a file, as is almost anything else).

What compiler are you using?

Quote:
I want to keep from entering the if statement if a directory is passed.


C++ I/O knows nothing about directories. You will either need to use platform-specific APIs to detect whether you are dealing with a file or with a directory.
For C++, portable results, I suggest using Boost's file I/O utilities.

Share this post


Link to post
Share on other sites
Oh yeah, that "everything is a file on unix" thing. Yeah I'm using g++ on Linux. I'm also compiling it on windows, though.

I don't want to include boost. Eventually I won't be sending the function directories so it won't matter. It just sort of bugged me that is_open() wouldn't fail. I guess I'll just check for a .ani extension for now.

Share this post


Link to post
Share on other sites
Quote:
Original post by icecubeflower
Oh yeah, that "everything is a file on unix" thing. Yeah I'm using g++ on Linux. I'm also compiling it on windows, though.


Create a /linux and a /win32 directories in which you stick OS-specific implementations of utility functions. Then write two implementations of a is_directory() function, using stat() on Linux, and GetFileAttributes() on Win32.

Then, depending on your platform, you compile one directory or another. No, I'm not a big fan of mixing multiple-platform code in a single file through conditional compilation.

Quote:
I don't want to include boost.

*shrug*

Quote:
Eventually I won't be sending the function directories so it won't matter.

That kind of reasoning is how security holes happen.

Quote:
It just sort of bugged me that is_open() wouldn't fail.

Note that read operations will still fail if you open a directory.

Quote:
I guess I'll just check for a .ani extension for now.

Just keep in mind that a directory can too end in ".ani". ;)

Share this post


Link to post
Share on other sites
Quote:

Quote:

Eventually I won't be sending the function directories so it won't matter.


That kind of reasoning is how security holes happen.


Does it really matter? I mean suppose someone does send the function a .ani file but the format is all wrong. Suppose I'm expecting int, int, int, string, string, string, in the file. But they give me some file with garbage in it. That will still crash my program. I mean if I go in the directories of any of the store-bought professional games I have and replace their data files with files with the same name but filled with random characters then those programs crash too. I mean if we're not checking the the file format is perfect then why would checking that a directory is not passed be any more important?

Share this post


Link to post
Share on other sites
If you are serious about becoming a professional software developer then yes, it does matter quite a bit. Ensuring your program behaves in a controlled manner when fed bad data is very important.

I would be very much surprised if those commercial games you mentioned really crashed when fed bad data, the way it happens when the operating system kills your process for an access violation, for example, rather than logging an error (cannot open file, bad data format, bad checksum, etc) and cleanly shutting down.

Here and now, for your specific program, it may not matter, but that is not code you can be proud of.

Share this post


Link to post
Share on other sites
Well. Do you have any links for me to read or something? I don't know how to make sure that the .ani file my function receives is formatted correctly. I mean if I'm expecting int isize, int, int and then isize strings but instead the file contains three random numbers followed by a random number of strings or it goes int, int, strings then I don't know what will happen.

What if I find that it is formatted incorrectly? Use that try, catch thing? Throw an exception? Exit?

A lot of stuff I have pretty robust. I'm still putting try catch blocks where I allocate dynamic memory. And whenever an image file does not exist I just return 0's so the game keeps playing but it gets blank images. But yeah, if a file is formatted crazy, I guess I have to check for that somehow.

Share this post


Link to post
Share on other sites
If you have formatted data, you can check each field individually, as well as make sure that the sequence of fields is correct (in a related note, XML schemas are used to validate XML files). If you have binary data, you'll have to rely on checksums and/or record delimiters. You'll also need, in any case, to verify that the values you receive are sensible (what that means depends on your program).

As for what to do when you find an invalid file, it is up to you - it depends in how you've designed your entire application. The main guiding principle for exception handling is to catch them where you can do something about them (which is not necessarily the point where they occur).


What happens when things are not as perfect as you expected is important (e.g. to avoid problems like denial of service), but even if you have to choose sub-obptimal behavior (e.g. shutting down the program), it's better than not knowing what happens (e.g. your machine getting pwned).

Share this post


Link to post
Share on other sites
I don't really see why shutting down the game would be sub-optimal behavior. I guess if my program was fed a bad .ani file then I could just skip the animation. But monsters and stuff rely on files as well. If the program finds that it is trying to read a corrupt monster file then I'd rather just exit and say "Bad monster file." That seems pretty optimal to me.

Share this post


Link to post
Share on other sites
For your game, today, it most likely does not matter. But if, say, Blizzard's Battlenet servers shut down every time someone with an out-of-date (or pirated) copy of Starcraft attempts to connect using an invalid protocol, or has a slight network glitch (for which networking protocols like TCP already compensate much) there would much howling on the Internet.

Share this post


Link to post
Share on other sites
Well yeah. I just mean for my game, say a new map is trying to load and it wants to load some monster called a gremlin. If it tries loading the gremlin file and the file doesn't make any sense I think I have two options: 1-Continue the game but just don't load a monster or 2-Exit. I think I'd rather exit.

Share this post


Link to post
Share on other sites
Quote:
Original post by icecubeflower
Why does ifstream successfully open a directory?

Sometimes I want infile.open(whatever) to fail if it's fed a non-existent file name. But if I pass it something like "home/icecube/" it opens successfully even though it didn't open a file. So then it tries infile>>inum or something and my program crashes.


So write the program in such a way that it doesn't crash if an input request fails. I've already linked you to a resource that explains what happens when input requests fail. Here's another.

Share this post


Link to post
Share on other sites
You know, a program actually crashes instantly if you open a directory as a file and try reading into an int. I just rewrote a bunch of stuff, checking to see if file I/O failed and it was useless. If you open a legitimate file and keep reading in after you hit eof it just sets the fail bits to true. If you try reading in from a ifstream that opened a directory=instant crash. I guess I have to actually make sure I didn't open a directory.

Share this post


Link to post
Share on other sites
Suppose I programmed a lot of structures. So one structure contains another. Suppose the outer structure opens a file and checks to make sure that it didn't open a directory. Then it passes the stream to another structure. So I know that the sub structure does not need to check anything about the file.

Is that bad? Should I make any function that is passed a stream check the stream even though I know the outer structure checked it already?

I mean realisitically I know it would only matter if someday someone used one of my inner structures in a different project and then nothing would be checking the stream. And I seriously doubt that's going to happen. But I guess I want to do the professional thing either way.

Share this post


Link to post
Share on other sites
neat stuff:
("crud/edumacation"=file "crud/darkimage"=directory")

#include <fstream>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
std::ifstream infile;
int ival;
int ix;
struct stat statbuf;

stat("crud/edumacation", &statbuf);
if(S_ISREG(statbuf.st_mode))
std::cout<<"crud/edumacation is a regular file\n";
else
std::cout<<"crud/edumacation is not a regular file\n";
if(S_ISDIR(statbuf.st_mode))
std::cout<<"It's a directory\n";

stat("crud/darkimage",&statbuf);
if(S_ISREG(statbuf.st_mode))
std::cout<<"crud/darkimage is a regular file\n";
else
std::cout<<"crud/darkimage is not a regular file\n";
if(S_ISDIR(statbuf.st_mode))
std::cout<<"It's a directory.\n";

return 0;
}




output:

icecube@inferno:~$ filecrash
crud/edumacation is a regular file
crud/darkimage is not a regular file
It's a directory.
icecube@inferno:~$




One thing I don't understand at all though is why do I have to say:
struct stat statbuf;

Why can't I just say:
stat statbuf;

That doesn't make any sense to me at all.

Share this post


Link to post
Share on other sites
stat is both a struct name and a function name. You need to say struct stat to specify that you want the struct name rather than the function name.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement