diff options
Diffstat (limited to 'winsup/cygwin/fhandler_netdrive.cc')
-rw-r--r-- | winsup/cygwin/fhandler_netdrive.cc | 106 |
1 files changed, 102 insertions, 4 deletions
diff --git a/winsup/cygwin/fhandler_netdrive.cc b/winsup/cygwin/fhandler_netdrive.cc index 0b6aba7d3..fbb2c1689 100644 --- a/winsup/cygwin/fhandler_netdrive.cc +++ b/winsup/cygwin/fhandler_netdrive.cc @@ -8,7 +8,6 @@ This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ -#include <windows.h> #include "winsup.h" #include <unistd.h> #include <stdlib.h> @@ -20,7 +19,9 @@ details. */ #include "dtable.h" #include "cygheap.h" #include <assert.h> -#include <shlwapi.h> +#include <winnetwk.h> + +#include <dirent.h> /* Returns 0 if path doesn't exist, >0 if path is a directory, -1 if path is a file, -2 if it's a symlink. */ @@ -70,9 +71,106 @@ fhandler_netdrive::fstat (struct __stat64 *buf) } struct dirent * -fhandler_netdrive::readdir (DIR * dir) +fhandler_netdrive::readdir (DIR *dir) +{ + DWORD size; + NETRESOURCE *nro; + DWORD ret; + + if (!dir->__d_position) + { + size_t len = strlen (get_name ()); + char *namebuf, *dummy; + NETRESOURCE nr = { 0 }, *nro2; + + if (len == 2) /* // */ + { + namebuf = (char *) alloca (MAX_COMPUTERNAME_LENGTH + 3); + strcpy (namebuf, "\\\\"); + size = MAX_COMPUTERNAME_LENGTH + 1; + if (!GetComputerName (namebuf + 2, &size)) + { + __seterrno (); + return NULL; + } + } + else + { + const char *from; + char *to; + namebuf = (char *) alloca (len + 1); + for (to = namebuf, from = get_name (); *from; to++, from++) + *to = (*from == '/') ? '\\' : *from; + *to = '\0'; + } + + nr.lpRemoteName = namebuf; + nr.dwType = RESOURCETYPE_DISK; + size = 4096; + nro = (NETRESOURCE *) alloca (size); + ret = WNetGetResourceInformation (&nr, nro, &size, &dummy); + if (ret != NO_ERROR) + { + __seterrno (); + return NULL; + } + + if (len == 2) + { + nro2 = nro; + size = 4096; + nro = (NETRESOURCE *) alloca (size); + ret = WNetGetResourceParent (nro2, nro, &size); + if (ret != NO_ERROR) + { + __seterrno (); + return NULL; + } + } + ret = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, + nro, &dir->__handle); + if (ret != NO_ERROR) + { + __seterrno (); + dir->__handle = INVALID_HANDLE_VALUE; + return NULL; + } + } + /* FIXME: dot and dot_dot handling */ + DWORD cnt = 1; + size = 16384; /* As documented in MSDN. */ + nro = (NETRESOURCE *) alloca (size); + ret = WNetEnumResource (dir->__handle, &cnt, nro, &size); + if (ret != NO_ERROR) + { + if (ret != ERROR_NO_MORE_ITEMS) + __seterrno (); + return NULL; + } + dir->__d_position++; + char *bs = strrchr (nro->lpRemoteName, '\\'); + strcpy (dir->__d_dirent->d_name, bs ? bs + 1 : nro->lpRemoteName); + return dir->__d_dirent; +} + +_off64_t +fhandler_netdrive::telldir (DIR *dir) +{ + return -1; +} + +void +fhandler_netdrive::seekdir (DIR *, _off64_t) +{ +} + +int +fhandler_netdrive::closedir (DIR *dir) { - return NULL; + if (dir->__handle != INVALID_HANDLE_VALUE) + WNetCloseEnum (dir->__handle); + dir->__handle = INVALID_HANDLE_VALUE; + return fhandler_virtual::closedir (dir); } int |