al_get_path_tail changes in 5.1.5?

I have upgraded from Allegro 5.0.8 to 5.1.5 and noticed this weird al_get_path_tail issue. Here is the pseudo code that is trying to read all files in C:/mydir (where "mydir" has a single directory inside named "test").

1ALLEGRO_FS_ENTRY* myDir = al_create_fs_entry("C:\\mydir"); 2 3if (al_open_directory(myDir)) { 4 5 ALLEGRO_FS_ENTRY* nextFile; 6 while (nextFile = al_read_directory(myDir)) { 7 8 const char* nextFilePath = al_get_fs_entry_name(nextFile); 9 10 // nextFilePath == "C:\\mydir\\test" 11 12 ALLEGRO_PATH* nextFilePathA = al_create_path(nextFilePath); 13 14 const char* nextFileName = al_get_path_tail(nextFilePathA); 15 16 // nextFileName == "mydir" when expecting "test" 17 18 al_destroy_path(nextFilePathA); 19 al_destroy_fs_entry(nextFile); 20 } 21 22 al_close_directory(myDir); 23} 24 25al_destroy_fs_entry(myDir);

In short - al_get_path_tail does not really return the last part/tail of a path, but one above it.

Note, that I am using PhysFS addon. Is this a bug or an intended change/feature?

Edit: Replacing al_create_path with al_create_path_for_directory fixed the issue when reading directories. Still, I would like to understand why this change was introduced in 5.1 branch.


Both functions al_create_path and al_creat_path_from_directory exist since 5.0. I guess that this means that the previous behaviour was actually a bug???

beoran said:

Both functions al_create_path and al_creat_path_from_directory exist since 5.0. I guess that this means that the previous behaviour was actually a bug???

I doubt it. More likely something isn't right in 5.1. It looks like al_create_path is now expecting a path for directories with the end slash/separator included? If that is the case - the File-System module functions don't play well with Path module functions (as al_get_fs_entry_name is returning paths without the end directory separator included).

The PhysFS addon could also be an issue here..

Thomas Fjellstrom
simast said:

In short - al_get_path_tail does not really return the last part/tail of a path, but one above it.

It returns the last directory in the path. If you pass in a path without a trailing slash, it interprets the last item as a filename, and if it has a trailing slash, its interpreted as a directory. I'm pretty sure it's always been like that. But al_create_path_for_directory was added because its quite annoying having to append a slash to a string gotten from some of the other functions all the time just to properly build an ALLEGRO_PATH for a path to a directory.

As far as I can recall this behaviour hasn't changed at all. The current behaviour of treating a path without a trailing slash as a directory with a file is what I had intended from the beginning. It had been modified a couple times since I wrote it and I can't remember exactly what got changed, but I don't think that did.

Maybe it's not the best design, my main reason for separating out the filename was so we could actually provide a proper "get filename" function, meaning you can tell the path functions that a given path contains a filename, and you can then get it. Rather than just having the get filename function always returning the last path component, even if its actually intended to be a directory.


Hi Thomas,


I'm pretty sure it's always been like that. As far as I can recall this behavior hasn't changed at all.

I have never had issues with that part of my code - it only started behaving differently when I have upgraded from 5.0.8 to 5.1.5. There must be some sort of a change somewhere there.

I think the real problem is illustrated with this code below:

  // Test Filesystem API
  ALLEGRO_FS_ENTRY* testFS = al_create_fs_entry("C:\\Windows\\");
  const char* testFSResult = al_get_fs_entry_name(testFS);

  // testFSResult is "C:\\Windows" (note the lack of trailing slash)

  // Test Path API
  ALLEGRO_PATH* testPath = al_create_path("C:\\Windows\\");
  const char* testPathResult = al_path_cstr(testPath, ALLEGRO_NATIVE_PATH_SEP);

  // testPathResult is "C:\\Windows\\" (with a trailing slash)

The Filesystem and Path APIs no longer work in tandem (the same).

Thomas Fjellstrom

Some things have changed, but I'm not sure it was the PATH api that changed, at least not in that regard. At the very least the PATH api is acting as intended, and the FS ENTRY stuff is also acting as intended. It's a bit annoying that they don't match up.

I think the FS stuff used to append a slash on every path that was a directory on windows to work better with win32 API functions that just don't work properly if you don't. But things were tweaked at one point to change that.

I could swear there was a way to get an FS_ENTRY directly from a PATH, but I can't seem to find it atm.

I'm not sure there's a way to properly fix this, as readdir just returns a bare string and you have to separately "stat" it to get its type.

I think if you want to keep the same behaviour you had, just always use al_create_path_for_directory, then you just have to ignore the filename and extension parts of the PATH api.

Peter Wang

path.c hasn't changed since 2010.

The behaviour of al_get_fs_entry_name was changed in 5.1.5, but it was never intended to preserve exactly the string that you passed in.

On Windows we have to strip trailing slashes before calling stat(). So the ALLEGRO_FS_ENTRY had a copy of the path, but we would copy it and strip it when calling stat(). But we were stripping it incorrectly, and since ALLEGRO_FS_ENTRY has a canonical copy of the path, why not strip it once when the entry is created and do it correctly? It just happens that al_get_fs_entry_name returns a pointer to the same canonical path, which is why you see the behaviour change.


I thought there might be something broken in 5.1 branch, but it looks like it's just a small BC break I can code around easily. Thanks, Peter, Thomas.

Thread #611986. Printed from