* 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:
parent
0d5ba26ccd
commit
5b59a2cc0d
|
@ -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.
|
||||||
|
|
|
@ -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)));
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue