I'd seen some ancient code that simplifed Unix paths for comparison by doing something like the following pseudocode:
- strip off the last path component to get a directory only part: /foo/bar -> /foo
- getcwd and remember original path
- chdir /foo
- getcwd and remember to return to caller
- chdir old original path
Is there a standard Unix system function that does all this without the thread unsafe current directory manipulation?
A mutex could make that code sequence le开发者_如何学Pythonss thread unsafe, but isn't really ideal (you'd have to know that all other code using getcwd or other functions dependent on the process cwd including system and vendor code protects with this same mutex).
What about realpath(3)?
Since it returns its result in a buffer you supply, thread-safety should not be an issue.
Try realpath()
or canonicalize_file_name()
If your system supports it (and it probably does), I suggest calling realpath(pathname, NULL)
; this will malloc
the buffer for the canonicalized filename and pass it back as the return value. You'd have to be sure to free()
the pointer. The alternative, passing in an output buffer, runs the risk of buffer overruns.
canonicalize_file_name()
is a Gnu extension that is equivalent to realpath(pathname, NULL)
.
There is no "canonical" path in a Unix directory. It may be possible for a file/directory to have multiple hard links/mount points.
The closest thing to the identity of a file/directory is its inode.
Oh dear, doing the action you mention couldn't possibly be thread safe, because it actually chdir's, which is going to confuse any other threads. I'll have to look up the string-manipulation portion of what you want, but it can't possibly also strip softlinks or do anything else that requires asking the operating system for file information without being a little thread-unsafe.
Related posts:
- unix path searching C function
- How to parse a folder path with spaces in C code
Try this to convert relative file paths, then compare them as strings:
#include<stdio.h>
#include<dirent.h>
#include<fcntl.h>
#include<sys/param.h>
int main( int argc, char **argv )
{
char buffer[MAXPATHLEN+1];
if( argc <= 1 ) return 0;
DIR*d = opendir( argv[1] );
if( !d ) return 0;
int dfd = dirfd(d);
if( !dfd ) return 0;
int result = fcntl( dfd, F_GETPATH, buffer );
if( result == -1 ) return 0;
fprintf( stdout, "path='%s'\n", buffer );
return 0;
}
精彩评论