I use this go get the content of directory foo: FindFirstFile(L"foo\\*", &findData). It works great when foo is a regular directory. However when foo is a junction pointing to another directory (created with mklink /j foo C:\gah) FindFirstFile fails.
The docs have this to say: "If the path points to a symbolic link, the WIN32_FIND_DATA buffer contains information about the symbolic link, not the target." But when I run it the debugger I just get an INVALID_HANDLE_VALUE and findData remains untouched.
So, how do I work around this?
Raymond Chen has an answer for you.
Functions like GetFileAttributes and FindFirstFile, when asked to
provide information about a symbolic link, returns information about
the link itself and not the link destination. If you use the
FindFirstFile function, you can tell that you have a symbolic link
because the file attributes will have the
FILE_ATTRIBUTES_REPARSE_POINT flag set, and the dwReserved0 member
will contain the special value IO_REPARSE_TAG_SYMLINK.
Okay, great, so now I know I have a symbolic link, but what if I want
information about the link target? For example, I want to know the
size of the link target, its last-modified time, and its name.
To do this, you open the symbolic link. The I/O manager dereferences
the symbolic link and gives you a handle to the link destination. You
can then call functions like GetFileSize,
GetFileInformationByHandleEx, or GetFinalPathNameByHandle to obtain
information about the symbolic link target.
Related
I am currently recoding the "ls" command to learn. However, when I browse files: I may have an error when I try to open the "folder" of the path pointed by the symbolic link. Because it's not a directory (I thought all symbolic links pointed to folders).
How can I check if it points to a directory? (I watch the manuals, stat, dir ..)
I thought all symbolic links pointed to folders
Nope. A symbolic link is an indirect reference to another path. That other path can refer to any kind of file that can be represented in any mounted file system, or to no file at all (i.e. it can be a broken link).
How to check that it points to a directory?
You mention the stat() function, but for reimplementing ls you should mostly be using lstat(), instead. The difference is that when the specified path refers to a symbolic link, stat returns information about the link's target path, whereas lstat returns information about the link itself (including information about the file type, from which you can tell that it is a link).
In the event that you encounter a symbolic link, you can simply check the same path again with stat() to find out what kind of file it points to. stat() will recursively resolve symbolic links to discover the information for the ultimate target, which will be a symbolic link only if it is a broken one. Any way around, you don't need to distinguish between a broken link and any other form of non-directory for your particular purpose.
I just ran into the same problem, and here is my solution:
bool IsDir(const char *path)
{
std::string tmp = path;
tmp += '/';
struct stat statbuf;
return (lstat(tmp.c_str(), &statbuf) >= 0) && S_ISDIR(statbuf.st_mode);
}
the key is the tail / in the path
however, I have no idea whether it's portable
I found a pacman project in github where a file conf.c includes a header file #include "ini.h" where ini.h contains only a single line (i.e no #include statement):
//ini.h
../common/ini.c
I have never seen anyone doing this before! It seems a bit hackish/rough around the edges. My questions are:
Is this legal C?
Is it portable?
Is it recommended?
I would have assumed the answer should be no for all these questions, but I may be learning something new...
edit
From the answers, I see its a Linux symlink. I guess that this means it is not portable to Windows, and would also make it more difficult to read outside a unix environment. I would also imagine that using relative paths (or include directories) instead of symlinks would be a better practice in cases like this for reasons mentioned above...
src/pacman/ini.h is a symbolic link according to the site.
Symbolic link has an information of where the target file is (path name), and I guess it is what is displayed on the site.
The OS will redirect access to that ini.h to ../common/ini.h, which is a normal C code.
I don't see any reason why not. The include statement indicates the compiler to replace that line with the whatever is in the included file
I need a method to obtain the absolute path of a file in C programming language for the implementation of 'cp' UNIX's command. The objective is show an error when the source path and destination path are the same.
There are multiple possibilities, for example:
cp file . // show error
cp ../file .
cp file file // show error
I haven't found a good method to solve this problem.
Converting comments into an answer.
Lookup realpath() to get the 'real name' of a path, but it really isn't necessary. You can use stat() to see if the device and inode number are the same for two names.
Also note that if you have two files linked (for example, /home/user1/name1 and /home/user2/name2), the names might be different but still refer to the same file (and the links could be 'hard' or symbolic). You can detect their equivalence with stat() but not with realpath() — at least, not with realpath() if the link is a hard link.
I'm editing linux v2.18.8 (CentOS5) to include file attributes for a project for school. One of the things we have to implement as a group is to list all attribute names (Attributes are text files stored in hidden directories at the same level as the file).
Just an example:
this.jpg is a file in /Desktop/Testing. When you add a custom user attribute a folder is created that holds the attributes. So if I add the attribute "Creator" and have it's value as "bob" you get a dir /Desktop/Testing/.this.jpg_attr/Creator (and if you open Creator, it's contents will be "bob").
What I'm interested in doing is listing all of the user created attributes in the attributes folder (or from the example all the files in /Desktop/Testing/.this.jpg_attr/) I know that I want to use the readdir call, but I don't know where to find it in the linux setup. If anyone could give me any guidance as to where to look for readdir, I think I can figure out how to manipulate it.
I'M NOT ASKING FOR ANY CODE. JUST A FILE PATH FOR WHERE READDIR IS, OR THE SYSTEM CALL THAT CALLS READDIR.
Thanks in advanced.
It's not exactly clear what you mean. The readdir function you want to use is part of the standard library and will be linked in automatically.
Perhaps you're asking how to include the header file that declares readdir. In that case:
#include <dirent.h>
You can get more information about the readdir function using this command:
man 3 readdir
The system call is getdents(2), however you should continue to use the readdir wrapper for portability.
If a file A is not symbolic link, we can use describe to get the labels which were applied on its current version.
But if it is symbolic link, we can just use describe to get a relative path of the target file. Is there any easy way to list the labels of the target of a symbolic link?
No, for the same reason you cannot access their extended pathname:
Symbolic links are not versioned and, hence, do not have version-extended pathnames.
Symlinks are not catalogued in the version history of the element. They serve only as a pointer to a target version, and allow you to create multiple access points to a single version.
You must first resolve the link element destination in your current view configuration before listing the label on that destination element (file or directory).