[A4] file_exists() sometimes won't detect a folder within the user's Desktop
raynebc

The program I develop will sometimes, but not always, run into a problem where a call to file_exists() with (FA_DIREC | FA_HIDDEN) as the given attributes will fail to detect a folder that certainly exists. Usually when this comes up it's within the user's own Desktop folder, and the OS is Windows 10. I don't really remember seeing this problem on previous versions of Windows going back to Windows XP. Is there some OS behavior known to cause this? Are there any better ways I can check that the folder exists?

Edgar Reynaldo

Do you have a basic program I can try? I use Windows 10. I can check the desktop folders for files or such...

EDIT
Did you try opening the actual location of the file? Call file_exists with the c:\users\x\desktop\blah.blah file?

I ran my old Eagle 4 classic demo, and it has a file explorer. I can navigate to the folder and locate a hidden test folder I just created.

I should note I'm enumerating the directory, not checking if 'file_exists'.

raynebc

The program has the user specify a folder path for the project they're creating, so the folder being checked isn't guaranteed to exist. So the program checks if it exists, and if it can't tell that it does, it uses _wmkdir() in the Windows build and then checks to make sure the folder now exists before attempting to write files to the folder.

I'm not even convinced this affects all of my Windows 10 user base. That, or very few of them save their projects into their Desktop. If you wanted to try the executable, here's the base Windows release:
http://ignition.customsforge.com/eof/download/357
and a hotfix that replaces older files in that:
http://ignition.customsforge.com/eof/download/376

The relevant portion of code is here:
https://github.com/raynebc/editor-on-fire/blob/master/src/menu/file.c#L453

To take an approach like yours, should I consider enumerating the parent of the folder being tested to see if the target folder is shown to exist? I have to wonder if using al_findfirst() and al_findnext() would run into the same inability to see the folder, assuming they can search for folders instead of just actual files?

Edgar Reynaldo

On first glance at my old code it looks like I'm using for_each_file_ex on a directory.

It also seems I used a specific way to find if a directory exists or not, using a system call and 'cd'.

#SelectExpand
1 2 3#include <cstdlib> 4#include <cstdio> 5 6int main(int argc , char** argv) { 7 8 if (argc != 2) { 9 return 1; 10 } 11 12 char command[4096]; 13 sprintf(command , "cd %s" , argv[1]); 14 15 bool exists = !(system(command)); 16// printf("cd x returns %i\n" , system("cd x"));// returns 1 on Windows, returns 256 on OpenSUSE 17// printf("cd build returns %i\n" , system("cd build"));// returns 0 18 19 if (exists) {printf("Exists\n");} else {printf("Does not exist\n");} 20 21 return 0; 22}

raynebc

Changing directory to the folder to see if it exists is worth a shot. I'll give that a try. Thank you.

Edgar Reynaldo

I never tested that on MacOS, so ymmv

raynebc

It should work, the *nix/Mac build of the program just use the normal chdir() function and it behaves properly. Worst case scenario I just limit the change directory test to the Windows build. Either way I'll probably only use that as a second test if file_exists() indicates the folder does not exist.

Edgar Reynaldo

Try using FA_ALL with file_exists - that shouldn't exclude any files or directories of any kind.

raynebc said:

a problem where a call to file_exists() with (FA_DIREC | FA_HIDDEN) as the given attributes will fail to detect a folder that certainly exists.

That would only look for hidden directories if I understand correctly.

raynebc

The documentation says it would include results that are directories OR hidden:
https://www.allegro.cc/manual/4/api/file-and-compression-routines/

I don't remember why we added FA_HIDDEN, it must have made it work better in the past.

Edgar Reynaldo

You should really use the updated docs from liballeg.org .

Yes, but it also excludes read only and system files.

When passed to the functions as the 'attrib' parameter, these flags represent an upper set in which the actual flag set of a matching file must be included. That is, in order for a file to be matching, its attributes may contain any of the specified flags but must not contain any of the unspecified flags. In other words, you explicitly exclude the flags that you do not specify. Thus if you pass 'FA_DIREC | FA_RDONLY', normal files and directories will be included as well as read-only files and directories, but not hidden files and directories. Similarly, if you pass 'FA_ARCH' then both archived and non-archived files will be included. If FA_NONE is passed all attributes are excluded and only files with no attributes are returned. Conversely, if you pass FA_ALL, no attributes are excluded so all files are returned (which is what you would usually want).

raynebc

I do want it to only check for directories though, if I pass FA_ALL, I'm not sure that's what it will accomplish. Your change directory method seems like it will be a reliable way to go. I think the hidden attribute was included because of Windows' odd behavior of using read only status for folders to do something like indicate it has an INI folder to process to control its display.

Edgar Reynaldo

You can check the return flags to see if it's a file or a directory :

int file_exists(const char *filename, int attrib, int *aret);

Checks whether a file matching the given name and attributes (see beginning of this chapter) exists. If `aret' is not NULL, it will be set to the attributes of the matching file. Example:

/* Check for a normal file. */
if (file_exists("franken.dat", 0, NULL))
allegro_message("It is alive!\n");

Return value: Returns non-zero if the file exists, or zero if it doesn't or the specified attributes mask it out.

Use 'aret' to get the return flags and & it with FA_DIREC to see if it is a directory.

Thread #617914. Printed from Allegro.cc