Hi, I was investigating why fdopendir() would succeed returning a non-null DIR* for a valid fd of an open file (while it should fail with ENOTDIR).
So far I traced the steps that happen: - in glibc, __fdopendir calls __file_name_lookup_under with the fd port, "/" as file name and O_DIRECTORY among the flags - __hurd_file_name_lookup strips leading "/" from the file name but adding trailing "/" if O_DIRECTORY is set (to force the lookup as directory), so the actual lookup RPC invoked (which is dir_lookup, since 0 is passed to __hurd_file_name_lookup) has "/" as file name - on the hurd side: diskfs_S_dir_lookup (or netfs_S_dir_lookup, since both behave the same in what follows) first strips leading "/", leaving the path as empty string, which causes the "fast path" if at line 67 to be executed, picking as result node the one associated to the fd port we had; below, at the gotit label, the type check based on the stat of the node does not trigger the if returning ENOTDIR, because mustbedir is false - back on the glibc side: the dir_lookup succeeded so the lookup called in __fdopendir passes and a new DIR* is returned At this point I'm a bit puzzled as to where should be the right place to fix, even because I don't know much the parts involved. It seems the lookup logic (implemented in the lookup glibc functions and in e.g. diskfs_S_dir_lookup) to force a directory based on trailing "/" works for paths with at least one component (like "/foo/"), so a solution in libdiskfs/libnetfs could be make the "fast path" set mustbedir if the flags contain O_DIRECTORY, although I'm not sure whether that would break assumptions done in other places. Otherwise, I'm not yet sure how fix the lookup glibc functions. As I said, I'm pretty new to the involved parts (lookup stuff), so if you have more ideas I will hear them. -- Pino Toscano
signature.asc
Description: This is a digitally signed message part.