* fhandler.h (class fhandler_netdrive): Add method rewinddir.

* fhandler_netdrive.cc (struct netdriveinf): New structure to
	store thread arguments.
	(thread_netdrive): Thread handling all potentially blocking
	WNet... calls.
	(create_thread_and_wait): Start and wait for above thread.
	(fhandler_netdrive::exists): Change to call create_thread_and_wait
	instead of calling WNet... function.
	(fhandler_netdrive::readdir): Ditto.  Fix error handling.
	(fhandler_netdrive::rewinddir): New method.
This commit is contained in:
Corinna Vinschen 2005-05-17 20:34:15 +00:00
parent 0d5ba26ccd
commit 5b59a2cc0d
3 changed files with 116 additions and 36 deletions

View File

@ -1,3 +1,16 @@
2005-05-17 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_netdrive): Add method rewinddir.
* fhandler_netdrive.cc (struct netdriveinf): New structure to
store thread arguments.
(thread_netdrive): Thread handling all potentially blocking
WNet... calls.
(create_thread_and_wait): Start and wait for above thread.
(fhandler_netdrive::exists): Change to call create_thread_and_wait
instead of calling WNet... function.
(fhandler_netdrive::readdir): Ditto. Fix error handling.
(fhandler_netdrive::rewinddir): New method.
2005-05-17 Corinna Vinschen <corinna@vinschen.de> 2005-05-17 Corinna Vinschen <corinna@vinschen.de>
* external.cc (cygwin_internal): Avoid compiler warning. * external.cc (cygwin_internal): Avoid compiler warning.

View File

@ -1222,6 +1222,7 @@ class fhandler_netdrive: public fhandler_virtual
struct dirent *readdir (DIR *); struct dirent *readdir (DIR *);
_off64_t telldir (DIR *); _off64_t telldir (DIR *);
void seekdir (DIR *, _off64_t); void seekdir (DIR *, _off64_t);
void rewinddir (DIR *);
int closedir (DIR *); int closedir (DIR *);
int open (int flags, mode_t mode = 0); int open (int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));

View File

@ -18,11 +18,90 @@ details. */
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "sigproc.h"
#include "cygthread.h"
#include <assert.h> #include <assert.h>
#include <winnetwk.h> #include <winnetwk.h>
#include <dirent.h> #include <dirent.h>
enum
{
GET_RESOURCE_INFO = 0,
GET_RESOURCE_OPENENUM = 1,
GET_RESOURCE_OPENENUMTOP = 2,
GET_RESOURCE_ENUM = 3
};
struct netdriveinf
{
int what;
int ret;
PVOID in;
PVOID out;
DWORD outsize;
HANDLE sem;
};
static DWORD WINAPI
thread_netdrive (void *arg)
{
netdriveinf *ndi = (netdriveinf *) arg;
LPTSTR dummy = NULL;
LPNETRESOURCE nro, nro2;
DWORD size;
HANDLE enumhdl;
ReleaseSemaphore (ndi->sem, 1, NULL);
switch (ndi->what)
{
case GET_RESOURCE_INFO:
nro = (LPNETRESOURCE) alloca (size = 4096);
ndi->ret = WNetGetResourceInformation ((LPNETRESOURCE) ndi->in,
nro, &size, &dummy);
break;
case GET_RESOURCE_OPENENUM:
case GET_RESOURCE_OPENENUMTOP:
nro = (LPNETRESOURCE) alloca (size = 4096);
ndi->ret = WNetGetResourceInformation ((LPNETRESOURCE) ndi->in,
nro, &size, &dummy);
if (ndi->ret != NO_ERROR)
break;
if (ndi->what == GET_RESOURCE_OPENENUMTOP)
{
nro2 = nro;
nro = (LPNETRESOURCE) alloca (size = 4096);
ndi->ret = WNetGetResourceParent (nro2, nro, &size);
if (ndi->ret != NO_ERROR)
break;
}
ndi->ret = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, nro,
&enumhdl);
if (ndi->ret == NO_ERROR)
*(HANDLE *) ndi->out = enumhdl;
break;
case GET_RESOURCE_ENUM:
ndi->ret = WNetEnumResource ((HANDLE) ndi->in, (size = 1, &size),
(LPNETRESOURCE) ndi->out, &ndi->outsize);
break;
}
ReleaseSemaphore (ndi->sem, 1, NULL);
return 0;
}
static DWORD
create_thread_and_wait (int what, PVOID in, PVOID out, DWORD outsize,
const char *name)
{
netdriveinf ndi = { what, 0, in, out, outsize,
CreateSemaphore (&sec_none_nih, 0, 2, NULL) };
cygthread *thr = new cygthread (thread_netdrive, (LPVOID) &ndi, name);
if (thr->detach (ndi.sem))
ndi.ret = ERROR_OPERATION_ABORTED;
CloseHandle (ndi.sem);
return ndi.ret;
}
/* Returns 0 if path doesn't exist, >0 if path is a directory, /* 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. */ -1 if path is a file, -2 if it's a symlink. */
int int
@ -43,11 +122,9 @@ fhandler_netdrive::exists ()
nr.dwType = RESOURCETYPE_DISK; nr.dwType = RESOURCETYPE_DISK;
nr.lpLocalName = NULL; nr.lpLocalName = NULL;
nr.lpRemoteName = namebuf; nr.lpRemoteName = namebuf;
LPTSTR sys = NULL; DWORD ret = create_thread_and_wait (GET_RESOURCE_INFO, &nr, NULL, 0,
char buf[8192]; "WnetGetResourceInformation");
DWORD n = sizeof (buf); if (ret != ERROR_MORE_DATA && ret != NO_ERROR)
DWORD rc = WNetGetResourceInformation (&nr, &buf, &n, &sys);
if (rc != ERROR_MORE_DATA && rc != NO_ERROR)
return 0; return 0;
return 1; return 1;
} }
@ -80,8 +157,8 @@ fhandler_netdrive::readdir (DIR *dir)
if (!dir->__d_position) if (!dir->__d_position)
{ {
size_t len = strlen (get_name ()); size_t len = strlen (get_name ());
char *namebuf, *dummy; char *namebuf;
NETRESOURCE nr = { 0 }, *nro2; NETRESOURCE nr = { 0 };
if (len == 2) /* // */ if (len == 2) /* // */
{ {
@ -106,44 +183,24 @@ fhandler_netdrive::readdir (DIR *dir)
nr.lpRemoteName = namebuf; nr.lpRemoteName = namebuf;
nr.dwType = RESOURCETYPE_DISK; nr.dwType = RESOURCETYPE_DISK;
size = 4096; nro = (NETRESOURCE *) alloca (4096);
nro = (NETRESOURCE *) alloca (size); ret = create_thread_and_wait (len == 2 ? GET_RESOURCE_OPENENUMTOP
ret = WNetGetResourceInformation (&nr, nro, &size, &dummy); : GET_RESOURCE_OPENENUM,
&nr, &dir->__handle, 0, "WNetOpenEnum");
if (ret != NO_ERROR) if (ret != NO_ERROR)
{ {
__seterrno (); __seterrno_from_win_error (ret);
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; dir->__handle = INVALID_HANDLE_VALUE;
return NULL; return NULL;
} }
} }
DWORD cnt = 1; ret = create_thread_and_wait (GET_RESOURCE_ENUM, dir->__handle,
size = 16384; /* As documented in MSDN. */ nro = (LPNETRESOURCE) alloca (16384),
nro = (NETRESOURCE *) alloca (size); 16384, "WnetEnumResource");
ret = WNetEnumResource (dir->__handle, &cnt, nro, &size);
if (ret != NO_ERROR) if (ret != NO_ERROR)
{ {
if (ret != ERROR_NO_MORE_ITEMS) if (ret != ERROR_NO_MORE_ITEMS)
__seterrno (); __seterrno_from_win_error (ret);
return NULL; return NULL;
} }
dir->__d_position++; dir->__d_position++;
@ -163,6 +220,15 @@ fhandler_netdrive::seekdir (DIR *, _off64_t)
{ {
} }
void
fhandler_netdrive::rewinddir (DIR *dir)
{
if (dir->__handle != INVALID_HANDLE_VALUE)
WNetCloseEnum (dir->__handle);
dir->__handle = INVALID_HANDLE_VALUE;
return fhandler_virtual::rewinddir (dir);
}
int int
fhandler_netdrive::closedir (DIR *dir) fhandler_netdrive::closedir (DIR *dir)
{ {