I'm looking to write a C program which, given the name of symbolic link, will print the name of the file or directory the link points to. Any suggestions on how to start?
The readlink() function that has been mentioned is part of the answer. However, you should be aware of its horrid interface (it does not null terminate the response string!).
You might also want to look at the realpath() function, the use of which was discussed in SO 1563186. You could also look at the code for 'linkpath' at the IIUG Software Archive. It analyzes the security of all the directories encountered as a symbolic link is resolved - it uses readlink() and lstat() and stat(); one of the checks when testing the program was to ensure that realpath() resolved the name to the same file.
Make sure that you have an environment which supports POSIX functions, include unistd.h and then use the readlink function.
Depending on the platform, stat() or fstat() are probably the first things to try out. If you're on Linux or cygwin then the stat program will give you a reasonable idea of what to expect from the system API call (it pretty much gives you a text dump of it).
The system call you want is readlink(). Takes a path to the link, returns the string (not always a valid path in the filesystem!) stored in the link. Check the man page ("man 2 readlink") for details.
Note there is some ambiguity to your question. You might be asking for how to tell the "real" path in the filesystem, which is a little more complicated.
Related
Is there a POSIX function that searches PATH for an executable according to the POSIX spec's description of the PATH environment variable and returns the absolute path to the executable?
If not, is there a simple, safe, standard, and reliable way to search PATH?
Edit:
glibc's execvpe() function does its own PATH search, so I'm guessing there isn't a specific PATH search function defined by the standard.
Edit 2: I don't want to copy someone else's code or implement the PATH search myself for a few reasons:
DRY
More code I have to test and maintain
Possible licensing issues
POSIX says, "If PATH is unset or is set to null, the path search is implementation-defined." I would like the behavior in these cases to be consistent with whatever the system does, but I can't do this if there's not a standard function I can call.
Is there a POSIX function that searches PATH for an executable according to the POSIX spec's description of the PATH environment variable and returns the absolute path to the executable?
No.
If not, is there a simple, safe, standard, and reliable way to search PATH?
Yes and no. Yes, there is a standard for the format of PATH, from which the correctness/reliability of implementations follow.
No, there is no standard function that does this. Copying code is your best bet.
If PATH is unset or is set to null, the path search is implementation-defined.
That means you can't always portably replicate what execvp does, but searching /bin:/usr/bin is a pretty safe bet. Alternatively, just raise an error in this case.
(I admit that it would have been nice if POSIX had had this function, but it just isn't there.)
The command line tool which will do that. here's the man page
and the source
What about doing something like:
FILE *f = popen("command -v somecommand", "r")
and then read its output? This would result in behavior that matches the system's handling of empty/unset PATH, and it may be simpler than manually searching PATH.
There are some drawbacks to this approach:
If somecommand comes from the user, it may have to be sanitized to prevent code injection attacks. That would add to the complexity.
Reliably reading the stream while handling all possible error cases is not trivial. More complexity.
If somecommand is a shell special built-in (e.g., set), it'll return bogus results. This case should be detectable, but then what? More complexity.
I am doing a c programming assignment where I am working with command-line arguments. One of the notes says that if the file you work with (to my understanding, it will always be "list.csv") is not yet created to create one. Just like vim does when you write "vim new.txt" and new.txt does not exist yet.
I am just wondering if there is a function that tests for the existence of a file? Or do I use some sort of try/catch block?
you can use fopen(). the second parameter says, what to do. Read, create+write, append+create(if not existent)
one way is to use fstat() on the filename.
under UNIX try 'man fstat'
Typically when you want to write to a file the library or operating system API will automatically try to create it for you if it does not already exist. Exactly how you can control this depends on the API that you will be using.
I am taking in an argument using fopen. What are some checks I can do to make sure that fopen actually takes in the string to a valid filename?
The number one method is to try opening the file. If fopen() returns NULL, there was an error. Check the errno variable or function to find out the problem.
Trying to preprocess a file specification is an exercise in futility. The operating system will do every relevant check for you, including those which are hard for you to do, like checking file protection ACLs, etc.
The question isn't clear, but if you want to know if the file name you have points to an existing file, you can use access (Linux documentation) (Windows documentation).
I know it is possible to get an absolute path of a file with realpath() function. However, according to BUGS section the manpage, there are some problem in its implementation. The details are following:
BUGS
Avoid using this function. It is broken by design since (unless using the non-standard resolved_path == NULL feature) it is impossible to determine a suitable size for the output buffer, resolved_path. According to POSIX a buffer of size PATH_MAX suffices, but PATH_MAX need not be a defined constant, and may have to be obtained using pathconf(3). And asking pathconf(3) does not really help, since on the one hand POSIX warns that the result of pathconf(3) may be huge and unsuitable for mallocing memory. And on the other hand pathconf(3) may return -1 to signify that PATH_MAX is not bounded.
The libc4 and libc5 implementation contains a buffer overflow (fixed in libc-5.4.13). Thus, set-user-ID programs like mount(8) need a private version.
So, the question is what is the best practice to get the absolute path of a file?
I know this question is old, but I don't see any answers that address the core issue: The man page OP referenced is wrong and outdated, for at least two reasons.
One is that POSIX 2008 added/mandated support for the NULL argument option, whereby realpath allocates the string for you. Programs using this feature will be portable to all relevant versions of GNU/Linux, probably most other modern systems, and anything conforming to POSIX 2008.
The second reason the man page is wrong is the admonition against PATH_MAX. This is purely GNU religious ideology against "arbitrary limits". In the real world, not having a pathname length limit would add all sorts of avenues for abuse/DoS, would add lots of failure cases to tasks that otherwise could not fail, and would break more interfaces than just realpath.
If you care about maximum portability, it's probably best to use a mix of both methods. See the POSIX documentation for details:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
I would use a fixed-size, caller-provided buffer if PATH_MAX is defined, and otherwise pass NULL. This seems to cover all cases, but you might also want to check older versions of POSIX to see if they have any guidelines for what to do if PATH_MAX is not defined.
Use getcwd() and readlink() which allows to give a buffer size to reimplement realpath(). Note that you have to resolve symbolic links, "." and ".." from left to right to do it correctly.
From the shell, I can get a full path using readlink -f $FILE. There's a readlink() function in glibc, maybe that'll help you.
# man 2 readlink
I am trying to write a program that allows a binary to be run, substituting a certain file when requested with another. It is a library with simple replacements for the system call functions, that is used with LD_PRELOAD. The problem is that it catches opens for reading (the substitute file is read instead), but writes always go back to the actual, specified file. Are there any other "open" system calls I should know about?
Nevermind -- stupid mistake.
Wasn't checking both absolute and relative paths...
I am not sure what the cause of your problem is, but using strace on your program might give some insight. It should be part of any sane Linux distribution.
If it's open for writing, it's most likely going through the creat function (I'm guessing fopen would be redirecting you there). Check your fcntl.h for a complete list.
substituting a certain file when requested with another
Sounds like you check only for the input file (do you check by filename?). You need to check and substitute the output file, too.
If you output goes to one of the standard outputs, then you need to close and reopen them with your output substitute) before you fork into the executable.
To find all system calls that your executable makes you can use strace.
To find all library calls that your executable makes you can use ltrace.