Merge pull request #90 from gizmo98/patch-2
[libretro-ppsspp.git] / Core / realpath.c
blob607206c87c0885e97d61094b462010bf368e96f8
1 /* realpath.c
2 * $Id$
4 * Provides an implementation of the "realpath" function, conforming
5 * approximately to SUSv3, and adapted for use on native Microsoft(R)
6 * Win32 platforms.
8 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
10 * This is free software. You may redistribute and/or modify it as you
11 * see fit, without restriction of copyright.
13 * This software is provided "as is", in the hope that it may be useful,
14 * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
15 * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
16 * time will the author accept any form of liability for any damages,
17 * however caused, resulting from the use of this software.
21 #include <io.h>
22 #include <stdlib.h>
23 #include <errno.h>
25 char __cdecl
26 *realpath( const char *__restrict__ name, char *__restrict__ resolved )
28 char *retname = NULL; /* we will return this, if we fail */
30 /* SUSv3 says we must set `errno = EINVAL', and return NULL,
31 * if `name' is passed as a NULL pointer.
34 if( name == NULL )
35 errno = EINVAL;
37 /* Otherwise, `name' must refer to a readable filesystem object,
38 * if we are going to resolve its absolute path name.
41 else if( access( name, 4 ) == 0 )
43 /* If `name' didn't point to an existing entity,
44 * then we don't get to here; we simply fall past this block,
45 * returning NULL, with `errno' appropriately set by `access'.
47 * When we _do_ get to here, then we can use `_fullpath' to
48 * resolve the full path for `name' into `resolved', but first,
49 * check that we have a suitable buffer, in which to return it.
52 if( (retname = resolved) == NULL )
54 /* Caller didn't give us a buffer, so we'll exercise the
55 * option granted by SUSv3, and allocate one.
57 * `_fullpath' would do this for us, but it uses `malloc', and
58 * Microsoft's implementation doesn't set `errno' on failure.
59 * If we don't do this explicitly ourselves, then we will not
60 * know if `_fullpath' fails on `malloc' failure, or for some
61 * other reason, and we want to set `errno = ENOMEM' for the
62 * `malloc' failure case.
65 retname = (char*)malloc( _MAX_PATH );
68 /* By now, we should have a valid buffer.
69 * If we don't, then we know that `malloc' failed,
70 * so we can set `errno = ENOMEM' appropriately.
73 if( retname == NULL )
74 errno = ENOMEM;
76 /* Otherwise, when we do have a valid buffer,
77 * `_fullpath' should only fail if the path name is too long.
80 else if( (retname = _fullpath( retname, name, _MAX_PATH )) == NULL )
81 errno = ENAMETOOLONG;
84 /* By the time we get to here,
85 * `retname' either points to the required resolved path name,
86 * or it is NULL, with `errno' set appropriately, either of which
87 * is our required return condition.
90 return retname;
93 /* $RCSfile$: end of file */