Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » al_make_path_canonical() issue

This thread is locked; no one can reply to it. rss feed Print
al_make_path_canonical() issue
Bruce Pascoe
Member #15,931
April 2015
avatar

Currently al_make_path_canonical() doesn't collapse ".." pieces. The documentation says this is by design to preserve symlink semantics, however there are certain sandboxing scenarios where collapsing the ".." anyway (without resolving symlinks) would actually be desirable. Could we add an optional boolean parameter to the function for this purpose?

Thomas Fjellstrom
Member #476
June 2000
avatar

Currently al_make_path_canonical() doesn't collapse ".." pieces. The documentation says this is by design to preserve symlink semantics, however there are certain sandboxing scenarios where collapsing the ".." anyway (without resolving symlinks) would actually be desirable. Could we add an optional boolean parameter to the function for this purpose?

I don't know how safe that is. collapsing .. means it'd have to remove the previous dir in the chain, but the parent in the dir string may not actually be the correct parent... I don't think we can just add a parameter, probably have to add another function for that.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Elias
Member #358
May 2000

Just to clarify, if there is a symlink:

data/trees -> /myart/treegame/rendered

And the game has a path like this:

data/trees/../tree.png

Then the actual file is at: /myart/treegame/rendered/../tree.png which is /myart/treegame/tree.png

If you collapse the ".." instead you end up with: data/tree.png which does not exist.

What we could do is add a function "al_make_path_absolute" which is aware of symlinks and returns the absolute path without any symlinks to a file. Right now nothing similar to this exists at all though and I'm not sure if we want such a specialized function.

--
"Either help out or stop whining" - Evert

Bruce Pascoe
Member #15,931
April 2015
avatar

Yes, I'm aware of the symlink issue. However, there are certain scenarios, e.g. sandboxing, where this is actually desirable. Say you want to sandbox your game to a specific directory, now within the game engine the game constructs a path like this:

data/trees/../tree.png

Because the game is sandboxed, the game engine expects that to refer to the same file as data/tree.png, following the symlink would violate that assumption.

Thomas Fjellstrom
Member #476
June 2000
avatar

Is there a specific reason you even need to bother?

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Bruce Pascoe
Member #15,931
April 2015
avatar

Yes, my game engine, minisphere, has the ability to run a game from a package file, where within the package index each file is stored with its full path as its filename, like this:

images/ScottSucks.png
sounds/BGM/ThePromise.ogg

If a game within that package does, say:

var image = new Image("../fatpig_images/maggie.png");

The path the engine constructs for this internally ends up being:

images/../fatpig_images/maggie.png

When running an unpackaged game, this succeeds because the operating system resolves it. But for a package, the engine returns a file not found because the index lookup fails. In order for it to succeed, the path has to be canonized to:

fatpig_images/maggie.png

Which Allegro won't do.

Thomas Fjellstrom
Member #476
June 2000
avatar

I tend to prefer to have a manager that takes "names" of resources, generally they look like filenames, and can be resolved as such, but don't have to be. And they generally never have ..'s in them.

Your example doesn't make all that much sense to me. A .. should still resolve in a "package", at least assuming if your package api is sane.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Bruce Pascoe
Member #15,931
April 2015
avatar

Indeed, that's the way I have it set up, there's a sandbox manager within the game which takes a resource path and resolves it for the underlying FS type (local or package). The rest of the engine doesn't care where the resource is.

The trouble is, I have to be compatible with the Sphere engine, which accepts paths containing .. For games running from the local FS, this works fine. But the SPK package format (which I didn't invent) stores all resources with their full path as a filename--there is no concept of a directory in an SPK package. So in order to allow .. in a resource name, the path has to be pre-resolved. Thats where I'm having trouble.

Thomas Fjellstrom
Member #476
June 2000
avatar

How do you treat leading ..'s? say your whole path is '../foo/bar/baz.xyz', you can't just remove it and have it be proper...

Ignoring that, here's something you can use:

#SelectExpand
1#include <allegro5/allegro5.h> 2#include <stdio.h> 3 4bool make_path_canonical_ex(ALLEGRO_PATH *path) 5{ 6 unsigned i; 7 ALLEGRO_ASSERT(path); 8 9 for (i = 0; i < al_get_path_num_components(path); ) { 10 if (strcmp(al_get_path_component(path, i), ".") == 0) 11 { 12 al_remove_path_component(path, i); 13 } 14 else if(strcmp(al_get_path_component(path, i), "..") == 0) 15 { 16 al_remove_path_component(path, i); 17 if(i > 0) 18 { 19 i--; 20 al_remove_path_component(path, i); 21 } 22 } 23 else 24 { 25 i++; 26 } 27 } 28 29 return true; 30} 31 32void test_path(const char *pstr) 33{ 34 ALLEGRO_PATH *path = al_create_path(pstr); 35 al_make_path_canonical(path); 36 37 printf("path: '%s' -> '%s'\n", pstr, al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP)); 38} 39 40int main(int argc, char **argv) 41{ 42 al_init(); 43 44 test_path("../foo/bar/baz.zyz"); 45 test_path("../foo/bar/../baz.xyz"); 46 test_path("foo/../baz.xyz"); 47 test_path("/foo/bar/../baz.xyz"); 48 49 return 0; 50}

Not 100% tested, but that shows at least those types of paths work.

moose@balsa:~/projects$ ./al_make_path_canonical_ex 
path: '../foo/bar/baz.zyz' -> 'foo/bar/baz.zyz'
path: '../foo/bar/../baz.xyz' -> 'foo/baz.xyz'
path: 'foo/../baz.xyz' -> 'baz.xyz'
path: '/foo/bar/../baz.xyz' -> '/foo/baz.xyz'

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Bruce Pascoe
Member #15,931
April 2015
avatar

At least in my case, the sandbox manager will never generate a path with leading .. as all asset loading functions in Sphere are defined as being relative to some subdirectory or another, which is prepended to the path given by the user (hence why I have to support .. in the first place). Even if it did though, removing it would be fine as the game directory is defined as the root, so it's the same deal as, say C:\..\maggie.fat.

Thanks for the code though, that should work fine. :)

Thomas Fjellstrom
Member #476
June 2000
avatar

That code will remove the leading "empty" component that tells the code that that's an absolute path. So C:\..\file.ext may actually become "file.ext".

I actually just meant "..\foo\file.ext", as removing .. cant remove something before it, and removing .. in that case makes the path pretty meaningless.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Bruce Pascoe
Member #15,931
April 2015
avatar

Yeah, I already handle absolute paths separately because they always refer to the physical file system. The package manager never sees them. The package manager only sees paths of the form:

images/tiles/tree.png

Within the context of a package, the path above is actually absolute, even though it would be considered relative in most other contexts. So for this use case there will never be an issue of an absolute path being converted to a (meaningless) relative one, and naive ".." collapsing is sufficient.

Honestly I wasn't aware of al_remove_component() etc. For whatever reason I assumed Allegro paths were like strings, mostly immutable. So thanks again!

Thomas Fjellstrom
Member #476
June 2000
avatar

Yeah, the whole idea behind the path api is to make paths mutable, and more useful, especially cross platform.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Go to: