You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(16) |
Aug
(203) |
Sep
(142) |
Oct
(113) |
Nov
(73) |
Dec
(27) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(7) |
Feb
(38) |
Mar
(6) |
Apr
(1) |
May
(9) |
Jun
(104) |
Jul
(6) |
Aug
(11) |
Sep
(13) |
Oct
(6) |
Nov
(15) |
Dec
(37) |
2008 |
Jan
(17) |
Feb
(4) |
Mar
(6) |
Apr
(4) |
May
(2) |
Jun
(5) |
Jul
(1) |
Aug
(3) |
Sep
(21) |
Oct
(7) |
Nov
|
Dec
(3) |
2009 |
Jan
(4) |
Feb
(15) |
Mar
|
Apr
(34) |
May
(44) |
Jun
(12) |
Jul
(6) |
Aug
(15) |
Sep
(20) |
Oct
(10) |
Nov
(1) |
Dec
(20) |
2010 |
Jan
(19) |
Feb
(5) |
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <ped...@us...> - 2007-06-30 21:13:30
|
Revision: 1027 http://svn.sourceforge.net/cegcc/?rev=1027&view=rev Author: pedroalves Date: 2007-06-30 14:13:29 -0700 (Sat, 30 Jun 2007) Log Message: ----------- * Makefile (download): Depend on all instead of only on PipeDev.dll. * PipeLib.h (PIPELIB_API): New define. (CreatePipe, GetPipeName, SetPipeTag): Use PIPELIB_API. * PipeLib.cpp: Include windows.h earlier. (GetPipeName, SetPipeTag, PeekNamedPipe): Use PIPELIB_API. (CreatePipe): Use PIPELIB_API. Comment unused parameter names. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/Makefile trunk/cegcc/tools/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-30 21:08:05 UTC (rev 1026) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-30 21:13:29 UTC (rev 1027) @@ -1,3 +1,14 @@ +2007-06-30 Pedro Alves <ped...@po...> + + * Makefile (download): Depend on all instead of only on + PipeDev.dll. + * PipeLib.h (PIPELIB_API): New define. + (CreatePipe, GetPipeName, SetPipeTag): Use PIPELIB_API. + * PipeLib.cpp: Include windows.h earlier. + (GetPipeName, SetPipeTag, PeekNamedPipe): Use + PIPELIB_API. + (CreatePipe): Use PIPELIB_API. Comment unused parameter names. + 2007-06-29 Pedro Alves <ped...@po...> * PipeLib: Delete. Modified: trunk/cegcc/tools/PipeLib/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/Makefile 2007-06-30 21:08:05 UTC (rev 1026) +++ trunk/cegcc/tools/PipeLib/Makefile 2007-06-30 21:13:29 UTC (rev 1027) @@ -25,7 +25,7 @@ rm -f $@ $(AR) r $@ $< -download: PipeDev.dll +download: all pcp PipeDev.dll ":/Windows/PipeDev.dll" clean-dev: Modified: trunk/cegcc/tools/PipeLib/PipeLib.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.cpp 2007-06-30 21:08:05 UTC (rev 1026) +++ trunk/cegcc/tools/PipeLib/PipeLib.cpp 2007-06-30 21:13:29 UTC (rev 1027) @@ -24,9 +24,11 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <windows.h> + +#include "PipeLib.h" #include "PipeDev.h" -#include <windows.h> #include <devload.h> #include <stdlib.h> @@ -93,7 +95,7 @@ } /* Undocumented, for pipedev.dll debugging purposes only. */ -extern "C" BOOL +PIPELIB_API BOOL SetPipeTag (HANDLE p, const WCHAR* name) { if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_TAG, @@ -113,7 +115,7 @@ return TRUE; } -extern "C" BOOL +PIPELIB_API BOOL GetPipeName (HANDLE p, WCHAR* name) { DWORD actual; @@ -125,11 +127,11 @@ return TRUE; } -extern "C" BOOL +PIPELIB_API BOOL CreatePipe (PHANDLE hReadPipe, PHANDLE hWritePipe, - LPSECURITY_ATTRIBUTES lpPipeAttributes, - DWORD nSize) + LPSECURITY_ATTRIBUTES /* lpPipeAttributes */, + DWORD /* nSize */) { int inst; WCHAR* wsKey; @@ -145,9 +147,8 @@ RegDeleteKey (HKEY_LOCAL_MACHINE, wsKey); free (wsKey); - /* Although MSDN documentcs that error should - return INVALID_HANDLE_VALUE, I see it returning - NULL here. */ + /* Although MSDN documents the error as INVALID_HANDLE_VALUE, I + see it returning NULL here. */ if (h != INVALID_HANDLE_VALUE && h != NULL) break; } @@ -155,7 +156,7 @@ if (inst == MAX_INSTANCES) return FALSE; - /* name + num + ':' + '0' */ + /* name + num + ':' + '\0' */ wchar_t device_name[(sizeof (NAME_BASE) - 1) + 2 + 1 + 1]; wsprintf (device_name, L"%s%02d:", NAME_BASE, inst); @@ -194,7 +195,7 @@ LPDWORD lpBytesLeftThisMessage }; -BOOL +PIPELIB_API BOOL PeekNamedPipe (HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, Modified: trunk/cegcc/tools/PipeLib/PipeLib.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.h 2007-06-30 21:08:05 UTC (rev 1026) +++ trunk/cegcc/tools/PipeLib/PipeLib.h 2007-06-30 21:13:29 UTC (rev 1027) @@ -28,19 +28,16 @@ #define __PIPE_LIB_H__ #ifdef __cplusplus -extern "C" -{ +# define PIPELIB_API extern "C" +#else +# define PIPELIB_API #endif -BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); -BOOL GetPipeName (HANDLE, WCHAR*); +PIPELIB_API BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); +PIPELIB_API BOOL GetPipeName (HANDLE, WCHAR*); /* Internal, for pipedev.dll debugging purposes. */ -BOOL SetPipeTag (HANDLE, const WCHAR*); +PIPELIB_API BOOL SetPipeTag (HANDLE, const WCHAR*); -#ifdef __cplusplus -} -#endif - #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-30 21:08:06
|
Revision: 1026 http://svn.sourceforge.net/cegcc/?rev=1026&view=rev Author: pedroalves Date: 2007-06-30 14:08:05 -0700 (Sat, 30 Jun 2007) Log Message: ----------- Fix typo. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-30 21:06:26 UTC (rev 1025) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-30 21:08:05 UTC (rev 1026) @@ -1,7 +1,7 @@ 2007-06-29 Pedro Alves <ped...@po...> - * (PipeLib): Delete. - * (PipeDev): Delete. + * PipeLib: Delete. + * PipeDev: Delete. 2007-06-29 Pedro Alves <ped...@po...> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-30 21:06:29
|
Revision: 1025 http://svn.sourceforge.net/cegcc/?rev=1025&view=rev Author: pedroalves Date: 2007-06-30 14:06:26 -0700 (Sat, 30 Jun 2007) Log Message: ----------- * rcp.c (get_logfile): Delete. (logfile): New global. (vlog): New. (error): Use vlog. (debug): Use vlog. (MIN): New define. (RCP_ERR_DELAY): Remove. (RcpReceive): Don't output to stderr - use debug instead. (ParseTarget): Likewise. (RcpSvrSend): Remove Sleep calls. (RcpSvrRecv): Change type of blen to DWORD. Remove Sleep calls. Don't output to stderr - use debug instead. Limit the amount of bytes to receive to the size of the receiving file. Wait for the extra NULL byte afterwards. (rcp_main): Add start and stop logging. Modified Paths: -------------- trunk/cegcc/tools/rcp/ChangeLog trunk/cegcc/tools/rcp/rcp.c Modified: trunk/cegcc/tools/rcp/ChangeLog =================================================================== --- trunk/cegcc/tools/rcp/ChangeLog 2007-06-29 23:31:37 UTC (rev 1024) +++ trunk/cegcc/tools/rcp/ChangeLog 2007-06-30 21:06:26 UTC (rev 1025) @@ -1,3 +1,21 @@ +2007-06-30 Pedro Alves <ped...@po...> + + * rcp.c (get_logfile): Delete. + (logfile): New global. + (vlog): New. + (error): Use vlog. + (debug): Use vlog. + (MIN): New define. + (RCP_ERR_DELAY): Remove. + (RcpReceive): Don't output to stderr - use debug instead. + (ParseTarget): Likewise. + (RcpSvrSend): Remove Sleep calls. + (RcpSvrRecv): Change type of blen to DWORD. Remove Sleep calls. + Don't output to stderr - use debug instead. Limit the amount of + bytes to receive to the size of the receiving file. Wait for the + extra NULL byte afterwards. + (rcp_main): Add start and stop logging. + 2007-06-25 Pedro Alves <ped...@po...> * FindFileA.c: Add a notice on file origin. Convert C++ comments Modified: trunk/cegcc/tools/rcp/rcp.c =================================================================== --- trunk/cegcc/tools/rcp/rcp.c 2007-06-29 23:31:37 UTC (rev 1024) +++ trunk/cegcc/tools/rcp/rcp.c 2007-06-30 21:06:26 UTC (rev 1025) @@ -66,53 +66,51 @@ #include <cwd.h> -static FILE * -get_logfile (void) -{ -#if 0 - static FILE* logger = NULL; +static const char *logfile = "rcp.log"; - if (logger == NULL) - { - char buf[200]; - sprintf (buf, "rcp-%08x", (unsigned) GetCurrentProcessId ()); - logger = fopen (buf, "a+"); - } - return logger; -#else - return stderr; -#endif -} - static int debugFlag = 0; static void -error (const char *message) +vlog (const char *pre, const char *format, va_list ap) { - FILE* f = get_logfile (); - fprintf (f, "%s\n", message); - fflush (f); + FILE *f = fopen (logfile, "a+"); + if (!f) + return; + fprintf (f, "%s", pre); + vfprintf (f, format, ap); + fclose (f); } static void +error (const char *format, ...) +{ + if (debugFlag) + { + va_list ap; + va_start (ap, format); + vlog ("error: ", format, ap); + va_end (ap); + } +} + +static void debug (const char *format, ...) { if (debugFlag) { - FILE* f = get_logfile (); va_list ap; va_start (ap, format); - vfprintf (f, format, ap); - fflush (f); + vlog ("debug: ", format, ap); va_end (ap); } } +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif + /* This is the size of the buffer used with rcp */ #define RCP_BUFFER_SIZE 8192 -/* This is a delay time in milliseconds to wait after sending an error - condition to the remote hosts during an rcp. */ -#define RCP_ERR_DELAY 1000 /* Several of the messages sent in the rcp protocol are single byte ( 0x00 ) or are text messages terminated by a ('\n'). @@ -138,13 +136,10 @@ error ("Cannot receive client data."); return rlen; } - if (debugFlag) - { - if (!rlen) - fprintf (stderr, "...got %d chars. \n", rlen); - else - fprintf (stderr, "...got %d chars. [%c]\n", rlen, buff[i]); - } + if (rlen == 0) + debug ("...got %d chars. \n", rlen); + else + debug ("...got %d chars. [%c]\n", rlen, buff[i]); tchar = buff[i]; i++; if (i > blen) @@ -195,9 +190,8 @@ #if 0 lLen = ExpandEnvironmentStrings (Target, strPath, MAX_PATH); - if (debugFlag) - fprintf (stderr, "The expanded path is %d chars %d: %s\n", lLen, - GetLastError (), strPath); + debug ("The expanded path is %d chars %d: %s\n", lLen, + GetLastError (), strPath); #else strcpy (strPath, Target); #endif @@ -398,7 +392,6 @@ sprintf (&buff[1], "rcp: %s: Not a plain file\n", expTarget); if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error sending result status."); - Sleep (RCP_ERR_DELAY); if (bMoreFiles) CloseTarget (hFile); return; @@ -417,7 +410,6 @@ sprintf (&buff[1], "rcp: %s: Permission Denied\n", expTarget); if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error sending result status."); - Sleep (RCP_ERR_DELAY); if (bMoreFiles) CloseTarget (hFile); return; @@ -491,7 +483,6 @@ sprintf (&buff[1], "rcp: %s: Cannot open file\n", FileName); if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error sending result status."); - Sleep (RCP_ERR_DELAY); if (bMoreFiles) CloseTarget (hFile); return; @@ -545,7 +536,6 @@ < 1) error ("Error sending result status."); close (FileId); - Sleep (RCP_ERR_DELAY); if (bMoreFiles) CloseTarget (hFile); return; @@ -637,7 +627,7 @@ RcpSvrRecv (char *Target, BOOL bRecursive, BOOL bTargDir) { char buff[RCP_BUFFER_SIZE + 1]; - int blen = RCP_BUFFER_SIZE; + DWORD blen = RCP_BUFFER_SIZE; int FileId; DWORD dwFileSize; DWORD dwBytesRecv; @@ -669,7 +659,6 @@ { error ("Error sending result status."); } - Sleep (RCP_ERR_DELAY); CloseTarget (hFile); return; } @@ -686,7 +675,6 @@ { error ("Error sending result status."); } - Sleep (RCP_ERR_DELAY); return; } @@ -703,7 +691,6 @@ sprintf (&buff[1], "rcp: %s: Permission Denied\n", expTarget); if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error sending result status."); - Sleep (RCP_ERR_DELAY); return; } } @@ -734,7 +721,6 @@ expTarget); if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error sending result status."); - Sleep (RCP_ERR_DELAY); return; } } @@ -794,10 +780,8 @@ buff[0] = 1; sprintf (&buff[1], "rcp: %s: Directory access failure %d\n", expTarget, errno); - if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < - 1) + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error sending result status."); - Sleep (RCP_ERR_DELAY); return; } /* Create directory. */ @@ -810,7 +794,6 @@ expTarget); if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error sending result status."); - Sleep (RCP_ERR_DELAY); return; } } @@ -841,7 +824,6 @@ sprintf (&buff[1], "rcp: %s :Cannot open file\n", Target2); if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error sending result status."); - Sleep (RCP_ERR_DELAY); return; } break; @@ -851,8 +833,7 @@ } dwFileSize = atol (&buff[6]); - if (debugFlag) - fprintf (stderr, "Receiving file %s of size %lu.\n", Target2, dwFileSize); + debug ("Receiving file %s of size %lu.\n", Target2, dwFileSize); buff[0] = 0; if (write (fileno (stdout), buff, 1) < 1) @@ -881,7 +862,8 @@ while (dwBytesRecv < dwFileSize) { /* Receive data from the client. */ - if ((dwBytes = read (fileno (stdin), buff, blen)) == -1) + int toread = MIN (dwFileSize - dwBytesRecv, blen); + if ((dwBytes = read (fileno (stdin), buff, toread)) == -1) { error ("Cannot receive client data."); close (FileId); @@ -890,6 +872,8 @@ dwBytesRecv += dwBytes; + debug ("Got %lu (%lu/%lu).\n", dwBytes, dwBytesRecv, dwFileSize); + /* Write the data to the file. */ nValue = write (FileId, buff, dwBytes); @@ -901,11 +885,17 @@ Target2); if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) error ("Error writing error status."); - Sleep (RCP_ERR_DELAY); close (FileId); return; } } + + if ((dwBytes = read (fileno (stdin), buff, 1)) == -1) + error ("Cannot receive NULL byte."); + else if (buff[0] != '\0') + error ("Got invalid data (0x%02x).", (int)buff[0]); + else + debug ("Done receiving.\n"); } close (FileId); @@ -979,6 +969,8 @@ exit (1); } + debug ("starting up\n"); + if (bSvrRecv) { if (bRecursive) @@ -989,9 +981,14 @@ else RcpSvrSend (argv[i], bRecursive); + debug ("closing down\n"); + /* Make sure we end up where we started. */ chdir (HomeDir); free (HomeDir); + + debug ("closing down (2)\n"); + return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-29 23:31:38
|
Revision: 1024 http://svn.sourceforge.net/cegcc/?rev=1024&view=rev Author: pedroalves Date: 2007-06-29 16:31:37 -0700 (Fri, 29 Jun 2007) Log Message: ----------- Remove extra whitespacing. Modified Paths: -------------- trunk/cegcc/tools/rshd/ChangeLog Modified: trunk/cegcc/tools/rshd/ChangeLog =================================================================== --- trunk/cegcc/tools/rshd/ChangeLog 2007-06-29 23:26:06 UTC (rev 1023) +++ trunk/cegcc/tools/rshd/ChangeLog 2007-06-29 23:31:37 UTC (rev 1024) @@ -95,8 +95,8 @@ 2007-06-13 Danny Backx <dan...@us...> - * rshd.c : Remove #include <pkfuncs.h>. - * Makefile : Add references to PipeLib directory so rshd can be built + * rshd.c: Remove #include <pkfuncs.h>. + * Makefile: Add references to PipeLib directory so rshd can be built without installing PipeLib. 2007-06-10 Pedro Alves <ped...@po...> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-29 23:26:50
|
Revision: 1023 http://svn.sourceforge.net/cegcc/?rev=1023&view=rev Author: pedroalves Date: 2007-06-29 16:26:06 -0700 (Fri, 29 Jun 2007) Log Message: ----------- * Makefile (LDFLAGS): Clear. (CFLAGS): Remove PipeLib reference. (PIPELIBDIR): New. (LIBS): New. (INCLUDES): Add -I$(PIPELIBDIR). (rshd_unstripped.exe): Link with $(LIBS). (download): Don't download tester.exe by default. Modified Paths: -------------- trunk/cegcc/tools/rshd/ChangeLog trunk/cegcc/tools/rshd/Makefile Modified: trunk/cegcc/tools/rshd/ChangeLog =================================================================== --- trunk/cegcc/tools/rshd/ChangeLog 2007-06-29 23:16:59 UTC (rev 1022) +++ trunk/cegcc/tools/rshd/ChangeLog 2007-06-29 23:26:06 UTC (rev 1023) @@ -1,5 +1,15 @@ 2007-06-30 Pedro Alves <ped...@po...> + * Makefile (LDFLAGS): Clear. + (CFLAGS): Remove PipeLib reference. + (PIPELIBDIR): New. + (LIBS): New. + (INCLUDES): Add -I$(PIPELIBDIR). + (rshd_unstripped.exe): Link with $(LIBS). + (download): Don't download tester.exe by default. + +2007-06-30 Pedro Alves <ped...@po...> + * rshd.c: Include getopt.h. (logfile): New global. (logprintf): Use logfile if set. Modified: trunk/cegcc/tools/rshd/Makefile =================================================================== --- trunk/cegcc/tools/rshd/Makefile 2007-06-29 23:16:59 UTC (rev 1022) +++ trunk/cegcc/tools/rshd/Makefile 2007-06-29 23:26:06 UTC (rev 1023) @@ -1,9 +1,12 @@ TARGET=arm-wince-mingw32ce -LDFLAGS=-lws2 -L../PipeLib -lPipeLib -CFLAGS=-O0 -g3 -I../PipeLib + +LDFLAGS= +CFLAGS=-O0 -g3 WARNFLAGS=-Wall -Wextra -INCLUDES= +PIPELIBDIR=../PipeLib +LIBS=-lws2 -L$(PIPELIBDIR) -lPipeLib +INCLUDES=-I$(PIPELIBDIR) ALLFLAGS=$(CFLAGS) $(INCLUDES) $(WARNFLAGS) @@ -27,10 +30,10 @@ BINDIST_FILES=\ rshd.exe -all: $(BINS) +all: $(BINS) rshd_unstripped.exe: rshd.c Makefile - $(CC) -o $@ $< $(ALLFLAGS) $(LDFLAGS) + $(CC) -o $@ $< $(ALLFLAGS) $(LDFLAGS) $(LIBS) rshd.exe: rshd_unstripped.exe $(STRIP) $< -o $@ @@ -41,7 +44,7 @@ tester.exe: tester_unstripped.exe $(TARGET)-strip $< -o $@ -download: download-rshd download-tester +download: download-rshd download-rshd: rshd.exe pcp $< ":/rshd.exe" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-29 23:17:01
|
Revision: 1022 http://svn.sourceforge.net/cegcc/?rev=1022&view=rev Author: pedroalves Date: 2007-06-29 16:16:59 -0700 (Fri, 29 Jun 2007) Log Message: ----------- * rshd.c: Include getopt.h. (logfile): New global. (logprintf): Use logfile if set. (BUFSIZE): New define. (stdin_thread): Use BUFSIZE. Echo using logprintf. (stdout_thread): Likewise. (stderr_thread): Likewise. (handle_connection): Kill a few warnings. Set stderrsockfd to -1 after closing it. Remove dead code. (progname): New global. (usage): New function. (main): Use getopt. Add -l option. * Makefile (LDFLAGS): Adjust to new PipeLib path. (CFLAGS): Likewise. Modified Paths: -------------- trunk/cegcc/tools/rshd/ChangeLog trunk/cegcc/tools/rshd/Makefile trunk/cegcc/tools/rshd/rshd.c Modified: trunk/cegcc/tools/rshd/ChangeLog =================================================================== --- trunk/cegcc/tools/rshd/ChangeLog 2007-06-29 17:25:16 UTC (rev 1021) +++ trunk/cegcc/tools/rshd/ChangeLog 2007-06-29 23:16:59 UTC (rev 1022) @@ -1,3 +1,20 @@ +2007-06-30 Pedro Alves <ped...@po...> + + * rshd.c: Include getopt.h. + (logfile): New global. + (logprintf): Use logfile if set. + (BUFSIZE): New define. + (stdin_thread): Use BUFSIZE. Echo using logprintf. + (stdout_thread): Likewise. + (stderr_thread): Likewise. + (handle_connection): Kill a few warnings. Set stderrsockfd to -1 + after closing it. Remove dead code. + (progname): New global. + (usage): New function. + (main): Use getopt. Add -l option. + * Makefile (LDFLAGS): Adjust to new PipeLib path. + (CFLAGS): Likewise. + 2007-06-28 Pedro Alves <ped...@po...> * rshd.c (localecho): New global. Modified: trunk/cegcc/tools/rshd/Makefile =================================================================== --- trunk/cegcc/tools/rshd/Makefile 2007-06-29 17:25:16 UTC (rev 1021) +++ trunk/cegcc/tools/rshd/Makefile 2007-06-29 23:16:59 UTC (rev 1022) @@ -1,6 +1,6 @@ TARGET=arm-wince-mingw32ce -LDFLAGS=-lws2 -L../PipeLib/PipeLib -lPipeLib -CFLAGS=-O0 -g3 -I../PipeLib/PipeLib +LDFLAGS=-lws2 -L../PipeLib -lPipeLib +CFLAGS=-O0 -g3 -I../PipeLib WARNFLAGS=-Wall -Wextra INCLUDES= Modified: trunk/cegcc/tools/rshd/rshd.c =================================================================== --- trunk/cegcc/tools/rshd/rshd.c 2007-06-29 17:25:16 UTC (rev 1021) +++ trunk/cegcc/tools/rshd/rshd.c 2007-06-29 23:16:59 UTC (rev 1022) @@ -28,6 +28,7 @@ #include <fcntl.h> #include <stdarg.h> #include <malloc.h> +#include <getopt.h> #include <windows.h> #include <winsock2.h> @@ -44,15 +45,16 @@ static BOOL debug = FALSE; static BOOL localecho = FALSE; +static const char* logfile = NULL; static void logprintf (const char *fmt, ...) { - if (0) + if (logfile) { - FILE *logfile = fopen("/rshd.log", "a+"); + FILE *logfile = fopen(logfile, "a+"); if (logfile) { @@ -249,6 +251,8 @@ } #endif +#define BUFSIZE 0x1000 + /* All 3 threads return 0 if they are closing because the pipes were broken due to the child closing them, and 1 if the remote side closed the sockets before the child died. We use this knowledge in @@ -267,9 +271,9 @@ while (!data->stop) { int read = 0; - char buf[1]; + char buf[BUFSIZE + 1]; - read = recv (data->sockfd, buf, sizeof(buf), 0); + read = recv (data->sockfd, buf, BUFSIZE, 0); if (read < 0) { DWORD err = WSAGetLastError (); @@ -315,10 +319,8 @@ if (localecho) { - printf ("0: (%d)", read); - fflush (stdout); - write (fileno (stdout), buf, read); - printf ("\n"); + buf[BUFSIZE] = '\0'; + logprintf ("0 (%d): %s\n", read, buf); } } } @@ -341,9 +343,9 @@ while (!data->stop) { DWORD read = 0; - char buf[256]; + char buf[BUFSIZE + 1]; logprintf ("%s (%d): going to ReadFile\n", thread_name, __LINE__); - if (!ReadFile (data->readh[1], buf, sizeof (buf), &read, FALSE)) + if (!ReadFile (data->readh[1], buf, BUFSIZE, &read, FALSE)) { logprintf ("%s: broken pipe\n", thread_name); break; @@ -380,17 +382,11 @@ if (ret) goto out; - logprintf ("%s (%d): going to echo\n", thread_name, __LINE__); - if (localecho) { - printf ("1: (%u)", (unsigned)read); - fflush (stdout); - write (fileno (stdout), buf, read); - printf ("\n"); + buf[BUFSIZE] = '\0'; + logprintf ("1 (%lu): %s\n", read, buf); } - - logprintf ("%s (%d): going to echo: done\n", thread_name, __LINE__); } } @@ -420,9 +416,9 @@ while (!data->stop) { DWORD read = 0; - char buf[256]; + char buf[BUFSIZE + 1]; - if (!ReadFile (data->readh[2], buf, sizeof (buf), &read, FALSE)) + if (!ReadFile (data->readh[2], buf, BUFSIZE, &read, FALSE)) { logprintf ("%s: broken pipe\n", thread_name); break; @@ -454,10 +450,8 @@ if (localecho) { - printf ("2: (%u)", (unsigned) read); - fflush (stdout); - write (fileno (stdout), buf, read); - printf ("\n"); + buf[BUFSIZE] = '\0'; + logprintf ("2 (%lu): %s\n", read, buf); } } } @@ -641,7 +635,7 @@ static WINAPI DWORD handle_connection (void *arg) { - PROCESS_INFORMATION pi = { 0 }; + PROCESS_INFORMATION pi; int s2 = (int) arg; /* sizeof (void*) == sizeof (int) */ int stderrsockfd = -1; unsigned short stderr_port = 0; @@ -827,18 +821,17 @@ CloseHandle (pi.hThread); pi.hThread = NULL; - /* Wait for stdin/stdout/stderr to close before exiting. */ - i = 0; stopped = 0; - /* Wait for the three threads (stdin/stdout/stderr) to finish. */ + /* Wait for the three threads (stdin/stdout/stderr) to finish, or + for the child to exit. */ while (i < 3) { DWORD waitCount = COUNTOF (waith) - stopped; DWORD w; w = WaitForMultipleObjects (waitCount, waith, FALSE, INFINITE); - if (WAIT_OBJECT_0 <= w && w < WAIT_OBJECT_0 + waitCount) + if (/* WAIT_OBJECT_0 <= w && */ w < WAIT_OBJECT_0 + waitCount) { DWORD j = w - WAIT_OBJECT_0; HANDLE h = waith[j]; @@ -887,7 +880,7 @@ } /* Also close the sockets. At least stdin - will be frequenly blocked in a recv call. */ + will be frequenly blocked in a recv call. */ if (s2 != -1) { shutdown (s2, 2); @@ -900,6 +893,7 @@ { shutdown (stderrsockfd, 2); closesocket (stderrsockfd); + stderrsockfd = -1; client_data->stderrsockfd = -1; } } @@ -949,9 +943,6 @@ closesocket (stderrsockfd); } - if (pi.hThread != NULL) - CloseHandle (pi.hThread); - release_data (client_data); return 0; @@ -1039,23 +1030,52 @@ } } +static const char* progname; + +static void usage (void) __attribute__((noreturn)); + +static void +usage (void) +{ + fprintf (stderr, +"%s: RSH server for Windows CE\n" +"Usage: rsh [-h] [-d] [-e] [-l FILE]\n" +"-h Give this help list\n" +"-d Debug mode\n" +"-e Echo child stdin/stdout/stderr to local console\n" +"-l FILE Log debug to FILE. Implies -d\n" +, progname); + exit (1); +} + int main (int argc, char **argv) { - int i; + int c; WSADATA wsad; WSAStartup (MAKEWORD (2, 0), &wsad); - for (i = 1; i < argc; i++) - if (strcmp(argv[i], "-d") == 0) - debug = 1; - else if (strcmp(argv[i], "-l") == 0) - localecho = 1; - else + progname = argv[0]; + while ((c = getopt (argc, argv, "hdel:")) != -1) + { + switch (c) { - fprintf (stderr, "unknown option %s\n", argv[i]); - exit (1); + case 'h': + usage (); + case 'd': + debug = 1; + break; + case 'e': + localecho = 1; + break; + case 'l': + logfile = optarg; + break; + default: + fprintf (stderr, "Unknown option -- %c\n", optopt); + usage (); } + } accept_connections (); return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2007-06-29 17:25:30
|
Revision: 1021 http://svn.sourceforge.net/cegcc/?rev=1021&view=rev Author: dannybackx Date: 2007-06-29 10:25:16 -0700 (Fri, 29 Jun 2007) Log Message: ----------- Change path to PipeLib Modified Paths: -------------- trunk/cegcc/tools/PipeLib/PipeTest/Makefile Modified: trunk/cegcc/tools/PipeLib/PipeTest/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeTest/Makefile 2007-06-28 23:36:22 UTC (rev 1020) +++ trunk/cegcc/tools/PipeLib/PipeTest/Makefile 2007-06-29 17:25:16 UTC (rev 1021) @@ -5,8 +5,8 @@ WARNFLAGS=-Wall -Wextra -INCLUDES=-I../PipeLib -LIBS=-L../PipeLib -lPipeLib +INCLUDES=-I.. +LIBS=-L.. -lPipeLib ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 23:36:24
|
Revision: 1020 http://svn.sourceforge.net/cegcc/?rev=1020&view=rev Author: pedroalves Date: 2007-06-28 16:36:22 -0700 (Thu, 28 Jun 2007) Log Message: ----------- Remove extra spaces. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:34:32 UTC (rev 1019) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:36:22 UTC (rev 1020) @@ -5,11 +5,11 @@ 2007-06-29 Pedro Alves <ped...@po...> - * PipeLib/PipeLib.cpp : Move ... - * PipeLib.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. - * PipeLib/PipeLib.h : Move ... - * PipeLib.h : ... here. - * PipeDev/Makefile : Delete. + * PipeLib/PipeLib.cpp: Move ... + * PipeLib.cpp: ... here. Include PipeDev.h instead of PipeDevice.h. + * PipeLib/PipeLib.h: Move ... + * PipeLib.h: ... here. + * PipeDev/Makefile: Delete. * Makefile (all): Add libPipeLib.a. (PipeLib.o, libPipeLib.a, clean-dev, clean-lib): New rules. (clean): Depend on clean-dev and clean-lib to do the clean work. @@ -17,12 +17,12 @@ 2007-06-29 Pedro Alves <ped...@po...> - * PipeDev/PipeDevice.cpp : Move ... - * PipeDev.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. - * PipeDev/PipeDevice.h : Move ... - * PipeDev.h : ... here. - * PipeDev/Makefile : Move ... - * Makefile : ... here. + * PipeDev/PipeDevice.cpp: Move ... + * PipeDev.cpp: ... here. Include PipeDev.h instead of PipeDevice.h. + * PipeDev/PipeDevice.h: Move ... + * PipeDev.h: ... here. + * PipeDev/Makefile: Move ... + * Makefile: ... here. (PipeDev_unstripped.dll): Depend on PipeDev.cpp and PipeDev.h. 2007-06-28 Pedro Alves <ped...@po...> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 23:34:34
|
Revision: 1019 http://svn.sourceforge.net/cegcc/?rev=1019&view=rev Author: pedroalves Date: 2007-06-28 16:34:32 -0700 (Thu, 28 Jun 2007) Log Message: ----------- * (PipeLib): Delete. * (PipeDev): Delete. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Removed Paths: ------------- trunk/cegcc/tools/PipeLib/PipeDev/ trunk/cegcc/tools/PipeLib/PipeLib/ Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:31:21 UTC (rev 1018) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:34:32 UTC (rev 1019) @@ -1,5 +1,10 @@ 2007-06-29 Pedro Alves <ped...@po...> + * (PipeLib): Delete. + * (PipeDev): Delete. + +2007-06-29 Pedro Alves <ped...@po...> + * PipeLib/PipeLib.cpp : Move ... * PipeLib.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. * PipeLib/PipeLib.h : Move ... This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 23:31:23
|
Revision: 1018 http://svn.sourceforge.net/cegcc/?rev=1018&view=rev Author: pedroalves Date: 2007-06-28 16:31:21 -0700 (Thu, 28 Jun 2007) Log Message: ----------- * PipeLib/PipeLib.cpp : Move ... * PipeLib.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. * PipeLib/PipeLib.h : Move ... * PipeLib.h : ... here. * PipeDev/Makefile : Delete. * Makefile (all): Add libPipeLib.a. (PipeLib.o, libPipeLib.a, clean-dev, clean-lib): New rules. (clean): Depend on clean-dev and clean-lib to do the clean work. (.PHONY): Add clean-dev and clean-lib. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/Makefile Added Paths: ----------- trunk/cegcc/tools/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib.h Removed Paths: ------------- trunk/cegcc/tools/PipeLib/PipeLib/Makefile trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:31:21 UTC (rev 1018) @@ -1,5 +1,17 @@ 2007-06-29 Pedro Alves <ped...@po...> + * PipeLib/PipeLib.cpp : Move ... + * PipeLib.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. + * PipeLib/PipeLib.h : Move ... + * PipeLib.h : ... here. + * PipeDev/Makefile : Delete. + * Makefile (all): Add libPipeLib.a. + (PipeLib.o, libPipeLib.a, clean-dev, clean-lib): New rules. + (clean): Depend on clean-dev and clean-lib to do the clean work. + (.PHONY): Add clean-dev and clean-lib. + +2007-06-29 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp : Move ... * PipeDev.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. * PipeDev/PipeDevice.h : Move ... Modified: trunk/cegcc/tools/PipeLib/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/Makefile 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/Makefile 2007-06-28 23:31:21 UTC (rev 1018) @@ -10,7 +10,7 @@ ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) -all: PipeDev.dll +all: PipeDev.dll libPipeLib.a PipeDev_unstripped.dll: PipeDev.cpp PipeDev.h Makefile $(CXX) $< -shared -o $@ $(ALLFLAGS) @@ -18,10 +18,22 @@ PipeDev.dll: PipeDev_unstripped.dll $(STRIP) $< -o $@ +PipeLib.o: PipeLib.cpp + $(CXX) $< -c -o $@ $(ALLFLAGS) + +libPipeLib.a: PipeLib.o + rm -f $@ + $(AR) r $@ $< + download: PipeDev.dll pcp PipeDev.dll ":/Windows/PipeDev.dll" -clean: - rm -f PipeDev.dll +clean-dev: + rm -f PipeDev.dll PipeDev_unstripped.dll -.PHONY: all clean download +clean-lib: + rm -f libPipeLib.a PipeLib.o + +clean: clean-dev clean-lib + +.PHONY: all clean clean-dev clean-lib download Deleted: trunk/cegcc/tools/PipeLib/PipeLib/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/Makefile 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/PipeLib/Makefile 2007-06-28 23:31:21 UTC (rev 1018) @@ -1,22 +0,0 @@ -TARGET=arm-wince-mingw32ce - -CXX=$(TARGET)-g++ -AR=$(TARGET)-ar - -INCLUDES=-I../PipeDev/ - -ALLFLAGS=$(INCLUDES) $(CXXFLAGS) - -all: libPipeLib.a - -PipeLib.o: PipeLib.cpp - $(CXX) $< -c -o $@ $(ALLFLAGS) - -libPipeLib.a: PipeLib.o - rm -f $@ - $(AR) r $@ $< - -clean: - rm -f libPipeLib.a PipeLib.o - -.PHONE: all clean Deleted: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-28 23:31:21 UTC (rev 1018) @@ -1,229 +0,0 @@ -/* Copyright (c) 2007, Pedro Alves - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include <PipeDevice.h> - -#include <windows.h> -#include <devload.h> -#include <stdlib.h> - -#define KEY_NAME_BASE L"PipeDevice_" -#define NAME_BASE L"PD" /* Pipe Device */ -#define MAX_INSTANCES 99 - -#if 0 - -/* Doesn't work on CE < 5 ... */ -static int -FindFreeInstanceIndex (void) -{ - HANDLE h; - DEVMGR_DEVICE_INFORMATION di; - WCHAR wzName[6]; - for (int i=0; i < MAX_INSTANCES; i++) - { - wsprintf (wzName, L"%s%02d:", NAME_BASE, i); - di.dwSize = sizeof (di); - h = FindFirstDevice (DeviceSearchByLegacyName, wzName, &di); - if (h == INVALID_HANDLE_VALUE) - return i; - CloseHandle (h); - } - return -1; -} -#endif - -static void -PrepareRegistryForInstance (DWORD dwIndex, WCHAR** wzKey) -{ - DWORD dw; - HKEY hk; - WCHAR szKeyName[255]; - WCHAR wzPrefix[4]; //3 letter + zero character - DWORD dwDisp; - swprintf (wzPrefix, L"%s%d", NAME_BASE, dwIndex / 10); - - swprintf (szKeyName, L"Drivers\\%s%d", KEY_NAME_BASE, dwIndex); - *wzKey = wcsdup (szKeyName); - - if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, - szKeyName, 0, NULL, 0, - KEY_WRITE, NULL, &hk, &dwDisp)) - { - wprintf (L"Failed to create registry key %s, error = %d\n", - szKeyName, (int) GetLastError ()); - return; - } - - RegSetValueEx (hk, L"dll", 0, REG_SZ, (BYTE *)DEVICE_DLL_NAME, - sizeof (DEVICE_DLL_NAME)); - RegSetValueEx (hk, L"prefix", 0, REG_SZ, (BYTE *)wzPrefix, - sizeof (wzPrefix)); - - dw = dwIndex % 10; - RegSetValueEx (hk, L"index", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); - - dw = DEVFLAGS_LOADLIBRARY | DEVFLAGS_NAKEDENTRIES; - RegSetValueEx (hk, L"Flags", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); - - RegCloseKey (hk); -} - -/* Undocumented, for pipedev.dll debugging purposes only. */ -extern "C" BOOL -SetPipeTag (HANDLE p, const WCHAR* name) -{ - if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_TAG, - (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), - NULL, 0, NULL, NULL)) - return FALSE; - return TRUE; -} - -static BOOL -SetPipeName (HANDLE p, WCHAR* name) -{ - if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_NAME, - (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), - NULL, 0, NULL, NULL)) - return FALSE; - return TRUE; -} - -extern "C" BOOL -GetPipeName (HANDLE p, WCHAR* name) -{ - DWORD actual; - if (!DeviceIoControl (p, PIPE_IOCTL_GET_PIPE_NAME, - NULL, 0, - (LPVOID)name, MAX_PATH * sizeof (WCHAR), - &actual, NULL)) - return FALSE; - return TRUE; -} - -extern "C" BOOL -CreatePipe (PHANDLE hReadPipe, - PHANDLE hWritePipe, - LPSECURITY_ATTRIBUTES lpPipeAttributes, - DWORD nSize) -{ - int inst; - WCHAR* wsKey; - HANDLE h; - - *hReadPipe = NULL; - *hWritePipe = NULL; - - for (inst = 0 ; inst < MAX_INSTANCES; inst++) - { - PrepareRegistryForInstance (inst, &wsKey); - h = ActivateDevice (wsKey, 0); - RegDeleteKey (HKEY_LOCAL_MACHINE, wsKey); - free (wsKey); - - /* Although MSDN documentcs that error should - return INVALID_HANDLE_VALUE, I see it returning - NULL here. */ - if (h != INVALID_HANDLE_VALUE && h != NULL) - break; - } - - if (inst == MAX_INSTANCES) - return FALSE; - - /* name + num + ':' + '0' */ - wchar_t device_name[(sizeof (NAME_BASE) - 1) + 2 + 1 + 1]; - wsprintf (device_name, L"%s%02d:", NAME_BASE, inst); - - *hReadPipe = CreateFile (device_name, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - SetPipeName (*hReadPipe, device_name); - - *hWritePipe = CreateFile (device_name, - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - return TRUE; -} - -#if 0 - -struct PeekStruct -{ - DWORD Size; /* for future extension */ - PVOID lpBuffer, - DWORD nBufferSize, - - /* TODO: We need to use MapPtr for this to work */ - LPDWORD lpBytesRead, - LPDWORD lpTotalBytesAvail, - LPDWORD lpBytesLeftThisMessage - }; - -BOOL -PeekNamedPipe (HANDLE hNamedPipe, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesRead, - LPDWORD lpTotalBytesAvail, - LPDWORD lpBytesLeftThisMessage - ) -{ - DWORD avail; - DWORD actual; - - PeekStruct data; - data.Size = sizeof (PeekStruct); - data.lpBuffer = lpBuffer; - data.nBufferSize = nBufferSize; - data.lpBytesRead = lpBytesRead; - data.lpTotalBytesAvail = lpTotalBytesAvail; - data.lpBytesLeftThisMessage = lpBytesLeftThisMessage; - - if (!DeviceIoControl (hNamedPipe, PIPE_IOCTRL_PEEK_NAMED_PIPE, - NULL, 0, - (LPVOID)&data, sizeof (PeekStruct), &actual, NULL)) - return FALSE; - - /* We can detect here if we are talking to an older driver. */ - if (actual != data.Size) - return FALSE; - - return FALSE; -} - -#endif Deleted: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-28 23:31:21 UTC (rev 1018) @@ -1,46 +0,0 @@ -/* Copyright (c) 2007, Pedro Alves - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#ifndef __PIPE_LIB_H__ -#define __PIPE_LIB_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); -BOOL GetPipeName (HANDLE, WCHAR*); - -/* Internal, for pipedev.dll debugging purposes. */ -BOOL SetPipeTag (HANDLE, const WCHAR*); - -#ifdef __cplusplus -} -#endif - - -#endif Copied: trunk/cegcc/tools/PipeLib/PipeLib.cpp (from rev 1011, trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp) =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.cpp (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeLib.cpp 2007-06-28 23:31:21 UTC (rev 1018) @@ -0,0 +1,229 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "PipeDev.h" + +#include <windows.h> +#include <devload.h> +#include <stdlib.h> + +#define KEY_NAME_BASE L"PipeDevice_" +#define NAME_BASE L"PD" /* Pipe Device */ +#define MAX_INSTANCES 99 + +#if 0 + +/* Doesn't work on CE < 5 ... */ +static int +FindFreeInstanceIndex (void) +{ + HANDLE h; + DEVMGR_DEVICE_INFORMATION di; + WCHAR wzName[6]; + for (int i=0; i < MAX_INSTANCES; i++) + { + wsprintf (wzName, L"%s%02d:", NAME_BASE, i); + di.dwSize = sizeof (di); + h = FindFirstDevice (DeviceSearchByLegacyName, wzName, &di); + if (h == INVALID_HANDLE_VALUE) + return i; + CloseHandle (h); + } + return -1; +} +#endif + +static void +PrepareRegistryForInstance (DWORD dwIndex, WCHAR** wzKey) +{ + DWORD dw; + HKEY hk; + WCHAR szKeyName[255]; + WCHAR wzPrefix[4]; //3 letter + zero character + DWORD dwDisp; + swprintf (wzPrefix, L"%s%d", NAME_BASE, dwIndex / 10); + + swprintf (szKeyName, L"Drivers\\%s%d", KEY_NAME_BASE, dwIndex); + *wzKey = wcsdup (szKeyName); + + if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, + szKeyName, 0, NULL, 0, + KEY_WRITE, NULL, &hk, &dwDisp)) + { + wprintf (L"Failed to create registry key %s, error = %d\n", + szKeyName, (int) GetLastError ()); + return; + } + + RegSetValueEx (hk, L"dll", 0, REG_SZ, (BYTE *)DEVICE_DLL_NAME, + sizeof (DEVICE_DLL_NAME)); + RegSetValueEx (hk, L"prefix", 0, REG_SZ, (BYTE *)wzPrefix, + sizeof (wzPrefix)); + + dw = dwIndex % 10; + RegSetValueEx (hk, L"index", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); + + dw = DEVFLAGS_LOADLIBRARY | DEVFLAGS_NAKEDENTRIES; + RegSetValueEx (hk, L"Flags", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); + + RegCloseKey (hk); +} + +/* Undocumented, for pipedev.dll debugging purposes only. */ +extern "C" BOOL +SetPipeTag (HANDLE p, const WCHAR* name) +{ + if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_TAG, + (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), + NULL, 0, NULL, NULL)) + return FALSE; + return TRUE; +} + +static BOOL +SetPipeName (HANDLE p, WCHAR* name) +{ + if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_NAME, + (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), + NULL, 0, NULL, NULL)) + return FALSE; + return TRUE; +} + +extern "C" BOOL +GetPipeName (HANDLE p, WCHAR* name) +{ + DWORD actual; + if (!DeviceIoControl (p, PIPE_IOCTL_GET_PIPE_NAME, + NULL, 0, + (LPVOID)name, MAX_PATH * sizeof (WCHAR), + &actual, NULL)) + return FALSE; + return TRUE; +} + +extern "C" BOOL +CreatePipe (PHANDLE hReadPipe, + PHANDLE hWritePipe, + LPSECURITY_ATTRIBUTES lpPipeAttributes, + DWORD nSize) +{ + int inst; + WCHAR* wsKey; + HANDLE h; + + *hReadPipe = NULL; + *hWritePipe = NULL; + + for (inst = 0 ; inst < MAX_INSTANCES; inst++) + { + PrepareRegistryForInstance (inst, &wsKey); + h = ActivateDevice (wsKey, 0); + RegDeleteKey (HKEY_LOCAL_MACHINE, wsKey); + free (wsKey); + + /* Although MSDN documentcs that error should + return INVALID_HANDLE_VALUE, I see it returning + NULL here. */ + if (h != INVALID_HANDLE_VALUE && h != NULL) + break; + } + + if (inst == MAX_INSTANCES) + return FALSE; + + /* name + num + ':' + '0' */ + wchar_t device_name[(sizeof (NAME_BASE) - 1) + 2 + 1 + 1]; + wsprintf (device_name, L"%s%02d:", NAME_BASE, inst); + + *hReadPipe = CreateFile (device_name, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + SetPipeName (*hReadPipe, device_name); + + *hWritePipe = CreateFile (device_name, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + return TRUE; +} + +#if 0 + +struct PeekStruct +{ + DWORD Size; /* for future extension */ + PVOID lpBuffer, + DWORD nBufferSize, + + /* TODO: We need to use MapPtr for this to work */ + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage + }; + +BOOL +PeekNamedPipe (HANDLE hNamedPipe, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage + ) +{ + DWORD avail; + DWORD actual; + + PeekStruct data; + data.Size = sizeof (PeekStruct); + data.lpBuffer = lpBuffer; + data.nBufferSize = nBufferSize; + data.lpBytesRead = lpBytesRead; + data.lpTotalBytesAvail = lpTotalBytesAvail; + data.lpBytesLeftThisMessage = lpBytesLeftThisMessage; + + if (!DeviceIoControl (hNamedPipe, PIPE_IOCTRL_PEEK_NAMED_PIPE, + NULL, 0, + (LPVOID)&data, sizeof (PeekStruct), &actual, NULL)) + return FALSE; + + /* We can detect here if we are talking to an older driver. */ + if (actual != data.Size) + return FALSE; + + return FALSE; +} + +#endif Copied: trunk/cegcc/tools/PipeLib/PipeLib.h (from rev 1011, trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h) =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.h (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeLib.h 2007-06-28 23:31:21 UTC (rev 1018) @@ -0,0 +1,46 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef __PIPE_LIB_H__ +#define __PIPE_LIB_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); +BOOL GetPipeName (HANDLE, WCHAR*); + +/* Internal, for pipedev.dll debugging purposes. */ +BOOL SetPipeTag (HANDLE, const WCHAR*); + +#ifdef __cplusplus +} +#endif + + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 23:21:45
|
Revision: 1017 http://svn.sourceforge.net/cegcc/?rev=1017&view=rev Author: pedroalves Date: 2007-06-28 16:20:53 -0700 (Thu, 28 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.cpp : Move ... * PipeDev.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. * PipeDev/PipeDevice.h : Move ... * PipeDev.h : ... here. * PipeDev/Makefile : Move ... * Makefile : ... here. (PipeDev_unstripped.dll): Depend on PipeDev.cpp and PipeDev.h. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Added Paths: ----------- trunk/cegcc/tools/PipeLib/Makefile trunk/cegcc/tools/PipeLib/PipeDev.cpp trunk/cegcc/tools/PipeLib/PipeDev.h Removed Paths: ------------- trunk/cegcc/tools/PipeLib/PipeDev/Makefile trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:56:18 UTC (rev 1016) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:20:53 UTC (rev 1017) @@ -1,3 +1,13 @@ +2007-06-29 Pedro Alves <ped...@po...> + + * PipeDev/PipeDevice.cpp : Move ... + * PipeDev.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. + * PipeDev/PipeDevice.h : Move ... + * PipeDev.h : ... here. + * PipeDev/Makefile : Move ... + * Makefile : ... here. + (PipeDev_unstripped.dll): Depend on PipeDev.cpp and PipeDev.h. + 2007-06-28 Pedro Alves <ped...@po...> * PipeDev/PipeDevice.cpp (RecursiveCS): New implementation. Copied: trunk/cegcc/tools/PipeLib/Makefile (from rev 1002, trunk/cegcc/tools/PipeLib/PipeDev/Makefile) =================================================================== --- trunk/cegcc/tools/PipeLib/Makefile (rev 0) +++ trunk/cegcc/tools/PipeLib/Makefile 2007-06-28 23:20:53 UTC (rev 1017) @@ -0,0 +1,27 @@ +TARGET=arm-wince-mingw32ce + +CXX=$(TARGET)-g++ +AR=$(TARGET)-ar +STRIP=$(TARGET)-strip + +WARNFLAGS=-Wall -Wextra + +INCLUDES= + +ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) + +all: PipeDev.dll + +PipeDev_unstripped.dll: PipeDev.cpp PipeDev.h Makefile + $(CXX) $< -shared -o $@ $(ALLFLAGS) + +PipeDev.dll: PipeDev_unstripped.dll + $(STRIP) $< -o $@ + +download: PipeDev.dll + pcp PipeDev.dll ":/Windows/PipeDev.dll" + +clean: + rm -f PipeDev.dll + +.PHONY: all clean download Deleted: trunk/cegcc/tools/PipeLib/PipeDev/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/Makefile 2007-06-28 00:56:18 UTC (rev 1016) +++ trunk/cegcc/tools/PipeLib/PipeDev/Makefile 2007-06-28 23:20:53 UTC (rev 1017) @@ -1,27 +0,0 @@ -TARGET=arm-wince-mingw32ce - -CXX=$(TARGET)-g++ -AR=$(TARGET)-ar -STRIP=$(TARGET)-strip - -WARNFLAGS=-Wall -Wextra - -INCLUDES= - -ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) - -all: PipeDev.dll - -PipeDev_unstripped.dll: PipeDevice.cpp Makefile - $(CXX) $< -shared -o $@ $(ALLFLAGS) - -PipeDev.dll: PipeDev_unstripped.dll - $(STRIP) $< -o $@ - -download: PipeDev.dll - pcp PipeDev.dll ":/Windows/PipeDev.dll" - -clean: - rm -f PipeDev.dll - -.PHONY: all clean download Deleted: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:56:18 UTC (rev 1016) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 23:20:53 UTC (rev 1017) @@ -1,956 +0,0 @@ -/* Copyright (c) 2007, Pedro Alves - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include "PipeDevice.h" - -#include <windows.h> -#include <devload.h> -#include <set> -#include <string> - -#ifndef min -#define min(A, B) ((A) < (B) ? (A) : (B)) -#endif - -typedef struct _DEVICE_PSL_NOTIFY -{ - DWORD dwSize; - DWORD dwFlags; - HANDLE hProc; - HANDLE hThread; -} DEVICE_PSL_NOTIFY, *PDEVICE_PSL_NOTIFY; - -#ifndef FILE_DEVICE_PSL -#define FILE_DEVICE_PSL 259 -#endif - -#define IOCTL_PSL_NOTIFY \ - CTL_CODE (FILE_DEVICE_PSL, 255, METHOD_NEITHER, FILE_ANY_ACCESS) - -#define DLL_PROCESS_EXITING 4 - -#define PIPEDEV_API extern "C" __declspec (dllexport) - -//#define DEBUG_MODE -//#define NOLOCKS -//#define DEBUG_LOCKS - -#ifdef DEBUG_LOCKS -# define G(CS) (__LINE__, CS) -#else -# define G(CS) (CS) -#endif - -#ifdef DEBUG_MODE -static void -LogMessage2 (const char* msg) -{ - FILE* log = fopen ("pipelog.txt", "a+"); - fprintf (log, "%s", msg); - fclose (log); -} - -static void -LogMessage (const char *file, int line, const char* msg, ...) -{ - va_list ap; - char buf[1024]; - char *b = buf; - va_start (ap, msg); - sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); - b += strlen (b); - vsprintf (b, msg, ap); - va_end (ap); - - LogMessage2 (buf); -} - -struct LogScope -{ - explicit LogScope (const char *func, const char* msg) - : func_(func) - , msg_(msg) - { - char buf[512]; - sprintf (buf, "> %s", msg_); - LogMessage (func_, -1, buf); - } - ~LogScope () - { - char buf[512]; - sprintf (buf, "< %s", msg_); - LogMessage (func_, -1, buf); - } - - const char* func_; - const char* msg_; -}; - -# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) -# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) -#else -# define LOG(MSG, ...) do; while (0) -# define LOGSCOPE(MSG) do; while (0) -#endif - -class CSWrapper -{ -public: - explicit CSWrapper (CRITICAL_SECTION* cs) : cs_(*cs) {} - ~CSWrapper () {} - - void Lock () - { -#ifndef NOLOCKS - EnterCriticalSection (&cs_); -#endif - } - void Unlock () - { -#ifndef NOLOCKS - LeaveCriticalSection (&cs_); -#endif - } -private: - CRITICAL_SECTION& cs_; -}; - -class CS : public CSWrapper -{ -public: - CS () : CSWrapper (&cs_) - { -#ifndef NOLOCKS - InitializeCriticalSection (&cs_); -#endif - } - ~CS () - { -#ifndef NOLOCKS - DeleteCriticalSection (&cs_); -#endif - } -private: - CRITICAL_SECTION cs_; -}; - -class RecursiveCS -{ - public: - RecursiveCS(); - ~RecursiveCS(); - - void Lock(); - void Unlock(); - - private: - LONG Locks; - DWORD ThreadID; - DWORD Count; - HANDLE EventHandle; -}; - -RecursiveCS::RecursiveCS() - : Locks(0) - , ThreadID(0) - , Count(0) -{ -#ifndef NOLOCKS - /* auto - only release one at a time. */ - EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); -#endif -} - -RecursiveCS::~RecursiveCS() -{ -#ifndef NOLOCKS - CloseHandle (EventHandle); -#endif -} - -void -RecursiveCS::Lock() -{ -#ifndef NOLOCKS - int test; - do - test = Locks; - while (InterlockedCompareExchange(&Locks, test + 1, test) != test); - - if (test != 0) - { - if (ThreadID != GetCurrentThreadId()) - { - /* Get in line */ - WaitForSingleObject (EventHandle, INFINITE); - } - - /* No need to wait anymore. */ - InterlockedDecrement (&Locks); - } - ThreadID = GetCurrentThreadId(); - ++Count; -#endif -} - -void -RecursiveCS::Unlock() -{ -#ifndef NOLOCKS - if (!--Count) - { - ThreadID = 0; - - if (InterlockedCompareExchange (&Locks, 0, 1) != 1) - SetEvent (EventHandle); - } -#endif -} - -#ifdef DEBUG_LOCKS -template <class T> -class LockGuard -{ -public: - LockGuard (int line, T &cs) : cs_(cs), lineno(line) - { - LOG ("+LockGuard: line : %d\n", line); - cs_.Lock (); - } - ~LockGuard () - { - LOG ("~LockGuard: line : %d\n", lineno); - cs_.Unlock (); - } - -private: - T &cs_; - - int lineno; -}; -#else -template <class T> -class LockGuard -{ -public: - explicit LockGuard (T &cs) : cs_(cs) { cs_.Lock (); } - ~LockGuard () { cs_.Unlock (); } - -private: - T &cs_; -}; -#endif - -class PipeOpenContext; - -class PipeDeviceContext -{ -public: - typedef ::LockGuard<PipeDeviceContext> LockGuard; - - explicit PipeDeviceContext (LPCWSTR activepath) - : OpenCount(0) - , WROpenCount(0) - , DeviceName(NULL) - , DeviceTag(NULL) - , Aborting(FALSE) -#ifdef DEBUG_MODE - , TotalWritten(0) - , TotalRead(0) -#endif - , head(0) - , count(0) - { - ActivePath = wcsdup (activepath); - ReadEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - WriteEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - - /* This should wake all threads, so it is manual reset. */ - AbortEvent = CreateEvent (NULL, TRUE, FALSE, NULL); - } - - ~PipeDeviceContext () - { - if (DeviceName) - free (DeviceName); - if (DeviceTag) - free (DeviceTag); - if (ActivePath) - free (ActivePath); - CloseHandle (ReadEvent); - CloseHandle (WriteEvent); - CloseHandle (AbortEvent); - } - - DWORD size () - { - return count; - } - - DWORD tail () - { - return (head + count) & (sizeof (buffer) - 1); - } - - void Lock () - { - cs.Lock (); - } - - void Unlock () - { - cs.Unlock (); - } - - DWORD writeBytes (const BYTE* data, DWORD dsize) - { - DWORD fit = sizeof (buffer) - size (); - fit = min (dsize, fit); - DWORD t = tail (); - for (DWORD i = 0; i < fit; i++) - buffer[(t + i) & (sizeof (buffer) - 1)] = data[i]; - count += fit; -#ifdef DEBUG_MODE - TotalWritten += fit; -#endif - return fit; - } - - DWORD readBytes (BYTE* buf, DWORD bsize) - { - DWORD fit = min (bsize, size ()); - for (DWORD i = 0; i < fit; i++) - buf[i] = buffer[(head + i) & (sizeof (buffer) - 1)]; - count -= fit; - head += fit; - head &= (sizeof (buffer) - 1); -#ifdef DEBUG_MODE - TotalRead += fit; -#endif - return fit; - } - -public: - DWORD OpenCount; - DWORD WROpenCount; - - WCHAR* ActivePath; - - HANDLE ReadEvent; - HANDLE WriteEvent; - HANDLE AbortEvent; - - WCHAR* DeviceName; - WCHAR* DeviceTag; - BOOL Aborting; - -#ifdef DEBUG_MODE - DWORD TotalWritten; - DWORD TotalRead; -#endif - -private: - BYTE buffer[0x1000]; - DWORD head; - DWORD count; - - RecursiveCS cs; -}; - -class PipeOpenContext -{ -public: - PipeOpenContext (PipeDeviceContext* devctx, - DWORD accessCode, DWORD shareMode) - : DeviceContext (devctx) - , dwAccessCode (accessCode) - , dwShareMode (shareMode) - {} - - ~PipeOpenContext () - {} - - PipeDeviceContext* DeviceContext; - DWORD dwAccessCode; - DWORD dwShareMode; -}; - -static CRITICAL_SECTION open_pipes_cs; - -extern "C" BOOL WINAPI -DllMain (HANDLE /*hinstDLL*/, DWORD dwReason, LPVOID /*lpvReserved*/) -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - InitializeCriticalSection (&open_pipes_cs); - break; - case DLL_PROCESS_DETACH: - DeleteCriticalSection (&open_pipes_cs); - break; - } - - return TRUE; -} - -/* This is needed for MSVC, but it makes no harm in gcc. */ -struct ltwstr -{ - bool operator () (const std::wstring& s1, const std::wstring& s2) const - { - return wcscmp (s1.c_str (), s2.c_str ()) < 0; - } -}; - -typedef std::set<std::wstring, ltwstr> vwstring; -static vwstring open_pipes; - -PIPEDEV_API BOOL Deinit (PipeDeviceContext* pDeviceContext); - -static HANDLE -GetDeviceHandle (PipeDeviceContext* pDeviceContext) -{ - LOGSCOPE ("\n"); - HKEY hActive; - DWORD Type; - HANDLE hDev = INVALID_HANDLE_VALUE; - - DWORD status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, pDeviceContext->ActivePath, - 0, 0, &hActive); - if (status != ERROR_SUCCESS) - return INVALID_HANDLE_VALUE; - - DWORD Len = sizeof(hDev); - status = RegQueryValueEx (hActive, DEVLOAD_HANDLE_VALNAME, NULL, &Type, - (PUCHAR)&hDev, &Len); - if (status != ERROR_SUCCESS) - { - /* weird */ - } - - RegCloseKey (hActive); - - return hDev; -} - -#ifdef DEBUG_MODE - -static DWORD WINAPI -LogThread (void *arg) -{ - PipeDeviceContext* dev = (PipeDeviceContext*)arg; - - int count = 0; - - while (1) - switch (WaitForSingleObject (dev->AbortEvent, 1000)) - { - case WAIT_TIMEOUT: - { - PipeDeviceContext::LockGuard guard G(*dev); - LOG ("(%08d)\t" - "%ls\t" - "buffer size = %lu\t" - "read = %lu\t" - "write = %lu\n", - count++, - dev->DeviceTag ?: L"(notag)", - dev->size (), - dev->TotalRead, - dev->TotalWritten); - } - break; - default: - return 0; - } - - return 0; -} -#endif - -PIPEDEV_API DWORD -Init (LPCTSTR pContext) -{ - LOGSCOPE ("\n"); - CSWrapper cs (&open_pipes_cs); - LockGuard<CSWrapper> guard G(cs); - - LOG ("%ls\n", pContext); - - /* TODO: The key here isn't exactly the best. Maybe we should use - the device name instead, and get that from the registry - that would - also get rid of the IOCTL calls. */ - if (open_pipes.find (pContext) != open_pipes.end ()) - /* already open, PipeLib will try another one. */ - return 0; - - PipeDeviceContext* pDeviceContext = new PipeDeviceContext (pContext); - if (pDeviceContext == NULL) - return 0; - -#ifdef DEBUG_MODE - CloseHandle (CreateThread (NULL, 0, LogThread, (void*)pDeviceContext, 0, NULL)); -#endif - - open_pipes.insert (pContext); - - return (DWORD)pDeviceContext; -} - -#ifdef DEBUG_MODE -static int close_calls; -#endif - -PIPEDEV_API BOOL -Deinit (PipeDeviceContext* pDeviceContext) -{ - LOGSCOPE ("\n"); - /* All file handles must to be closed before deinitialising - the driver. */ - -#ifdef DEBUG_MODE - if (pDeviceContext) - LOG ("oc %lu, wc: %lu, close_calls: %d\n", - pDeviceContext->OpenCount, - pDeviceContext->WROpenCount, - close_calls); - else - LOG ("close_calls: %d\n", close_calls); -#endif - - if (pDeviceContext == NULL) - return FALSE; - - { - PipeDeviceContext::LockGuard guard G(*pDeviceContext); - - if (pDeviceContext->OpenCount != 0) - return FALSE; - } - - LOG ("deactivate success\n"); - - /* Allow reuse. */ - open_pipes.erase (pDeviceContext->ActivePath); - - /* Race? Is it possible that there can be another process - calling any function on the device while we are - Dinitializing it? Doesn't CE take care of that? */ - delete pDeviceContext; - return TRUE; -} - -PIPEDEV_API DWORD -Open (PipeDeviceContext* pDeviceContext, DWORD AccessCode, DWORD ShareMode) -{ - LOGSCOPE ("\n"); - - LOG ("oc %lu, wc: %lu, AccessCode %x, ShareMode %x\n", - pDeviceContext->OpenCount, pDeviceContext->WROpenCount, - AccessCode, ShareMode); - - PipeOpenContext* pOpenContext = - new PipeOpenContext (pDeviceContext, AccessCode, ShareMode); - - LOG ("going to lock\n"); - - PipeDeviceContext::LockGuard guard G(*pOpenContext->DeviceContext); - - LOG ("locked\n"); - - pDeviceContext->OpenCount++; - - if (AccessCode & GENERIC_WRITE) - pDeviceContext->WROpenCount++; - - LOG ("OpenCount: %lu, WROpenCount: %lu\n", - pDeviceContext->OpenCount, - pDeviceContext->WROpenCount); - - return (DWORD)pOpenContext; -} - -static DWORD WINAPI -Deactivator (HANDLE dev) -{ - LOGSCOPE ("\n"); - - if (!DeactivateDevice (dev)) - LOG("deactivate failed\n"); - else - LOG("deactivate success\n"); - - return 0; -} - -static void -DeactivatePipeDevice (PipeDeviceContext* dev) -{ - LOGSCOPE ("\n"); - HANDLE hdev = GetDeviceHandle (dev); - HANDLE h = CreateThread (NULL, 0, Deactivator, hdev, 0, NULL); - CloseHandle (h); -} - -PIPEDEV_API BOOL -Close (PipeOpenContext* pOpenContext) -{ - LOGSCOPE ("\n"); -#ifdef DEBUG_MODE - close_calls++; -#endif - - if (pOpenContext) - LOG ("oc %lu, wc: %lu\n", - pOpenContext->DeviceContext->OpenCount, - pOpenContext->DeviceContext->WROpenCount); - else - LOG ("openctx %p\n", pOpenContext); - - if (pOpenContext == NULL) - return FALSE; - - PipeDeviceContext* dev = pOpenContext->DeviceContext; - - PipeDeviceContext::LockGuard guard G(*dev); - - if (dev->OpenCount == 0) - return FALSE; - - dev->OpenCount--; - if (pOpenContext->dwAccessCode & GENERIC_WRITE) - dev->WROpenCount--; - - if (dev->WROpenCount == 0 || dev->OpenCount == 0) - /* Wake up the other side so it can see the broken pipe. */ - SetEvent (dev->AbortEvent); - - delete pOpenContext; - - LOG ("oc %lu, wc: %lu\n", - dev->OpenCount, dev->WROpenCount); - - if (dev->OpenCount == 0) - { - /* Deactivating the device here seems to corrupt Device.exe, and - sometimes hangs the device. Do it in an auxilary thread. */ - /* Perhaps this should be made safer. If anotherthread was just - waken up due to the SetEvent above, this will be a race. - Perhaps we need a wait counter per device and have the - deactivator thread wait for it to reach 0 ... Irks, this is - getting fishy. */ - DeactivatePipeDevice (dev); - } - - return TRUE; -} - -PIPEDEV_API DWORD -Read (PipeOpenContext* pOpenContext, BYTE* pBuffer, DWORD dwCount) -{ - LOGSCOPE ("\n"); - - if (IsBadReadPtr (pBuffer, dwCount)) - { - SetLastError (ERROR_INVALID_PARAMETER); - LOG ("\n"); - return -1; - } - - DWORD needed = dwCount; - - if (pOpenContext == NULL - || (pOpenContext->dwAccessCode & GENERIC_READ) == 0) - { - LOG ("Invalid access or no context\n"); - return (DWORD)-1; - } - - PipeDeviceContext* dev = pOpenContext->DeviceContext; - - BOOL breaknext = FALSE; - HANDLE Events[2]; - - do - { - LOG ("new iteration\n"); - - { - PipeDeviceContext::LockGuard guard G(*dev); - - Events[0] = dev->AbortEvent; - Events[1] = dev->WriteEvent; - - /* Read before checking for broken pipe, so - we get a chance to return valid data when that - happens. */ - DWORD read = dev->readBytes (pBuffer, dwCount); - pBuffer += read; - dwCount -= read; - - if (read) - SetEvent (dev->ReadEvent); - - if (dev->Aborting /* this device is long gone, */ - || dev->WROpenCount == 0 /* or broken pipe */ - || dev->OpenCount == 0 /* or, ... weird */ - ) - { - SetLastError (ERROR_BROKEN_PIPE); - if (needed - dwCount) - { - /* I don't know a way to report error and 'valid - data' at the same time. Is there a way? Instead - we report 'valid' and the next Read call will error. */ - LOG ("Pipe broken, but with data\n"); - break; - } - LOG ("Pipe broken\n"); - return (DWORD) -1; - } - - if (read || dwCount == 0) - { - /* We've either read something or pBuffer_ is full. */ - LOG ("read || dwCount == 0\n"); - break; - } - - if (breaknext) - break; - } - - LOG ("going to wait for data\n"); - - /* The buffer was empty, wait for data. */ - switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) - { - case WAIT_OBJECT_0 + 1: - /* Data was written to the pipe. Do one more iteration - to fetch what we can and bail out. */ - LOG ("write event detected\n"); - breaknext = TRUE; - break; - default: - /* With either wait error or AbortEvent - signaled, return with error. */ - LOG ("WaitForMultipleObjects default case\n"); - return (DWORD) -1; - } - } - while (dwCount); - - LOG ("Read: %u\n", needed - dwCount); - return needed - dwCount; -} - -PIPEDEV_API DWORD -Write (PipeOpenContext* pOpenContext, const BYTE* pBuffer, DWORD dwCount) -{ - LOGSCOPE ("\n"); - - if (IsBadWritePtr ((void*) pBuffer, dwCount)) - { - SetLastError (ERROR_INVALID_PARAMETER); - LOG ("\n"); - return -1; - } - - DWORD needed = dwCount; - - LOG ("oc %lu, wc: %lu\n", - pOpenContext->DeviceContext->OpenCount, - pOpenContext->DeviceContext->WROpenCount); - - if (pOpenContext == NULL - || (pOpenContext->dwAccessCode & GENERIC_WRITE) == 0) - { - LOG ("Invalid access or no context\n"); - return (DWORD)-1; - } - - PipeDeviceContext* dev = pOpenContext->DeviceContext; - - BOOL breaknext = FALSE; - HANDLE Events[2]; - - do - { - LOG ("new iteration\n"); - - { - PipeDeviceContext::LockGuard guard G(*dev); - - LOG ("lock acquired\n"); - - Events[0] = dev->AbortEvent; - Events[1] = dev->ReadEvent; - - if (dev->Aborting) - { - /* this device is long gone */ - SetLastError (ERROR_NO_DATA); - LOG ("Device is gone\n"); - return (DWORD)-1; - } - - if (dev->OpenCount == 0) - { - /* weird */ - SetLastError (ERROR_NO_DATA); - LOG ("Device is not open\n"); - return (DWORD)-1; - } - - if (dev->OpenCount == dev->WROpenCount) - { - /* no readers */ - SetLastError (ERROR_NO_DATA); - LOG ("No readers left: oc %lu, wc: %lu\n", - dev->OpenCount, - dev->WROpenCount); - return (DWORD)-1; - } - - DWORD wrote = dev->writeBytes (pBuffer, dwCount); - pBuffer += wrote; - dwCount -= wrote; - - LOG ("written %lu\n", wrote); - - /* According to MSDN, a write of 0, also wakes - the reading end of the pipe. */ - PulseEvent (dev->WriteEvent); - - if (dwCount == 0) - break; - - if (breaknext) - break; - } - - LOG ("going to wait for event\n"); - switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) - { - case WAIT_OBJECT_0 + 1: - LOG ("got read event\n"); - breaknext = TRUE; - break; - default: - /* With either wait error or AbortEvent - signaled, return with error. */ - LOG ("WaitForMultipleObjects default case\n"); - return (DWORD) -1; - } - } - while (dwCount); - - LOG ("returning %u\n", needed - dwCount); - return needed - dwCount; -} - -PIPEDEV_API DWORD -Seek (PipeOpenContext* /*pOpenContext*/, long /*Amount*/, WORD /*wType*/) -{ - LOGSCOPE ("\n"); - /* Pipes don't support seeking. */ - return (DWORD)-1; -} - -PIPEDEV_API BOOL -IOControl (PipeOpenContext* pOpenContext, DWORD dwCode, - PBYTE pBufIn, DWORD dwLenIn, - PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) -{ - LOGSCOPE ("\n"); - - /* Kill unused warnings. */ - (void)pBufIn; - (void)dwLenIn; - (void)pBufOut; - (void)dwLenOut; - (void)pdwActualOut; - - BOOL bRet = FALSE; - - if (pOpenContext == NULL) - return FALSE; - - PipeDeviceContext* dev = pOpenContext->DeviceContext; - PipeDeviceContext::LockGuard guard G(*dev); - -#ifdef DEBUG_MODE - LOG ("%x : %d\n", dwCode, dev->OpenCount); -#endif - - if (dwCode == IOCTL_PSL_NOTIFY) - { - PDEVICE_PSL_NOTIFY pPslPacket = (PDEVICE_PSL_NOTIFY)pBufIn; - - if (pPslPacket->dwSize == sizeof (DEVICE_PSL_NOTIFY) - && pPslPacket->dwFlags == DLL_PROCESS_EXITING) - { - LOG ("Process dying: %p : %p\n", pPslPacket->hProc, pPslPacket->hThread); - dev->Aborting = TRUE; - /* Unlock all blocked threads. */ - SetEvent (dev->AbortEvent); - } - return TRUE; - } - - switch (dwCode) - { - case PIPE_IOCTL_SET_PIPE_TAG: - if (dev->DeviceTag) - free (dev->DeviceTag); - dev->DeviceTag = wcsdup ((WCHAR*)pBufIn); - bRet = TRUE; - break; - case PIPE_IOCTL_SET_PIPE_NAME: - if (dev->DeviceName) - free (dev->DeviceName); - dev->DeviceName = wcsdup ((WCHAR*)pBufIn); - bRet = TRUE; - break; - case PIPE_IOCTL_GET_PIPE_NAME: - wcscpy ( (WCHAR*)pBufOut, dev->DeviceName); - *pdwActualOut = (wcslen (dev->DeviceName) + 1) * sizeof (WCHAR); - bRet = TRUE; - break; - } - - return bRet; -} - -PIPEDEV_API void -PowerDown (PipeDeviceContext* /*pDeviceContext*/) -{ -} - -PIPEDEV_API void -PowerUp (PipeDeviceContext* /*pDeviceContext*/) -{ -} Deleted: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-28 00:56:18 UTC (rev 1016) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-28 23:20:53 UTC (rev 1017) @@ -1,44 +0,0 @@ -/* Copyright (c) 2007, Pedro Alves - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#ifndef __PIPEDEVICE_H__ -#define __PIPEDEVICE_H__ - -#include <windows.h> -#include <winioctl.h> - -#define PIPE_IOCTL_SET_PIPE_NAME \ - CTL_CODE(FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define PIPE_IOCTL_GET_PIPE_NAME \ - CTL_CODE(FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define PIPE_IOCTL_SET_PIPE_TAG \ - CTL_CODE(FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define DEVICE_DLL_NAME L"PipeDev.dll" - -#endif Copied: trunk/cegcc/tools/PipeLib/PipeDev.cpp (from rev 1015, trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp) =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev.cpp (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeDev.cpp 2007-06-28 23:20:53 UTC (rev 1017) @@ -0,0 +1,956 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "PipeDev.h" + +#include <windows.h> +#include <devload.h> +#include <set> +#include <string> + +#ifndef min +#define min(A, B) ((A) < (B) ? (A) : (B)) +#endif + +typedef struct _DEVICE_PSL_NOTIFY +{ + DWORD dwSize; + DWORD dwFlags; + HANDLE hProc; + HANDLE hThread; +} DEVICE_PSL_NOTIFY, *PDEVICE_PSL_NOTIFY; + +#ifndef FILE_DEVICE_PSL +#define FILE_DEVICE_PSL 259 +#endif + +#define IOCTL_PSL_NOTIFY \ + CTL_CODE (FILE_DEVICE_PSL, 255, METHOD_NEITHER, FILE_ANY_ACCESS) + +#define DLL_PROCESS_EXITING 4 + +#define PIPEDEV_API extern "C" __declspec (dllexport) + +//#define DEBUG_MODE +//#define NOLOCKS +//#define DEBUG_LOCKS + +#ifdef DEBUG_LOCKS +# define G(CS) (__LINE__, CS) +#else +# define G(CS) (CS) +#endif + +#ifdef DEBUG_MODE +static void +LogMessage2 (const char* msg) +{ + FILE* log = fopen ("pipelog.txt", "a+"); + fprintf (log, "%s", msg); + fclose (log); +} + +static void +LogMessage (const char *file, int line, const char* msg, ...) +{ + va_list ap; + char buf[1024]; + char *b = buf; + va_start (ap, msg); + sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); + b += strlen (b); + vsprintf (b, msg, ap); + va_end (ap); + + LogMessage2 (buf); +} + +struct LogScope +{ + explicit LogScope (const char *func, const char* msg) + : func_(func) + , msg_(msg) + { + char buf[512]; + sprintf (buf, "> %s", msg_); + LogMessage (func_, -1, buf); + } + ~LogScope () + { + char buf[512]; + sprintf (buf, "< %s", msg_); + LogMessage (func_, -1, buf); + } + + const char* func_; + const char* msg_; +}; + +# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) +# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) +#else +# define LOG(MSG, ...) do; while (0) +# define LOGSCOPE(MSG) do; while (0) +#endif + +class CSWrapper +{ +public: + explicit CSWrapper (CRITICAL_SECTION* cs) : cs_(*cs) {} + ~CSWrapper () {} + + void Lock () + { +#ifndef NOLOCKS + EnterCriticalSection (&cs_); +#endif + } + void Unlock () + { +#ifndef NOLOCKS + LeaveCriticalSection (&cs_); +#endif + } +private: + CRITICAL_SECTION& cs_; +}; + +class CS : public CSWrapper +{ +public: + CS () : CSWrapper (&cs_) + { +#ifndef NOLOCKS + InitializeCriticalSection (&cs_); +#endif + } + ~CS () + { +#ifndef NOLOCKS + DeleteCriticalSection (&cs_); +#endif + } +private: + CRITICAL_SECTION cs_; +}; + +class RecursiveCS +{ + public: + RecursiveCS(); + ~RecursiveCS(); + + void Lock(); + void Unlock(); + + private: + LONG Locks; + DWORD ThreadID; + DWORD Count; + HANDLE EventHandle; +}; + +RecursiveCS::RecursiveCS() + : Locks(0) + , ThreadID(0) + , Count(0) +{ +#ifndef NOLOCKS + /* auto - only release one at a time. */ + EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); +#endif +} + +RecursiveCS::~RecursiveCS() +{ +#ifndef NOLOCKS + CloseHandle (EventHandle); +#endif +} + +void +RecursiveCS::Lock() +{ +#ifndef NOLOCKS + int test; + do + test = Locks; + while (InterlockedCompareExchange(&Locks, test + 1, test) != test); + + if (test != 0) + { + if (ThreadID != GetCurrentThreadId()) + { + /* Get in line */ + WaitForSingleObject (EventHandle, INFINITE); + } + + /* No need to wait anymore. */ + InterlockedDecrement (&Locks); + } + ThreadID = GetCurrentThreadId(); + ++Count; +#endif +} + +void +RecursiveCS::Unlock() +{ +#ifndef NOLOCKS + if (!--Count) + { + ThreadID = 0; + + if (InterlockedCompareExchange (&Locks, 0, 1) != 1) + SetEvent (EventHandle); + } +#endif +} + +#ifdef DEBUG_LOCKS +template <class T> +class LockGuard +{ +public: + LockGuard (int line, T &cs) : cs_(cs), lineno(line) + { + LOG ("+LockGuard: line : %d\n", line); + cs_.Lock (); + } + ~LockGuard () + { + LOG ("~LockGuard: line : %d\n", lineno); + cs_.Unlock (); + } + +private: + T &cs_; + + int lineno; +}; +#else +template <class T> +class LockGuard +{ +public: + explicit LockGuard (T &cs) : cs_(cs) { cs_.Lock (); } + ~LockGuard () { cs_.Unlock (); } + +private: + T &cs_; +}; +#endif + +class PipeOpenContext; + +class PipeDeviceContext +{ +public: + typedef ::LockGuard<PipeDeviceContext> LockGuard; + + explicit PipeDeviceContext (LPCWSTR activepath) + : OpenCount(0) + , WROpenCount(0) + , DeviceName(NULL) + , DeviceTag(NULL) + , Aborting(FALSE) +#ifdef DEBUG_MODE + , TotalWritten(0) + , TotalRead(0) +#endif + , head(0) + , count(0) + { + ActivePath = wcsdup (activepath); + ReadEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + WriteEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + + /* This should wake all threads, so it is manual reset. */ + AbortEvent = CreateEvent (NULL, TRUE, FALSE, NULL); + } + + ~PipeDeviceContext () + { + if (DeviceName) + free (DeviceName); + if (DeviceTag) + free (DeviceTag); + if (ActivePath) + free (ActivePath); + CloseHandle (ReadEvent); + CloseHandle (WriteEvent); + CloseHandle (AbortEvent); + } + + DWORD size () + { + return count; + } + + DWORD tail () + { + return (head + count) & (sizeof (buffer) - 1); + } + + void Lock () + { + cs.Lock (); + } + + void Unlock () + { + cs.Unlock (); + } + + DWORD writeBytes (const BYTE* data, DWORD dsize) + { + DWORD fit = sizeof (buffer) - size (); + fit = min (dsize, fit); + DWORD t = tail (); + for (DWORD i = 0; i < fit; i++) + buffer[(t + i) & (sizeof (buffer) - 1)] = data[i]; + count += fit; +#ifdef DEBUG_MODE + TotalWritten += fit; +#endif + return fit; + } + + DWORD readBytes (BYTE* buf, DWORD bsize) + { + DWORD fit = min (bsize, size ()); + for (DWORD i = 0; i < fit; i++) + buf[i] = buffer[(head + i) & (sizeof (buffer) - 1)]; + count -= fit; + head += fit; + head &= (sizeof (buffer) - 1); +#ifdef DEBUG_MODE + TotalRead += fit; +#endif + return fit; + } + +public: + DWORD OpenCount; + DWORD WROpenCount; + + WCHAR* ActivePath; + + HANDLE ReadEvent; + HANDLE WriteEvent; + HANDLE AbortEvent; + + WCHAR* DeviceName; + WCHAR* DeviceTag; + BOOL Aborting; + +#ifdef DEBUG_MODE + DWORD TotalWritten; + DWORD TotalRead; +#endif + +private: + BYTE buffer[0x1000]; + DWORD head; + DWORD count; + + RecursiveCS cs; +}; + +class PipeOpenContext +{ +public: + PipeOpenContext (PipeDeviceContext* devctx, + DWORD accessCode, DWORD shareMode) + : DeviceContext (devctx) + , dwAccessCode (accessCode) + , dwShareMode (shareMode) + {} + + ~PipeOpenContext () + {} + + PipeDeviceContext* DeviceContext; + DWORD dwAccessCode; + DWORD dwShareMode; +}; + +static CRITICAL_SECTION open_pipes_cs; + +extern "C" BOOL WINAPI +DllMain (HANDLE /*hinstDLL*/, DWORD dwReason, LPVOID /*lpvReserved*/) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + InitializeCriticalSection (&open_pipes_cs); + break; + case DLL_PROCESS_DETACH: + DeleteCriticalSection (&open_pipes_cs); + break; + } + + return TRUE; +} + +/* This is needed for MSVC, but it makes no harm in gcc. */ +struct ltwstr +{ + bool operator () (const std::wstring& s1, const std::wstring& s2) const + { + return wcscmp (s1.c_str (), s2.c_str ()) < 0; + } +}; + +typedef std::set<std::wstring, ltwstr> vwstring; +static vwstring open_pipes; + +PIPEDEV_API BOOL Deinit (PipeDeviceContext* pDeviceContext); + +static HANDLE +GetDeviceHandle (PipeDeviceContext* pDeviceContext) +{ + LOGSCOPE ("\n"); + HKEY hActive; + DWORD Type; + HANDLE hDev = INVALID_HANDLE_VALUE; + + DWORD status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, pDeviceContext->ActivePath, + 0, 0, &hActive); + if (status != ERROR_SUCCESS) + return INVALID_HANDLE_VALUE; + + DWORD Len = sizeof(hDev); + status = RegQueryValueEx (hActive, DEVLOAD_HANDLE_VALNAME, NULL, &Type, + (PUCHAR)&hDev, &Len); + if (status != ERROR_SUCCESS) + { + /* weird */ + } + + RegCloseKey (hActive); + + return hDev; +} + +#ifdef DEBUG_MODE + +static DWORD WINAPI +LogThread (void *arg) +{ + PipeDeviceContext* dev = (PipeDeviceContext*)arg; + + int count = 0; + + while (1) + switch (WaitForSingleObject (dev->AbortEvent, 1000)) + { + case WAIT_TIMEOUT: + { + PipeDeviceContext::LockGuard guard G(*dev); + LOG ("(%08d)\t" + "%ls\t" + "buffer size = %lu\t" + "read = %lu\t" + "write = %lu\n", + count++, + dev->DeviceTag ?: L"(notag)", + dev->size (), + dev->TotalRead, + dev->TotalWritten); + } + break; + default: + return 0; + } + + return 0; +} +#endif + +PIPEDEV_API DWORD +Init (LPCTSTR pContext) +{ + LOGSCOPE ("\n"); + CSWrapper cs (&open_pipes_cs); + LockGuard<CSWrapper> guard G(cs); + + LOG ("%ls\n", pContext); + + /* TODO: The key here isn't exactly the best. Maybe we should use + the device name instead, and get that from the registry - that would + also get rid of the IOCTL calls. */ + if (open_pipes.find (pContext) != open_pipes.end ()) + /* already open, PipeLib will try another one. */ + return 0; + + PipeDeviceContext* pDeviceContext = new PipeDeviceContext (pContext); + if (pDeviceContext == NULL) + return 0; + +#ifdef DEBUG_MODE + CloseHandle (CreateThread (NULL, 0, LogThread, (void*)pDeviceContext, 0, NULL)); +#endif + + open_pipes.insert (pContext); + + return (DWORD)pDeviceContext; +} + +#ifdef DEBUG_MODE +static int close_calls; +#endif + +PIPEDEV_API BOOL +Deinit (PipeDeviceContext* pDeviceContext) +{ + LOGSCOPE ("\n"); + /* All file handles must to be closed before deinitialising + the driver. */ + +#ifdef DEBUG_MODE + if (pDeviceContext) + LOG ("oc %lu, wc: %lu, close_calls: %d\n", + pDeviceContext->OpenCount, + pDeviceContext->WROpenCount, + close_calls); + else + LOG ("close_calls: %d\n", close_calls); +#endif + + if (pDeviceContext == NULL) + return FALSE; + + { + PipeDeviceContext::LockGuard guard G(*pDeviceContext); + + if (pDeviceContext->OpenCount != 0) + return FALSE; + } + + LOG ("deactivate success\n"); + + /* Allow reuse. */ + open_pipes.erase (pDeviceContext->ActivePath); + + /* Race? Is it possible that there can be another process + calling any function on the device while we are + Dinitializing it? Doesn't CE take care of that? */ + delete pDeviceContext; + return TRUE; +} + +PIPEDEV_API DWORD +Open (PipeDeviceContext* pDeviceContext, DWORD AccessCode, DWORD ShareMode) +{ + LOGSCOPE ("\n"); + + LOG ("oc %lu, wc: %lu, AccessCode %x, ShareMode %x\n", + pDeviceContext->OpenCount, pDeviceContext->WROpenCount, + AccessCode, ShareMode); + + PipeOpenContext* pOpenContext = + new PipeOpenContext (pDeviceContext, AccessCode, ShareMode); + + LOG ("going to lock\n"); + + PipeDeviceContext::LockGuard guard G(*pOpenContext->DeviceContext); + + LOG ("locked\n"); + + pDeviceContext->OpenCount++; + + if (AccessCode & GENERIC_WRITE) + pDeviceContext->WROpenCount++; + + LOG ("OpenCount: %lu, WROpenCount: %lu\n", + pDeviceContext->OpenCount, + pDeviceContext->WROpenCount); + + return (DWORD)pOpenContext; +} + +static DWORD WINAPI +Deactivator (HANDLE dev) +{ + LOGSCOPE ("\n"); + + if (!DeactivateDevice (dev)) + LOG("deactivate failed\n"); + else + LOG("deactivate success\n"); + + return 0; +} + +static void +DeactivatePipeDevice (PipeDeviceContext* dev) +{ + LOGSCOPE ("\n"); + HANDLE hdev = GetDeviceHandle (dev); + HANDLE h = CreateThread (NULL, 0, Deactivator, hdev, 0, NULL); + CloseHandle (h); +} + +PIPEDEV_API BOOL +Close (PipeOpenContext* pOpenContext) +{ + LOGSCOPE ("\n"); +#ifdef DEBUG_MODE + close_calls++; +#endif + + if (pOpenContext) + LOG ("oc %lu, wc: %lu\n", + pOpenContext->DeviceContext->OpenCount, + pOpenContext->DeviceContext->WROpenCount); + else + LOG ("openctx %p\n", pOpenContext); + + if (pOpenContext == NULL) + return FALSE; + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + PipeDeviceContext::LockGuard guard G(*dev); + + if (dev->OpenCount == 0) + return FALSE; + + dev->OpenCount--; + if (pOpenContext->dwAccessCode & GENERIC_WRITE) + dev->WROpenCount--; + + if (dev->WROpenCount == 0 || dev->OpenCount == 0) + /* Wake up the other side so it can see the broken pipe. */ + SetEvent (dev->AbortEvent); + + delete pOpenContext; + + LOG ("oc %lu, wc: %lu\n", + dev->OpenCount, dev->WROpenCount); + + if (dev->OpenCount == 0) + { + /* Deactivating the device here seems to corrupt Device.exe, and + sometimes hangs the device. Do it in an auxilary thread. */ + /* Perhaps this should be made safer. If anotherthread was just + waken up due to the SetEvent above, this will be a race. + Perhaps we need a wait counter per device and have the + deactivator thread wait for it to reach 0 ... Irks, this is + getting fishy. */ + DeactivatePipeDevice (dev); + } + + return TRUE; +} + +PIPEDEV_API DWORD +Read (PipeOpenContext* pOpenContext, BYTE* pBuffer, DWORD dwCount) +{ + LOGSCOPE ("\n"); + + if (IsBadReadPtr (pBuffer, dwCount)) + { + SetLastError (ERROR_INVALID_PARAMETER); + LOG ("\n"); + return -1; + } + + DWORD needed = dwCount; + + if (pOpenContext == NULL + || (pOpenContext->dwAccessCode & GENERIC_READ) == 0) + { + LOG ("Invalid access or no context\n"); + return (DWORD)-1; + } + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + BOOL breaknext = FALSE; + HANDLE Events[2]; + + do + { + LOG ("new iteration\n"); + + { + PipeDeviceContext::LockGuard guard G(*dev); + + Events[0] = dev->AbortEvent; + Events[1] = dev->WriteEvent; + + /* Read before checking for broken pipe, so + we get a chance to return valid data when that + happens. */ + DWORD read = dev->readBytes (pBuffer, dwCount); + pBuffer += read; + dwCount -= read; + + if (read) + SetEvent (dev->ReadEvent); + + if (dev->Aborting /* this device is long gone, */ + || dev->WROpenCount == 0 /* or broken pipe */ + || dev->OpenCount == 0 /* or, ... weird */ + ) + { + SetLastError (ERROR_BROKEN_PIPE); + if (needed - dwCount) + { + /* I don't know a way to report error and 'valid + data' at the same time. Is there a way? Instead + we report 'valid' and the next Read call will error. */ + LOG ("Pipe broken, but with data\n"); + break; + } + LOG ("Pipe broken\n"); + return (DWORD) -1; + } + + if (read || dwCount == 0) + { + /* We've either read something or pBuffer_ is full. */ + LOG ("read || dwCount == 0\n"); + break; + } + + if (breaknext) + break; + } + + LOG ("going to wait for data\n"); + + /* The buffer was empty, wait for data. */ + switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) + { + case WAIT_OBJECT_0 + 1: + /* Data was written to the pipe. Do one more iteration + to fetch what we can and bail out. */ + LOG ("write event detected\n"); + breaknext = TRUE; + break; + default: + /* With either wait error or AbortEvent + signaled, return with error. */ + LOG ("WaitForMultipleObjects default case\n"); + return (DWORD) -1; + } + } + while (dwCount); + + LOG ("Read: %u\n", needed - dwCount); + return needed - dwCount; +} + +PIPEDEV_API DWORD +Write (PipeOpenContext* pOpenContext, const BYTE* pBuffer, DWORD dwCount) +{ + LOGSCOPE ("\n"); + + if (IsBadWritePtr ((void*) pBuffer, dwCount)) + { + SetLastError (ERROR_INVALID_PARAMETER); + LOG ("\n"); + return -1; + } + + DWORD needed = dwCount; + + LOG ("oc %lu, wc: %lu\n", + pOpenContext->DeviceContext->OpenCount, + pOpenContext->DeviceContext->WROpenCount); + + if (pOpenContext == NULL + || (pOpenContext->dwAccessCode & GENERIC_WRITE) == 0) + { + LOG ("Invalid access or no context\n"); + return (DWORD)-1; + } + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + BOOL breaknext = FALSE; + HANDLE Events[2]; + + do + { + LOG ("new iteration\n"); + + { + PipeDeviceContext::LockGuard guard G(*dev); + + LOG ("lock acquired\n"); + + Events[0] = dev->AbortEvent; + Events[1] = dev->ReadEvent; + + if (dev->Aborting) + { + /* this device is long gone */ + SetLastError (ERROR_NO_DATA); + LOG ("Device is gone\n"); + return (DWORD)-1; + } + + if (dev->OpenCount == 0) + { + /* weird */ + SetLastError (ERROR_NO_DATA); + LOG ("Device is not open\n"); + return (DWORD)-1; + } + + if (dev->OpenCount == dev->WROpenCount) + { + /* no readers */ + SetLastError (ERROR_NO_DATA); + LOG ("No readers left: oc %lu, wc: %lu\n", + dev->OpenCount, + dev->WROpenCount); + return (DWORD)-1; + } + + DWORD wrote = dev->writeBytes (pBuffer, dwCount); + pBuffer += wrote; + dwCount -= wrote; + + LOG ("written %lu\n", wrote); + + /* According to MSDN, a write of 0, also wakes + the reading end of the pipe. */ + PulseEvent (dev->WriteEvent); + + if (dwCount == 0) + break; + + if (breaknext) + break; + } + + LOG ("going to wait for event\n"); + switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) + { + case WAIT_OBJECT_0 + 1: + LOG ("got read event\n"); + breaknext = TRUE; + break; + default: + /* With either wait error or AbortEvent + signaled, return with error. */ + LOG ("WaitForMultipleObjects default case\n"); + return (DWORD) -1; + } + } + while (dwCount); + + LOG ("returning %u\n", needed - dwCount); + return needed - dwCount; +} + +PIPEDEV_API DWORD +Seek (PipeOpenContext* /*pOpenContext*/, long /*Amount*/, WORD /*wType*/) +{ + LOGSCOPE ("\n"); + /* Pipes don't support seeking. */ + return (DWORD)-1; +} + +PIPEDEV_API BOOL +IOControl (PipeOpenContext* pOpenContext, DWORD dwCode, + PBYTE pBufIn, DWORD dwLenIn, + PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) +{ + LOGSCOPE ("\n"); + + /* Kill unused warnings. */ + (void)pBufIn; + (void)dwLenIn; + (void)pBufOut; + (void)dwLenOut; + (void)pdwActualOut; + + BOOL bRet = FALSE; + + if (pOpenContext == NULL) + return FALSE; + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + PipeDeviceContext::LockGuard guard G(*dev); + +#ifdef DEBUG_MODE + LOG ("%x : %d\n", dwCode, dev->OpenCount); +#endif + + if (dwCode == IOCTL_PSL_NOTIFY) + { + PDEVICE_PSL_NOTIFY pPslPacket = (PDEVICE_PSL_NOTIFY)pBufIn; + + if (pPslPacket->dwSize == sizeof (DEVICE_PSL_NOTIFY) + && pPslPacket->dwFlags == DLL_PROCESS_EXITING) + { + LOG ("Process dying: %p : %p\n", pPslPacket->hProc, pPslPacket->hThread); + dev->Aborting = TRUE; + /* Unlock all blocked threads. */ + SetEvent (dev->AbortEvent); + } + return TRUE; + } + + switch (dwCode) + { + case PIPE_IOCTL_SET_PIPE_TAG: + if (dev->DeviceTag) + free (dev->DeviceTag); + dev->DeviceTag = wcsdup ((WCHAR*)pBufIn); + bRet = TRUE; + break; + case PIPE_IOCTL_SET_PIPE_NAME: + if (dev->DeviceName) + free (dev->DeviceName); + dev->DeviceName = wcsdup ((WCHAR*)pBufIn); + bRet = TRUE; + break; + case PIPE_IOCTL_GET_PIPE_NAME: + wcscpy ( (WCHAR*)pBufOut, dev->DeviceName); + *pdwActualOut = (wcslen (dev->DeviceName) + 1) * sizeof (WCHAR); + bRet = TRUE; + break; + } + + return bRet; +} + +PIPEDEV_API void +PowerDown (PipeDeviceContext* /*pDeviceContext*/) +{ +} + +PIPEDEV_API void +PowerUp (PipeDeviceContext* /*pDeviceContext*/) +{ +} Copied: trunk/cegcc/tools/PipeLib/PipeDev.h (from rev 1012, trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h) =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev.h (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeDev.h 2007-06-28 23:20:53 UTC (rev 1017) @@ -0,0 +1,44 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef __PIPEDEVICE_H__ +#define __PIPEDEVICE_H__ + +#include <windows.h> +#include <winioctl.h> + +#define PIPE_IOCTL_SET_PIPE_NAME \ + CTL_CODE(FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define PIPE_IOCTL_GET_PIPE_NAME \ + CTL_CODE(FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define PIPE_IOCTL_SET_PIPE_TAG \ + CTL_CODE(FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define DEVICE_DLL_NAME L"PipeDev.dll" + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 00:56:19
|
Revision: 1016 http://svn.sourceforge.net/cegcc/?rev=1016&view=rev Author: pedroalves Date: 2007-06-27 17:56:18 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * rshd.c (localecho): New global. (stdin_thread, stdout_thread, stderr_thread): Exit thread with exit code of 1 if the thread is closing because the host closed. Echo to local console depending on localecho instead of debug. (create_child): Use SetPipeTag. (handle_connection): If creating the child failed, report an error message to the host. If the remote host closed the connection abruptly, kill the child. (main): Map -l option to localecho global var. Modified Paths: -------------- trunk/cegcc/tools/rshd/ChangeLog trunk/cegcc/tools/rshd/rshd.c Modified: trunk/cegcc/tools/rshd/ChangeLog =================================================================== --- trunk/cegcc/tools/rshd/ChangeLog 2007-06-28 00:44:14 UTC (rev 1015) +++ trunk/cegcc/tools/rshd/ChangeLog 2007-06-28 00:56:18 UTC (rev 1016) @@ -1,3 +1,15 @@ +2007-06-28 Pedro Alves <ped...@po...> + + * rshd.c (localecho): New global. + (stdin_thread, stdout_thread, stderr_thread): Exit thread with + exit code of 1 if the thread is closing because the host closed. + Echo to local console depending on localecho instead of debug. + (create_child): Use SetPipeTag. + (handle_connection): If creating the child failed, report an error + message to the host. If the remote host closed the connection + abruptly, kill the child. + (main): Map -l option to localecho global var. + 2007-06-26 Pedro Alves <ped...@po...> * Makefile (all): Depend on $(BINS) not $(TARGETS). Modified: trunk/cegcc/tools/rshd/rshd.c =================================================================== --- trunk/cegcc/tools/rshd/rshd.c 2007-06-28 00:44:14 UTC (rev 1015) +++ trunk/cegcc/tools/rshd/rshd.c 2007-06-28 00:56:18 UTC (rev 1016) @@ -43,6 +43,7 @@ #endif static BOOL debug = FALSE; +static BOOL localecho = FALSE; @@ -248,11 +249,18 @@ } #endif +/* All 3 threads return 0 if they are closing because the pipes were + broken due to the child closing them, and 1 if the remote side + closed the sockets before the child died. We use this knowledge in + the main WaitForMultipleObjects to kill the child if the remote + side closed the connection. */ + static DWORD WINAPI stdin_thread (void *arg) { struct client_data_t *data = arg; const char *thread_name = "stdin_thread"; + DWORD ret = 0; addref_data (data); @@ -277,7 +285,9 @@ logprintf ("%s: recv ERROR, winerr %d\n", thread_name, err); break; } - break; + if (!data->stop) + ret = 1; + goto out; } else if (read == 0) { @@ -303,7 +313,7 @@ SafeCloseHandle (&data->readh[0]); } - if (debug) + if (localecho) { printf ("0: (%d)", read); fflush (stdout); @@ -313,9 +323,10 @@ } } +out: release_data (data); - logprintf ("%s gone\n", thread_name); - return 0; + logprintf ("%s gone : %lu\n", thread_name, ret); + return ret; } static DWORD WINAPI @@ -323,6 +334,7 @@ { struct client_data_t *data = arg; const char *thread_name = "stdout_thread"; + DWORD ret = 0; addref_data (data); @@ -330,6 +342,7 @@ { DWORD read = 0; char buf[256]; + logprintf ("%s (%d): going to ReadFile\n", thread_name, __LINE__); if (!ReadFile (data->readh[1], buf, sizeof (buf), &read, FALSE)) { logprintf ("%s: broken pipe\n", thread_name); @@ -337,15 +350,20 @@ } else { + logprintf ("%s (%d): ReadFile ok: %lu\n", thread_name, __LINE__, read); /* We can't close the write side of the pipe until the child opens its version. Since it will only be open on the first stdout access, we have to wait until the read side returns something - which means the child opened stdout. */ SafeCloseHandle (&data->writeh[1]); + logprintf ("%s (%d): SafeCloseHandle ok\n", thread_name, __LINE__); } if (read) { - int written = send (data->sockfd, buf, read, 0); + int written; + logprintf ("%s (%d): going to send\n", thread_name, __LINE__); + written = send (data->sockfd, buf, read, 0); + ret = 1; if (written < 0) logprintf ("%s: write ERROR, winerr %d\n", thread_name, @@ -353,20 +371,34 @@ else if ((DWORD) written < read) logprintf ("%s: ERROR only wrote %d of %d bytes\n", thread_name, written, read); + else + { + logprintf ("%s (%d): sent ok\n", thread_name, __LINE__); + ret = 0; + } - if (debug) + if (ret) + goto out; + + logprintf ("%s (%d): going to echo\n", thread_name, __LINE__); + + if (localecho) { printf ("1: (%u)", (unsigned)read); fflush (stdout); write (fileno (stdout), buf, read); printf ("\n"); } + + logprintf ("%s (%d): going to echo: done\n", thread_name, __LINE__); } } + out: + logprintf ("%s (%d): at out\n", thread_name, __LINE__); release_data (data); - logprintf ("%s gone\n", thread_name); - return 0; + logprintf ("%s gone : %lu\n", thread_name, ret); + return ret; } static DWORD WINAPI @@ -375,6 +407,7 @@ struct client_data_t *data = arg; const char *thread_name = "stderr_thread"; int sockfd; + DWORD ret = 0; addref_data (data); @@ -405,6 +438,7 @@ if (read) { int written = send (sockfd, buf, read, 0); + ret = 1; if (written < 0) logprintf ("%s: write ERROR, winerr %d\n", thread_name, @@ -412,8 +446,13 @@ else if ((DWORD) written < read) logprintf ("%s: ERROR only wrote %d of %d bytes\n", thread_name, written, read); + else + ret = 0; - if (debug) + if (ret) + goto out; + + if (localecho) { printf ("2: (%u)", (unsigned) read); fflush (stdout); @@ -423,9 +462,10 @@ } } + out: release_data (data); - logprintf ("%s gone\n", thread_name); - return 0; + logprintf ("%s gone : %lu\n", thread_name, ret); + return ret; } static void @@ -480,6 +520,9 @@ if (!CreatePipe (&readh[i], &writeh[i], NULL, 0)) return NULL; + wsprintf (devname, L"dev%d", i); + SetPipeTag (readh[i], devname); + GetPipeName (readh[i], devname); DWORD dwLen = MAX_PATH; GetStdioPathW (i, prev_path[i], &dwLen); @@ -696,7 +739,6 @@ *p++ = c; *p = 0; - if ((stderr_port = atoi (stderrport)) > 0) { stderrsockfd = connect_stderr (s2, stderr_port); @@ -764,8 +806,12 @@ hndproc = create_child (command, client_data->readh, client_data->writeh, &pi); if (!hndproc) { + static char buf[1024]; + DWORD err = GetLastError (); logprintf ("handle_connection: ERROR can't create child process, " - "winerr %d\n", GetLastError ()); + "winerr %lu\n", err); + sprintf (buf, "can't create process\n%s\n", strwinerror (err)); + send (s2, buf, strlen (buf), 0); goto shutdown; } @@ -796,26 +842,43 @@ { DWORD j = w - WAIT_OBJECT_0; HANDLE h = waith[j]; + DWORD ec = 0; + BOOL abrupt; - /* Let's not wait for this handle again. */ - CloseHandle (waith[j]); - for (;j < COUNTOF (waith) - 1; j++) - waith[j] = waith[j + 1]; - waith[COUNTOF (waith) - 1] = INVALID_HANDLE_VALUE; - stopped++; - if (h == hndproc && stopped < COUNTOF (waith)) + /* i counts threads */ + if (h != hndproc) + i++; + + abrupt = (h != hndproc + && !client_data->stop + && (GetExitCodeThread (h, &ec) && ec == 1)); + + if (debug) { + fprintf (stderr, "j = %ld, abrupt = %d, stopped = %ld, i = %d\n", + j, abrupt, stopped, i); + fflush (stderr); + } + + if (abrupt + || (h == hndproc && stopped < COUNTOF (waith))) + { int k; - /* The child died without ever opening it's side - of the pipe, so our threads didn't see it close, - because we never closed our side. */ + /* if (h == hndproc, the child died without ever opening + it's side of the pipe, so our threads didn't see it + close, because we never closed our side. */ /* Tell the threads we are stopping. */ client_data->stop = 1; + if (abrupt) + /* A thread died abruptly. This means the remote side + is gone (SIGINT p.ex.). Let's kill the child. */ + TerminateProcess (hndproc, 1); + /* Close them now. */ for (k = 0; k < 3; k++) { @@ -840,8 +903,12 @@ client_data->stderrsockfd = -1; } } - else if (h != hndproc) - i++; + + /* Let's not wait for this handle again. */ + CloseHandle (waith[j]); + for (;j < COUNTOF (waith) - 1; j++) + waith[j] = waith[j + 1]; + waith[COUNTOF (waith) - 1] = INVALID_HANDLE_VALUE; } else { @@ -975,11 +1042,20 @@ int main (int argc, char **argv) { + int i; WSADATA wsad; WSAStartup (MAKEWORD (2, 0), &wsad); - if (argc > 1 && strcmp(argv[1], "-d") == 0) - debug = 1; + for (i = 1; i < argc; i++) + if (strcmp(argv[i], "-d") == 0) + debug = 1; + else if (strcmp(argv[i], "-l") == 0) + localecho = 1; + else + { + fprintf (stderr, "unknown option %s\n", argv[i]); + exit (1); + } accept_connections (); return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 00:44:16
|
Revision: 1015 http://svn.sourceforge.net/cegcc/?rev=1015&view=rev Author: pedroalves Date: 2007-06-27 17:44:14 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.cpp (RecursiveCS): New implementation. (LockGuard): Better split the DEBUG_LOCKS version. (LockGuard::LockGuard) [DEBUG_LOCKS]: Prepend a "+" to the log output. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:34:03 UTC (rev 1014) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:44:14 UTC (rev 1015) @@ -1,5 +1,11 @@ 2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (RecursiveCS): New implementation. + (LockGuard): Better split the DEBUG_LOCKS version. + (LockGuard::LockGuard) [DEBUG_LOCKS]: Prepend a "+" to the log output. + +2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (FastCS): Delete. 2007-06-28 Pedro Alves <ped...@po...> Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:34:03 UTC (rev 1014) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:44:14 UTC (rev 1015) @@ -159,78 +159,85 @@ class RecursiveCS { -public : - RecursiveCS () - : Count(0) - , RecursionCount(0) - , ThreadID(0) + public: + RecursiveCS(); + ~RecursiveCS(); - { + void Lock(); + void Unlock(); + + private: + LONG Locks; + DWORD ThreadID; + DWORD Count; + HANDLE EventHandle; +}; + +RecursiveCS::RecursiveCS() + : Locks(0) + , ThreadID(0) + , Count(0) +{ #ifndef NOLOCKS - /* auto - only release one at a time. */ - EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); + /* auto - only release one at a time. */ + EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); #endif - } +} - ~RecursiveCS () - { +RecursiveCS::~RecursiveCS() +{ #ifndef NOLOCKS - CloseHandle (EventHandle); + CloseHandle (EventHandle); #endif - } +} - void Lock () - { +void +RecursiveCS::Lock() +{ #ifndef NOLOCKS - if (ThreadID == GetCurrentThreadId ()) - { - InterlockedIncrement (&RecursionCount); - return; - } + int test; + do + test = Locks; + while (InterlockedCompareExchange(&Locks, test + 1, test) != test); - if (InterlockedIncrement (&Count) == 1) - InterlockedExchange (&RecursionCount, 0); - else - WaitForSingleObject (EventHandle, INFINITE); + if (test != 0) + { + if (ThreadID != GetCurrentThreadId()) + { + /* Get in line */ + WaitForSingleObject (EventHandle, INFINITE); + } - ThreadID = GetCurrentThreadId (); + /* No need to wait anymore. */ + InterlockedDecrement (&Locks); + } + ThreadID = GetCurrentThreadId(); + ++Count; #endif - } - - void Unlock () - { +} + +void +RecursiveCS::Unlock() +{ #ifndef NOLOCKS - if (RecursionCount == 0) - { - if (InterlockedDecrement (&Count) > 0) - { - /* release one thread */ - SetEvent (EventHandle); - } - } - else - { - InterlockedDecrement (&RecursionCount); - } + if (!--Count) + { + ThreadID = 0; + + if (InterlockedCompareExchange (&Locks, 0, 1) != 1) + SetEvent (EventHandle); + } #endif - } +} -private: - HANDLE EventHandle; - LONG Count; - LONG RecursionCount; - DWORD ThreadID; -}; - - +#ifdef DEBUG_LOCKS template <class T> class LockGuard { public: -#ifdef DEBUG_LOCKS LockGuard (int line, T &cs) : cs_(cs), lineno(line) { - LOG ("LockGuard: line : %d\n", line); + LOG ("+LockGuard: line : %d\n", line); cs_.Lock (); } ~LockGuard () @@ -238,18 +245,24 @@ LOG ("~LockGuard: line : %d\n", lineno); cs_.Unlock (); } + +private: + T &cs_; + + int lineno; +}; #else +template <class T> +class LockGuard +{ +public: explicit LockGuard (T &cs) : cs_(cs) { cs_.Lock (); } ~LockGuard () { cs_.Unlock (); } -#endif private: T &cs_; - -#ifdef DEBUG_LOCKS - int lineno; +}; #endif -}; class PipeOpenContext; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 00:34:06
|
Revision: 1014 http://svn.sourceforge.net/cegcc/?rev=1014&view=rev Author: pedroalves Date: 2007-06-27 17:34:03 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.cpp (FastCS): Delete. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:29:06 UTC (rev 1013) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:34:03 UTC (rev 1014) @@ -1,5 +1,9 @@ 2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (FastCS): Delete. + +2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (LogMessage2, LogMessage, LogScope) (LOG, LOGSCOPE): Move higher up in the file. (PipeDeviceContext::DeviceTag): New field. Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:29:06 UTC (rev 1013) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:34:03 UTC (rev 1014) @@ -157,47 +157,6 @@ CRITICAL_SECTION cs_; }; -class FastCS -{ -public: - FastCS () : Count(0) - { -#ifndef NOLOCKS - /* auto - only release one at a time. */ - EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); -#endif - } - ~FastCS () - { -#ifndef NOLOCKS - CloseHandle (EventHandle); -#endif - } - - void Lock () - { -#ifndef NOLOCKS - if (InterlockedIncrement (&Count) == 1) - /* first come - first serve. */ - return; - - /* everyone else, get in line. */ - WaitForSingleObject (EventHandle, INFINITE); -#endif - } - void Unlock () - { -#ifndef NOLOCKS - if (InterlockedDecrement (&Count) > 0) - /* release one pending */ - SetEvent (EventHandle); -#endif - } -private: - HANDLE EventHandle; - LONG Count; -}; - class RecursiveCS { public : This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 00:29:08
|
Revision: 1013 http://svn.sourceforge.net/cegcc/?rev=1013&view=rev Author: pedroalves Date: 2007-06-27 17:29:06 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.cpp (LogMessage2, LogMessage, LogScope) (LOG, LOGSCOPE): Move higher up in the file. (PipeDeviceContext::DeviceTag): New field. (PipeDeviceContext::TotalWritten, PipeDeviceContext::TotalRead) [DEBUG_MODE]: New fields. (PipeDeviceContext::~PipeDeviceContext): Free DeviceTag. (PipeDeviceContext::writeBytes(const void*, DWORD)): Change signature to ... (PipeDeviceContext::writeBytes(const BYTE*, DWORD)): ... this. Correct buffer wrapping. Add written bytes to TotalWritten. (PipeDeviceContext::readBytes(void*, DWORD)): Change signature to ... (PipeDeviceContext::readBytes(BYTE*, DWORD)): ... this. Correct buffer wrapping. Add read bytes to TotalRead. (LogThread) [DEBUG_MODE]: New function. (Init) [DEBUG_MODE]: Create a LogThread thread. Also set the AbortEvent event when OpenCount is 0. (Read(PipeOpenContext*, LPVOID, DWORD)): Change signature to ... (Read(PipeOpenContext*, BYTE*, DWORD)): ... this. Swap order of the wait events in the wait event array, so AbortEvent has priority. (Write(PipeOpenContext*, LPCVOID, DWORD)): Change signature to ... (Write(PipeOpenContext*, const BYTE*, DWORD)): ... this. Swap order of the wait events in the wait event array, so AbortEvent has priority. (IOControl): On PIPE_IOCTL_SET_PIPE_TAG ioctl, record the debug DeviceTag. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-27 23:55:01 UTC (rev 1012) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:29:06 UTC (rev 1013) @@ -1,5 +1,33 @@ 2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (LogMessage2, LogMessage, LogScope) + (LOG, LOGSCOPE): Move higher up in the file. + (PipeDeviceContext::DeviceTag): New field. + (PipeDeviceContext::TotalWritten, PipeDeviceContext::TotalRead) + [DEBUG_MODE]: New fields. + (PipeDeviceContext::~PipeDeviceContext): Free DeviceTag. + (PipeDeviceContext::writeBytes(const void*, DWORD)): Change signature + to ... + (PipeDeviceContext::writeBytes(const BYTE*, DWORD)): ... this. + Correct buffer wrapping. Add written bytes to TotalWritten. + (PipeDeviceContext::readBytes(void*, DWORD)): Change signature + to ... + (PipeDeviceContext::readBytes(BYTE*, DWORD)): ... this. + Correct buffer wrapping. Add read bytes to TotalRead. + (LogThread) [DEBUG_MODE]: New function. + (Init) [DEBUG_MODE]: Create a LogThread thread. Also set the + AbortEvent event when OpenCount is 0. + (Read(PipeOpenContext*, LPVOID, DWORD)): Change signature to ... + (Read(PipeOpenContext*, BYTE*, DWORD)): ... this. Swap order of the + wait events in the wait event array, so AbortEvent has priority. + (Write(PipeOpenContext*, LPCVOID, DWORD)): Change signature to ... + (Write(PipeOpenContext*, const BYTE*, DWORD)): ... this. Swap order + of the wait events in the wait event array, so AbortEvent has priority. + (IOControl): On PIPE_IOCTL_SET_PIPE_TAG ioctl, record the debug + DeviceTag. + +2007-06-28 Pedro Alves <ped...@po...> + * PipeLib/PipeLib.h (SetPipeTag): Declare. * PipeLib/PipeLib.cpp (SetPipeTag): Define. * PipeDev/PipeDevice.h (PIPE_IOCTL_SET_PIPE_TAG): Define. Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-27 23:55:01 UTC (rev 1012) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:29:06 UTC (rev 1013) @@ -64,6 +64,58 @@ # define G(CS) (CS) #endif +#ifdef DEBUG_MODE +static void +LogMessage2 (const char* msg) +{ + FILE* log = fopen ("pipelog.txt", "a+"); + fprintf (log, "%s", msg); + fclose (log); +} + +static void +LogMessage (const char *file, int line, const char* msg, ...) +{ + va_list ap; + char buf[1024]; + char *b = buf; + va_start (ap, msg); + sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); + b += strlen (b); + vsprintf (b, msg, ap); + va_end (ap); + + LogMessage2 (buf); +} + +struct LogScope +{ + explicit LogScope (const char *func, const char* msg) + : func_(func) + , msg_(msg) + { + char buf[512]; + sprintf (buf, "> %s", msg_); + LogMessage (func_, -1, buf); + } + ~LogScope () + { + char buf[512]; + sprintf (buf, "< %s", msg_); + LogMessage (func_, -1, buf); + } + + const char* func_; + const char* msg_; +}; + +# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) +# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) +#else +# define LOG(MSG, ...) do; while (0) +# define LOGSCOPE(MSG) do; while (0) +#endif + class CSWrapper { public: @@ -251,7 +303,12 @@ : OpenCount(0) , WROpenCount(0) , DeviceName(NULL) + , DeviceTag(NULL) , Aborting(FALSE) +#ifdef DEBUG_MODE + , TotalWritten(0) + , TotalRead(0) +#endif , head(0) , count(0) { @@ -267,6 +324,8 @@ { if (DeviceName) free (DeviceName); + if (DeviceTag) + free (DeviceTag); if (ActivePath) free (ActivePath); CloseHandle (ReadEvent); @@ -294,29 +353,31 @@ cs.Unlock (); } - DWORD writeBytes (const void* data_, DWORD dsize) + DWORD writeBytes (const BYTE* data, DWORD dsize) { DWORD fit = sizeof (buffer) - size (); fit = min (dsize, fit); - const BYTE* data = (const BYTE*)data_; - BYTE* b = buffer + tail (); + DWORD t = tail (); for (DWORD i = 0; i < fit; i++) - b[i & (sizeof (buffer) - 1)] = data[i]; + buffer[(t + i) & (sizeof (buffer) - 1)] = data[i]; count += fit; +#ifdef DEBUG_MODE + TotalWritten += fit; +#endif return fit; } - DWORD readBytes (void* buf_, DWORD bsize) + DWORD readBytes (BYTE* buf, DWORD bsize) { - BYTE* buf = (BYTE*)buf_; DWORD fit = min (bsize, size ()); - - const BYTE* h = buffer + head; for (DWORD i = 0; i < fit; i++) - buf[i] = h[i & (sizeof (buffer) - 1)]; + buf[i] = buffer[(head + i) & (sizeof (buffer) - 1)]; count -= fit; head += fit; head &= (sizeof (buffer) - 1); +#ifdef DEBUG_MODE + TotalRead += fit; +#endif return fit; } @@ -331,8 +392,14 @@ HANDLE AbortEvent; WCHAR* DeviceName; + WCHAR* DeviceTag; BOOL Aborting; +#ifdef DEBUG_MODE + DWORD TotalWritten; + DWORD TotalRead; +#endif + private: BYTE buffer[0x1000]; DWORD head; @@ -377,58 +444,6 @@ return TRUE; } -#ifdef DEBUG_MODE -static void -LogMessage2 (const char* msg) -{ - FILE* log = fopen ("pipelog.txt", "a+"); - fprintf (log, "%s", msg); - fclose (log); -} - -static void -LogMessage (const char *file, int line, const char* msg, ...) -{ - va_list ap; - char buf[1024]; - char *b = buf; - va_start (ap, msg); - sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); - b += strlen (b); - vsprintf (b, msg, ap); - va_end (ap); - - LogMessage2 (buf); -} - -struct LogScope -{ - explicit LogScope (const char *func, const char* msg) - : func_(func) - , msg_(msg) - { - char buf[512]; - sprintf (buf, "> %s", msg_); - LogMessage (func_, -1, buf); - } - ~LogScope () - { - char buf[512]; - sprintf (buf, "< %s", msg_); - LogMessage (func_, -1, buf); - } - - const char* func_; - const char* msg_; -}; - -# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) -# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) -#else -# define LOG(MSG, ...) do; while (0) -# define LOGSCOPE(MSG) do; while (0) -#endif - /* This is needed for MSVC, but it makes no harm in gcc. */ struct ltwstr { @@ -469,6 +484,41 @@ return hDev; } +#ifdef DEBUG_MODE + +static DWORD WINAPI +LogThread (void *arg) +{ + PipeDeviceContext* dev = (PipeDeviceContext*)arg; + + int count = 0; + + while (1) + switch (WaitForSingleObject (dev->AbortEvent, 1000)) + { + case WAIT_TIMEOUT: + { + PipeDeviceContext::LockGuard guard G(*dev); + LOG ("(%08d)\t" + "%ls\t" + "buffer size = %lu\t" + "read = %lu\t" + "write = %lu\n", + count++, + dev->DeviceTag ?: L"(notag)", + dev->size (), + dev->TotalRead, + dev->TotalWritten); + } + break; + default: + return 0; + } + + return 0; +} +#endif + PIPEDEV_API DWORD Init (LPCTSTR pContext) { @@ -489,6 +539,10 @@ if (pDeviceContext == NULL) return 0; +#ifdef DEBUG_MODE + CloseHandle (CreateThread (NULL, 0, LogThread, (void*)pDeviceContext, 0, NULL)); +#endif + open_pipes.insert (pContext); return (DWORD)pDeviceContext; @@ -506,9 +560,13 @@ the driver. */ #ifdef DEBUG_MODE - LOG ("oc %lu, wc: %lu, close_calls: %d\n", - dev->OpenCount, - dev->WROpenCount, close_calls); + if (pDeviceContext) + LOG ("oc %lu, wc: %lu, close_calls: %d\n", + pDeviceContext->OpenCount, + pDeviceContext->WROpenCount, + close_calls); + else + LOG ("close_calls: %d\n", close_calls); #endif if (pDeviceContext == NULL) @@ -611,16 +669,13 @@ return FALSE; dev->OpenCount--; - if (pOpenContext->dwAccessCode & GENERIC_WRITE) - { - dev->WROpenCount--; - if (dev->WROpenCount == 0) - /* Wake up the reading side so it can see - the broken pipe. */ - SetEvent (dev->AbortEvent); - } + dev->WROpenCount--; + if (dev->WROpenCount == 0 || dev->OpenCount == 0) + /* Wake up the other side so it can see the broken pipe. */ + SetEvent (dev->AbortEvent); + delete pOpenContext; LOG ("oc %lu, wc: %lu\n", @@ -628,9 +683,13 @@ if (dev->OpenCount == 0) { - /* Deactivating the device here seems to - corrupt the Device.exe, and sometimes hangs - the device. Do it in an auxilary thread. */ + /* Deactivating the device here seems to corrupt Device.exe, and + sometimes hangs the device. Do it in an auxilary thread. */ + /* Perhaps this should be made safer. If anotherthread was just + waken up due to the SetEvent above, this will be a race. + Perhaps we need a wait counter per device and have the + deactivator thread wait for it to reach 0 ... Irks, this is + getting fishy. */ DeactivatePipeDevice (dev); } @@ -638,18 +697,17 @@ } PIPEDEV_API DWORD -Read (PipeOpenContext* pOpenContext, LPVOID pBuffer_, DWORD dwCount) +Read (PipeOpenContext* pOpenContext, BYTE* pBuffer, DWORD dwCount) { LOGSCOPE ("\n"); - if (IsBadReadPtr (pBuffer_, dwCount)) + if (IsBadReadPtr (pBuffer, dwCount)) { SetLastError (ERROR_INVALID_PARAMETER); LOG ("\n"); return -1; } - BYTE* pBuffer = (BYTE*)pBuffer_; DWORD needed = dwCount; if (pOpenContext == NULL @@ -666,11 +724,13 @@ do { + LOG ("new iteration\n"); + { PipeDeviceContext::LockGuard guard G(*dev); - Events[0] = dev->WriteEvent; - Events[1] = dev->AbortEvent; + Events[0] = dev->AbortEvent; + Events[1] = dev->WriteEvent; /* Read before checking for broken pipe, so we get a chance to return valid data when that @@ -711,12 +771,15 @@ break; } + LOG ("going to wait for data\n"); + /* The buffer was empty, wait for data. */ switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) { - case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: /* Data was written to the pipe. Do one more iteration to fetch what we can and bail out. */ + LOG ("write event detected\n"); breaknext = TRUE; break; default: @@ -733,18 +796,17 @@ } PIPEDEV_API DWORD -Write (PipeOpenContext* pOpenContext, LPCVOID pBuffer_, DWORD dwCount) +Write (PipeOpenContext* pOpenContext, const BYTE* pBuffer, DWORD dwCount) { LOGSCOPE ("\n"); - if (IsBadWritePtr ((void*) pBuffer_, dwCount)) + if (IsBadWritePtr ((void*) pBuffer, dwCount)) { SetLastError (ERROR_INVALID_PARAMETER); LOG ("\n"); return -1; } - const BYTE* pBuffer = (const BYTE*)pBuffer_; DWORD needed = dwCount; LOG ("oc %lu, wc: %lu\n", @@ -765,13 +827,15 @@ do { + LOG ("new iteration\n"); + { PipeDeviceContext::LockGuard guard G(*dev); LOG ("lock acquired\n"); - Events[0] = dev->ReadEvent; - Events[1] = dev->AbortEvent; + Events[0] = dev->AbortEvent; + Events[1] = dev->ReadEvent; if (dev->Aborting) { @@ -803,6 +867,8 @@ pBuffer += wrote; dwCount -= wrote; + LOG ("written %lu\n", wrote); + /* According to MSDN, a write of 0, also wakes the reading end of the pipe. */ PulseEvent (dev->WriteEvent); @@ -814,9 +880,11 @@ break; } + LOG ("going to wait for event\n"); switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) { - case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + LOG ("got read event\n"); breaknext = TRUE; break; default: @@ -828,7 +896,7 @@ } while (dwCount); - LOG ("%u\n", needed - dwCount); + LOG ("returning %u\n", needed - dwCount); return needed - dwCount; } @@ -883,6 +951,12 @@ switch (dwCode) { + case PIPE_IOCTL_SET_PIPE_TAG: + if (dev->DeviceTag) + free (dev->DeviceTag); + dev->DeviceTag = wcsdup ((WCHAR*)pBufIn); + bRet = TRUE; + break; case PIPE_IOCTL_SET_PIPE_NAME: if (dev->DeviceName) free (dev->DeviceName); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-27 23:55:02
|
Revision: 1012 http://svn.sourceforge.net/cegcc/?rev=1012&view=rev Author: pedroalves Date: 2007-06-27 16:55:01 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.h (PIPE_IOCTL_SET_PIPE_TAG): Define. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-27 23:52:52 UTC (rev 1011) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-27 23:55:01 UTC (rev 1012) @@ -2,6 +2,7 @@ * PipeLib/PipeLib.h (SetPipeTag): Declare. * PipeLib/PipeLib.cpp (SetPipeTag): Define. + * PipeDev/PipeDevice.h (PIPE_IOCTL_SET_PIPE_TAG): Define. 2007-06-24 Pedro Alves <ped...@po...> Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-27 23:52:52 UTC (rev 1011) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-27 23:55:01 UTC (rev 1012) @@ -36,6 +36,9 @@ #define PIPE_IOCTL_GET_PIPE_NAME \ CTL_CODE(FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define PIPE_IOCTL_SET_PIPE_TAG \ + CTL_CODE(FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS) + #define DEVICE_DLL_NAME L"PipeDev.dll" #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-27 23:52:53
|
Revision: 1011 http://svn.sourceforge.net/cegcc/?rev=1011&view=rev Author: pedroalves Date: 2007-06-27 16:52:52 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeLib/PipeLib.h (SetPipeTag): Declare. * PipeLib/PipeLib.cpp (SetPipeTag): Define. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-26 00:32:57 UTC (rev 1010) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-27 23:52:52 UTC (rev 1011) @@ -1,3 +1,8 @@ +2007-06-28 Pedro Alves <ped...@po...> + + * PipeLib/PipeLib.h (SetPipeTag): Declare. + * PipeLib/PipeLib.cpp (SetPipeTag): Define. + 2007-06-24 Pedro Alves <ped...@po...> * conformtest.c: New file. Modified: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-26 00:32:57 UTC (rev 1010) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-27 23:52:52 UTC (rev 1011) @@ -92,6 +92,17 @@ RegCloseKey (hk); } +/* Undocumented, for pipedev.dll debugging purposes only. */ +extern "C" BOOL +SetPipeTag (HANDLE p, const WCHAR* name) +{ + if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_TAG, + (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), + NULL, 0, NULL, NULL)) + return FALSE; + return TRUE; +} + static BOOL SetPipeName (HANDLE p, WCHAR* name) { Modified: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-26 00:32:57 UTC (rev 1010) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-27 23:52:52 UTC (rev 1011) @@ -35,6 +35,9 @@ BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); BOOL GetPipeName (HANDLE, WCHAR*); +/* Internal, for pipedev.dll debugging purposes. */ +BOOL SetPipeTag (HANDLE, const WCHAR*); + #ifdef __cplusplus } #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-26 00:35:06
|
Revision: 1010 http://svn.sourceforge.net/cegcc/?rev=1010&view=rev Author: pedroalves Date: 2007-06-25 17:32:57 -0700 (Mon, 25 Jun 2007) Log Message: ----------- * Makefile (all): Depend on $(BINS) not $(TARGETS). Modified Paths: -------------- trunk/cegcc/tools/rshd/ChangeLog trunk/cegcc/tools/rshd/Makefile Modified: trunk/cegcc/tools/rshd/ChangeLog =================================================================== --- trunk/cegcc/tools/rshd/ChangeLog 2007-06-25 01:32:17 UTC (rev 1009) +++ trunk/cegcc/tools/rshd/ChangeLog 2007-06-26 00:32:57 UTC (rev 1010) @@ -1,7 +1,11 @@ +2007-06-26 Pedro Alves <ped...@po...> + + * Makefile (all): Depend on $(BINS) not $(TARGETS). + 2007-06-25 Pedro Alves <ped...@po...> * rshd.c (handle_connection): Remove out of sync comment. - + 2007-06-25 Pedro Alves <ped...@po...> * rshd.c (GetStdioPathW, SetStdioPathW): Declare. @@ -62,3 +66,10 @@ * COPYING, README, TODO, ChangeLog, Makefile, rshd.c, tester.c: New files. + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: Modified: trunk/cegcc/tools/rshd/Makefile =================================================================== --- trunk/cegcc/tools/rshd/Makefile 2007-06-25 01:32:17 UTC (rev 1009) +++ trunk/cegcc/tools/rshd/Makefile 2007-06-26 00:32:57 UTC (rev 1010) @@ -27,7 +27,7 @@ BINDIST_FILES=\ rshd.exe -all: $(TARGETS) +all: $(BINS) rshd_unstripped.exe: rshd.c Makefile $(CC) -o $@ $< $(ALLFLAGS) $(LDFLAGS) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-25 01:32:19
|
Revision: 1009 http://svn.sourceforge.net/cegcc/?rev=1009&view=rev Author: pedroalves Date: 2007-06-24 18:32:17 -0700 (Sun, 24 Jun 2007) Log Message: ----------- * FindFileA.c: Add a notice on file origin. Convert C++ comments into C comments. Modified Paths: -------------- trunk/cegcc/tools/rcp/ChangeLog trunk/cegcc/tools/rcp/FindFileA.c Modified: trunk/cegcc/tools/rcp/ChangeLog =================================================================== --- trunk/cegcc/tools/rcp/ChangeLog 2007-06-25 01:15:40 UTC (rev 1008) +++ trunk/cegcc/tools/rcp/ChangeLog 2007-06-25 01:32:17 UTC (rev 1009) @@ -1,5 +1,10 @@ 2007-06-25 Pedro Alves <ped...@po...> + * FindFileA.c: Add a notice on file origin. Convert C++ comments + into C comments. + +2007-06-25 Pedro Alves <ped...@po...> + Initial import. * LICENSE, README, TODO, ChangeLog, Makefile, rcp.c, FindFileA.c, Modified: trunk/cegcc/tools/rcp/FindFileA.c =================================================================== --- trunk/cegcc/tools/rcp/FindFileA.c 2007-06-25 01:15:40 UTC (rev 1008) +++ trunk/cegcc/tools/rcp/FindFileA.c 2007-06-25 01:32:17 UTC (rev 1009) @@ -1,6 +1,5 @@ -// findfile.c -// -// Time-stamp: <12/02/01 14:42:40 keuchel@keuchelnt> +/* Simple Ansi->Wide wrappers based on code original from + Rainer Keuchel's celib, which migrated into cegcc.dll. */ #include <wchar.h> @@ -39,7 +38,7 @@ COUNTOF (lpfd->cFileName), NULL, NULL); - // not in wince... + /* Not in wince... */ lpfd->cAlternateFileName[0] = 0; } @@ -52,7 +51,8 @@ WIN32_FIND_DATAW fdw; BOOL res; - // is this needed? + /* Is this needed? + Shouldn't be, as lpfd could contain garbage... */ fdw.dwFileAttributes = lpfd->dwFileAttributes; fdw.ftCreationTime = lpfd->ftCreationTime; fdw.ftLastAccessTime = lpfd->ftLastAccessTime; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-25 01:15:45
|
Revision: 1008 http://svn.sourceforge.net/cegcc/?rev=1008&view=rev Author: pedroalves Date: 2007-06-24 18:15:40 -0700 (Sun, 24 Jun 2007) Log Message: ----------- Initial import. * LICENSE, README, TODO, ChangeLog, Makefile, rcp.c, FindFileA.c, Readme_org.txt: New files. Added Paths: ----------- trunk/cegcc/tools/rcp/ trunk/cegcc/tools/rcp/ChangeLog trunk/cegcc/tools/rcp/FindFileA.c trunk/cegcc/tools/rcp/LICENSE trunk/cegcc/tools/rcp/Makefile trunk/cegcc/tools/rcp/README trunk/cegcc/tools/rcp/Readme_org.txt trunk/cegcc/tools/rcp/TODO trunk/cegcc/tools/rcp/rcp.c Added: trunk/cegcc/tools/rcp/ChangeLog =================================================================== --- trunk/cegcc/tools/rcp/ChangeLog (rev 0) +++ trunk/cegcc/tools/rcp/ChangeLog 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,14 @@ +2007-06-25 Pedro Alves <ped...@po...> + + Initial import. + + * LICENSE, README, TODO, ChangeLog, Makefile, rcp.c, FindFileA.c, + Readme_org.txt: New files. + + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: Property changes on: trunk/cegcc/tools/rcp/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/FindFileA.c =================================================================== --- trunk/cegcc/tools/rcp/FindFileA.c (rev 0) +++ trunk/cegcc/tools/rcp/FindFileA.c 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,91 @@ +// findfile.c +// +// Time-stamp: <12/02/01 14:42:40 keuchel@keuchelnt> + +#include <wchar.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define COUNTOF(X) (sizeof (X)/sizeof ((X)[0])) + +HANDLE WINAPI +FindFirstFileA (const char *lpName, LPWIN32_FIND_DATAA lpfd) +{ + HANDLE hFind; + WIN32_FIND_DATAW fdw; + wchar_t lpNameNew[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, lpName, -1, lpNameNew, COUNTOF (lpNameNew)); + + hFind = FindFirstFileW (lpNameNew, &fdw); + + if(hFind != INVALID_HANDLE_VALUE) + { + lpfd->dwFileAttributes = fdw.dwFileAttributes; + lpfd->ftCreationTime = fdw.ftCreationTime; + lpfd->ftLastAccessTime = fdw.ftLastAccessTime; + lpfd->ftLastWriteTime = fdw.ftLastWriteTime; + lpfd->nFileSizeHigh = fdw.nFileSizeHigh; + lpfd->nFileSizeLow = fdw.nFileSizeLow; + +#ifdef __COREDLL__ + lpfd->dwReserved0 = fdw.dwOID; +#endif + + WideCharToMultiByte (CP_ACP, 0, + fdw.cFileName, -1, + lpfd->cFileName, + COUNTOF (lpfd->cFileName), + NULL, NULL); + + // not in wince... + lpfd->cAlternateFileName[0] = 0; + } + + return hFind; +} + +BOOL WINAPI +FindNextFileA (HANDLE hFind, LPWIN32_FIND_DATAA lpfd) +{ + WIN32_FIND_DATAW fdw; + BOOL res; + + // is this needed? + fdw.dwFileAttributes = lpfd->dwFileAttributes; + fdw.ftCreationTime = lpfd->ftCreationTime; + fdw.ftLastAccessTime = lpfd->ftLastAccessTime; + fdw.ftLastWriteTime = lpfd->ftLastWriteTime; + fdw.nFileSizeHigh = lpfd->nFileSizeHigh; + fdw.nFileSizeLow = lpfd->nFileSizeLow; +#ifdef __COREDLL__ + fdw.dwOID = lpfd->dwReserved0; +#endif + + res = FindNextFileW(hFind, &fdw); + + if(res == TRUE) + { + lpfd->dwFileAttributes = fdw.dwFileAttributes; + lpfd->ftCreationTime = fdw.ftCreationTime; + lpfd->ftLastAccessTime = fdw.ftLastAccessTime; + lpfd->ftLastWriteTime = fdw.ftLastWriteTime; + lpfd->nFileSizeHigh = fdw.nFileSizeHigh; + lpfd->nFileSizeLow = fdw.nFileSizeLow; + +#ifdef __COREDLL__ + lpfd->dwReserved0 = fdw.dwOID; +#endif + + WideCharToMultiByte(CP_ACP, 0, + fdw.cFileName, -1, + lpfd->cFileName, + COUNTOF(lpfd->cFileName), + NULL, NULL); + + lpfd->cAlternateFileName[0] = 0; + } + + return res; +} Property changes on: trunk/cegcc/tools/rcp/FindFileA.c ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/LICENSE =================================================================== --- trunk/cegcc/tools/rcp/LICENSE (rev 0) +++ trunk/cegcc/tools/rcp/LICENSE 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,27 @@ +This tool was written based on the rcp extension to +"rshd - Remote Shell Daemon for Windows NT version 1.6" written by +Silviu C. Marghescu (http://www.cs.umd.edu/~silviu). The rcp +extension was written by Gary Doss (gd...@rp...). + +See the Readme_org.txt file for the original copyright notice, and the +original disclaimer. + +The changes made to the original files are also covered by the +following conditions: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ Added: trunk/cegcc/tools/rcp/Makefile =================================================================== --- trunk/cegcc/tools/rcp/Makefile (rev 0) +++ trunk/cegcc/tools/rcp/Makefile 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,74 @@ +TARGET=arm-wince-mingw32ce +CFLAGS=-O0 -g3 +WARNFLAGS=-Wall -Wextra + +INCLUDES=-I../errno -I../libcwd +LDFLAGS=-L../errno -L../libcwd +LIBS=-lcwd -lerrno + +ALLFLAGS=$(CFLAGS) $(INCLUDES) $(WARNFLAGS) + +CC=$(TARGET)-gcc +STRIP=$(TARGET)-strip + +BINS = rcp_unstripped.exe +STRIPPED_BINS = rcp.exe + +TARGETS = $(STRIPPED_BINS) + +srcdir=. +distdir=rcp-0.1.0 +TAR = tar +TARFLAGS = z +TARFILEEXT = .tar.gz + +SRCDIST_FILES=\ + rcp.c Makefile README TODO COPYING ChangeLog + +BINDIST_FILES=\ + rcp.exe + +OBJECTS=rcp.o FindFileA.o + +all: $(TARGETS) +bins: $(BINS) + +.c.o: + $(CC) -o $@ $< -c $(ALLFLAGS) + +rcp_unstripped.exe: $(OBJECTS) Makefile + $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(ALLFLAGS) $(LIBS) + +rcp.exe: rcp_unstripped.exe + $(STRIP) $< -o $@ + +download: rcp.exe + pcp rcp.exe ":/rcp.exe" + +clean: + rm -f $(BINS) $(STRIPPED_BINS) $(OBJECTS) + +dist: srcdist bindist + +srcdist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(SRCDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-src$(TARFILEEXT) $(distdir) + +bindist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(BINDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-bin$(TARFILEEXT) $(distdir) + + +.PHONY: all install download clean dist bindist srcdist Property changes on: trunk/cegcc/tools/rcp/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/README =================================================================== --- trunk/cegcc/tools/rcp/README (rev 0) +++ trunk/cegcc/tools/rcp/README 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,26 @@ + README for rcp for Windows CE + +This directory contains rcp for Windows CE. + +This tool was written based on the rcp extension to +"rshd - Remote Shell Daemon for Windows NT version 1.6" written by +Silviu C. Marghescu (http://www.cs.umd.edu/~silviu). The rcp +extension was written by Gary Doss (gd...@rp...). + +The rcp part was totally separated from Silviu's rshd, and converted +to read/write from/to stdin/stdout. It is supposed to be invoked from +rshd for WinCE with stdin/stdout/stderr redirected, much like a unix +version of rcp would do. + +To build make sure you have the mingw32ce toolchain on your path, and +type make. + +Have fun! + +Pedro Alves + +-- + +REPORTING BUGS: +ce...@so... +pe...@po... Property changes on: trunk/cegcc/tools/rcp/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/Readme_org.txt =================================================================== --- trunk/cegcc/tools/rcp/Readme_org.txt (rev 0) +++ trunk/cegcc/tools/rcp/Readme_org.txt 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,241 @@ +rshd - Remote Shell Daemon for Windows NT version 1.6 + +Written by Silviu C. Marghescu (http://www.cs.umd.edu/~silviu) +Copyright (C) 1996 Silviu C. Marghescu, Emaginet, Inc. +All Rights Reserved. + +Password functionality added by Ashley M. Hopkins (http://www.csee.usf.edu/~amhopki2) + +rshd is free software; you can redistribute it in its entirety +in any form you like. If you find any bugs, feel free to send me an +email at si...@em.... If you have added new features to rshd, +please send me all the source code modifications, including the version +of rshd that you are based on. Your additions may benefit other users. + + +Disclaimer +========== + +rshd is distributed hoping that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. + +Good data processing procedure dictates that any program be +thoroughly tested with non-critical data before relying on it. +The user must assume the entire risk of using the program. +THE AUTHOR SHALL NOT BE HELD LIABLE FOR ANY KIND OF DAMAGES OR CLAIMS THAT +DIRECTLY OR INDIRECTLY RESULT FROM USING THIS SOFTWARE. + + +Description +=========== + +rshd is a multithreaded daemon service that listens for connections on port +514 (tcp port for the shell/cmd protocol), runs commands passed by clients and sends +back the results. It was my experience that the rshd service included in the +Windows NT Resource Kit does not fully follow the BSD specification for the rsh protocol; +it works fine with the rsh client in NT, but other clients fail to connect. +This implementation of rshd tries to get as close as possible to the BSD specs +(http://www.bsdi.com). + +As of version 1.5, rshd comes with RCP server support, thanks to Gary Doss +(gd...@rp...); any problem/question concerning the rcp +part of rshd would be better answered by him. + +Important note: rshd was designed and implemented to be convenient and reliable, +rather than tightly secure. A client trying to connect to rshd will have to pass +a security clearance process, but rshd is probably far from a secure service. +If security is of major concern across your network, you should be very careful +when using this service. My target for rshd was a closed network, or a network +guarded by a firewall. + + +Requirements +============ + +o An Intel processor based machine running Microsoft Windows NT and TCP/IP. +o Window Socket DLL installed properly (version 1.1 or higher). + + +Installation +============ + +This package contains the following files: + readme.txt - this file + rshd.exe - the rshd daemon executable +The source distribution also contains: + rshd.cpp - the C++ source file (actually mostly C, but I prefer to define + variables when I really need them; plus, I like the // comments) + rshd_rcp.cpp - the C++ source file for the RCP service + service.cpp, service.h - the service routines (many thanks to Craig Link, + Microsoft for including the Service project in the samples) + rshd.ide - the project file for Borland C++ 5.0 users + rshd.mak - the project file for Microsoft Visual C++ 2.0 + + +Running rshd +============ + +In this new version, rshd runs as a service. You also have the option of running rshd +as a command line application (see "-d" later on). In order to get the service up and +running, you will have to complete the following steps: +1. install the service: + rhsd -install +2. start the service: + net start rshd +That's it! Stopping the service is as easy as starting it: + net stop rshd +Should you decide rshd is not the way to go: + rshd -remove +Starting/stopping the service can also be done through the "Services" Control Panel +applet; just look for the RSHD Daemon service. + +Note that if the applications you are running require user credentials, you should +run the service under the corresponding user account. + +Command line options: +-install installs the rshd service +-remove removes the rshd service + +The following command line options have been inherited from the previous, interactive +versions. I don't know if they'll be useful if you decide to run rshd as a service. +I haven't figured out yet how to run the service with command line options, therefore +the '-r' is set by default. + +-d enables debugging messages and allows you to run rshd as a command line process. Good + for those days when nothing works... +-1 no stdout redirection. By default, rshd will redirect the output of your + command into a temporary file and send the result back thru the client + socket. If however you are not interested in the output, or the command + is already redirected, this option will prevent stdout redirection. + Note that the option is global, meaning it will disable redirection + regardless of the commands you're passing... +-2 no stderr redirection. Same as '-1', but for stderr. At this point it + should be noted that under the BSD rshd specification, the client can pass + an auxillary tcp port number that the daemon can use to send the stderr + output back. The rshd will connect to that port if provided and send + back the stderr, unless this option is given. If no alternative stderr port + is provided, rshd will use the main socket for both stdout and stderr. +-4 4DOS command shell. Different shells and different operating systems have + different ways of redirecting output, especially for the standard error stream. + rshd was tested in the following configurations: CMD.EXE and 4NT.EXE on + Windows NT; COMMAND.COM and 4DOS.COM on Windows 95. If you're running 4DOS + on Windows 95, make sure you set the '-4' command parameter, otherwise the + stderr redirection will fail. +-s stronger security enabled. By default, when the client credentials can't + be checked, rshd assumes it to be friendly and runs the command. If that + creates security concernes, this option will accept the connection to a client + only if everything checks out. +-r no .rhosts checking. Per BSD rshd specification, rshd loads the + <windir>\.rhosts file and builds a list of trusted hosts. + Any further connections will be accepted only from a host in the + list. '-r' disables this checking. Note that this is a major security + issue: if your network is not closed or guarded by a firewall, anybody + can connect thru the rsh protocol and run commands on your machines. + Use this option only if you know exactly who is running what across your + network! +-p password option enabled. User will be prompted to enter a password after start of + the daemon. To enable rsh commands to execute on the daemon with this enabled user + must enter password from the command line in the rsh command between the hostname and the command. (rsh hostname password command) + The password option does not affect the rcp command. +-v displays the rshd version. +-h help screen. + +RCP usage: + Valid rcp requests are in the form: + rcp -t [-d] [-r] [-p] target + rcp -f [r] [-p] target + NOTE: The -p option is being ignored since there is not a good + correlation between UNIX and NT when it comes to file + permissions and ownership. + +I have tested rshd with the following rsh clients: WinRSH (both 16 and 32 bit +versions; this was the client I needed to use and didn't work with the Resource +Kit implementation of rshd); NT client of rsh; SunOS client of rsh. The main +difference between WinRSH and the other rsh clients is that WinRSH does not open +a stderr additional port; rshd will send both the stdout and stderr output thru +the main socket. + + +Security considerations +======================= + +As stated above, security was not the main issue while implementing rshd. The +daemon still tries to authenticate the remote user/host, but the authentication +process is not fully implemented and should not be considered secure. +In this version, only host authentication is implemented. If not disabled (see +the '-r' switch), an .rhosts mechanism is used: the remote host name is searched +in the .rhosts file; if it is not found, the connection is refused. +Sometimes, rshd does not have enough information to decide whether the connection +is secure or not (e.g. cannot determine the remote host name); in this cases, by +default, the connection is accepted, unless the '-s' switch is on. The '-s' switch +will enable a tighter security: only fully recognized clients will be able to connect. + +The password functionality added by Ashley M. Hopkins enables another layer of security by requiring that the user enter a password. This option can be used in conjunction with the .rhosts file or with the .rhosts checking disabled (-r). + +To allow compatibility across NT/95 platforms, the required path for the .rhosts file +(if you decide to use the feature) is: <windir>\.rhosts, where <windir> is your +Windows root directory as reported by the WINDIR environment variable. + + +Rebuilding rshd +=============== + +You probably have the sources already... I've built rshd with both Visual C++ +and Borland C++; the .ide file is the Borland project and the .mak is the one +you need for Visual C++. Make sure you define the appropriate macro (first lines +in rshd.cpp define either VISUALCPP or BORLANDCPP). + + +Known problems +============== + +Some rsh clients open an additional connection for the stderr output. There is a +known problem/feature in Microsoft's implementation of TCP/IP that causes closed +connections to linger on for 2 maximum segment lives (4 minutes). Within the timeout +period, the local port is unusable. For this reason, rshd has a mechanism for port +resolution that tries to assign local ports in a round-robin fashion. +It is not a clean solution, but it works for the time being (there is still a problem +if rshd is restarted, since it begins assigning ports from 1023; if those ports are +taken by TIME_WAIT connections, they'll be unusable). A way of reducing the timeout +period to less than 4 minutes is described in Microsoft's Knowledge Base article Q149532: + +***************************************************************************************** +A new registry has been added to TCP/IP to allow the TIME-WAIT state to be configurable. +This will allow TCP/IP users to free closed connection resources more quickly. + +The new registry entry is: + + TcpTimedWaitDelay + Key: Tcpip\Parameters + Value Type: REG_DWORD - Time in seconds + Valid Range: 30-300 (decimal) + Default: 0xF0 (240 decimal) +***************************************************************************************** + + +Also, very long command lines (e.g. more than 1024 characters) can cause rshd to +crash. Still working on it. + +For complex commands (e.g. "comm1 | comm2"), to achieve correct redirection, the whole +command needs to be enclosed in parenthesis (e.g. (comm1 | comm2) ). However, that creates +problems on some machines (errors have been reported on Windows 95, running under command.com). +Things go smoothly though if you have 4NT or 4DOS (use the '-4' flag then). + + + +Whether you have good or bad comments, improvements and suggestions, I would like +to hear from you at si...@em.... + + +Bug fixes, improvements +======================= + +Gary Doss (gd...@rp...) has had a major contribution to rshd, +with the RCP support and some pretty good bug fixes. + +Barbara Dawkins (bda...@rp...) has improved Gary's RCP support +and fixed a couple of bugs. + + +Ashley Hopkins (amh...@cs...) has added the password option to the rshd to improve security of this daemon. Additionally a bug has been fixed to allow the transfer of executable files. \ No newline at end of file Property changes on: trunk/cegcc/tools/rcp/Readme_org.txt ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/TODO =================================================================== --- trunk/cegcc/tools/rcp/TODO (rev 0) +++ trunk/cegcc/tools/rcp/TODO 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,5 @@ + +* Rewrite the ParseTarget, NextTarget and CloseTarget function to use + _findfirst, or dirent or something else. + +* Convert rcp_main to use getopt. Property changes on: trunk/cegcc/tools/rcp/TODO ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/rcp/rcp.c =================================================================== --- trunk/cegcc/tools/rcp/rcp.c (rev 0) +++ trunk/cegcc/tools/rcp/rcp.c 2007-06-25 01:15:40 UTC (rev 1008) @@ -0,0 +1,1002 @@ +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* Follows the original Copyright and disclaimer statements of the + original package. */ + +////////////////////////////////////////////////////////////////////////// +// +// rshd_rcp.cpp +// +// This file contains code which will extend rshd to handle rcp +// requests. +// +// Author: Gary L. Doss NCR Corporation +// Date: December 16, 1996 +// +////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////// +// +// rsh daemon for Windows NT/95 +// (c) 1996 Silviu Marghescu - Emaginet, Inc. +// +// +// This program is free software; you can redistribute and/or modify +// it. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +// +// rshd - Remote Shell Daemon for Windows NT/95 +// Author: Silviu C. Marghescu (http://www.cs.umd.edu/~silviu) +// Date: May 16, 1996 +// +////////////////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <io.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> +#include <stdarg.h> + +#include <windows.h> + +#include <cwd.h> + +static FILE * +get_logfile (void) +{ +#if 0 + static FILE* logger = NULL; + + if (logger == NULL) + { + char buf[200]; + sprintf (buf, "rcp-%08x", (unsigned) GetCurrentProcessId ()); + logger = fopen (buf, "a+"); + } + return logger; +#else + return stderr; +#endif +} + +static int debugFlag = 0; + +static void +error (const char *message) +{ + FILE* f = get_logfile (); + fprintf (f, "%s\n", message); + fflush (f); +} + +static void +debug (const char *format, ...) +{ + if (debugFlag) + { + FILE* f = get_logfile (); + va_list ap; + va_start (ap, format); + vfprintf (f, format, ap); + fflush (f); + va_end (ap); + } +} + +/* This is the size of the buffer used with rcp */ +#define RCP_BUFFER_SIZE 8192 +/* This is a delay time in milliseconds to wait after sending an error + condition to the remote hosts during an rcp. */ +#define RCP_ERR_DELAY 1000 + +/* Several of the messages sent in the rcp protocol are single + byte ( 0x00 ) or are text messages terminated by a ('\n'). + This routine reads the message a single byte at a time and + checks for the appropriate termination condition. + BUFF is the buffer to hold the data. + BLEN is the length of the buffer. + returns -1 if recv fails or number of characters received on SUCCESS. */ +static int +RcpReceive (char *buff, int blen) +{ + int i; + int rlen; + char tchar; + + i = 0; + buff[0] = 0; + do + { + rlen = read (fileno (stdin), &buff[i], 1); + if (rlen == -1) + { + error ("Cannot receive client data."); + return rlen; + } + if (debugFlag) + { + if (!rlen) + fprintf (stderr, "...got %d chars. \n", rlen); + else + fprintf (stderr, "...got %d chars. [%c]\n", rlen, buff[i]); + } + tchar = buff[i]; + i++; + if (i > blen) + { + /* The buffer has overflowed. */ + SetLastError (WSAEMSGSIZE); + return -1; + } + } + while (tchar != '\n' && tchar != '\0'); + + return i; +} + +/* ParseTarget is the first step in processing environment + variables and wild card characters that may exists in + the target specification of the rcp command. All + environment variables are expanded and a find is initiated + to handle the wild card characters ( ? and * ). + HFILE is a pointer to a file handle. The file handle is used + by the calling process to obtain more files associated with the target. + TARGET is the target file/directory that needs to be expanded. + BDIR is a flag will be set to TRUE if the TARGET is a directory and + FALSE if it is a file. + Return TRUE if there are possibly more files that match the target + and FALSE if this is the only file that matches. + + The wildcard characters are only valid if used in the last item + in the path specified by Target. + + See Also NextTarget and CloseTarget. */ +static BOOL +ParseTarget (HANDLE * hFile, char *Target, BOOL *bDir) +{ + char strPath[MAX_PATH]; +#if 0 + long lLen; +#endif + WIN32_FIND_DATAA wfdFileData; + BOOL bMoreFiles = FALSE; + char *strLastSlash; + char strDirectory[MAX_PATH]; + struct stat statbuf; + + /* TARGET may contain: + Environment Variables: %name% + Wild Card Characters: ? and * */ +#if 0 + lLen = ExpandEnvironmentStrings (Target, strPath, MAX_PATH); + + if (debugFlag) + fprintf (stderr, "The expanded path is %d chars %d: %s\n", lLen, + GetLastError (), strPath); +#else + strcpy (strPath, Target); +#endif + /* Determine the directory name for the expanded target. */ + strLastSlash = strchr (strPath, '/'); + while (strLastSlash != NULL) + { + *strLastSlash = '\\'; + strLastSlash++; + strLastSlash = strrchr (strLastSlash, '/'); + } + + strLastSlash = strrchr (strPath, '\\'); + if ((strLastSlash == NULL) || (strLastSlash == strPath)) + strDirectory[0] = 0; + else + { + strncpy (strDirectory, strPath, (long) (strLastSlash - strPath)); + strDirectory[(long) (strLastSlash - strPath)] = 0; + strcat (strDirectory, "\\"); + } + + /* If the target has wildcards, process them. */ + if ((strchr (strPath, '?') != NULL) || (strchr (strPath, '*') != NULL)) + { + *hFile = FindFirstFileA (strPath, &wfdFileData); + if (*hFile != INVALID_HANDLE_VALUE) + { + bMoreFiles = TRUE; + if (wfdFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + *bDir = TRUE; + /* Ignore directories "." and ".." */ + while (!(strcmp (wfdFileData.cFileName, ".")) || + !(strcmp (wfdFileData.cFileName, ".."))) + { + if (!FindNextFileA (*hFile, &wfdFileData)) + { + /* Handle error. */ + Target[0] = 0; + *bDir = FALSE; + return FALSE; + } + *bDir = + (wfdFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + ? TRUE : FALSE; + } + } + else + *bDir = FALSE; + + sprintf (Target, "%s%s", strDirectory, wfdFileData.cFileName); + } + else + { + Target[0] = 0; + *bDir = FALSE; + return FALSE; + } + } + else + { + /* Check to see if Target is a file or a directory. */ + strcpy (Target, strPath); + if (stat (Target, &statbuf) != 0) + return FALSE; + else + *bDir = (statbuf.st_mode & S_IFDIR) ? TRUE : FALSE; + } + return bMoreFiles; +} + +/* This function gets the next available target that matches + the specification passed to ParseTarget for the specified + HANDLE. HFILE is a HANDLE returned from call to ParseTarget. + BDIR is a flag that will be set to TRUE if the TARGET is a + directory and to FALSE if it is a regular file. + Returns NULL if no more matches exist, of a pointer to target + name if a match is found. + + Assumptions: + The pointer returned by NextTarget should never be deleted. + NextTarget is always called after ParseTarget. + No target names will be larger than MAX_PATH. + + See Also: ParseTarget, CloseTarget. */ +static char * +NextTarget (HANDLE hFile, BOOL * bDir) +{ + static char Target[MAX_PATH]; + WIN32_FIND_DATAA wfdFileData; + + /* Make sure the handle is not bad. */ + if (hFile == INVALID_HANDLE_VALUE) + { + *bDir = FALSE; + return NULL; + } + + if (FindNextFileA (hFile, &wfdFileData)) + { + /* A match was found. */ + if (wfdFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + *bDir = TRUE; + /* Ignore directories "." and "..". */ + while (!(strcmp (wfdFileData.cFileName, ".")) || + !(strcmp (wfdFileData.cFileName, ".."))) + { + if (!FindNextFileA (hFile, &wfdFileData)) + { + /* Handle error. */ + Target[0] = 0; + *bDir = FALSE; + return NULL; + } + if (wfdFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + *bDir = TRUE; + else + *bDir = FALSE; + } + } + else + *bDir = FALSE; + + sprintf (Target, "%s", wfdFileData.cFileName); + } + else + { + Target[0] = 0; + *bDir = FALSE; + return NULL; + } + return (Target); +} + +/* Terminate the search for target matches that was initiated + in the call to ParseTarget. HFILE is a HANDLE returned from + the call to ParseTarget. + + Assumptions: + CloseTarget must always be used to close the find initiated by + ParseTarget. + There are no more matches to a target when NextTarget returns + NULL. + + See Also: ParseTarget, NextTarget. */ +void +CloseTarget (HANDLE hFile) +{ + if (hFile != INVALID_HANDLE_VALUE) + FindClose (hFile); + return; +} + +/* This functions processes an rcp request to send files to + a remote system. TARGET is the target specified in the rcp + request. BRECURSIVE specified that this request must recurse + the sub-directories of the specfied target. + + Assumptions: + All files sent are read as BINARY files. This prevents + the translation of CR-LF to LF and preserves the size of the file + and the data contained in it. */ +void +RcpSvrSend (const char *Target, BOOL bRecursive) +{ + char buff[RCP_BUFFER_SIZE + 1]; + int blen = RCP_BUFFER_SIZE; + int FileId; + int nFileSize; + int nBytesRead; + int nBytesSent; + int dwBytes; + int nValue; + BOOL bMoreFiles; + HANDLE hFile = INVALID_HANDLE_VALUE; + char expTarget[MAX_PATH]; + char *Target2; + char *FileName; + BOOL bDir; + BOOL bTarget; + BOOL bProcessing; + struct _stat statbuf; + + debug ("sending %s\n", Target); + + /* Copy the target to a buffer we know will hold MAX_PATH. */ + strcpy (expTarget, Target); + /* Check the target for environment variables and wild cards. */ + bMoreFiles = ParseTarget (&hFile, expTarget, &bDir); + bTarget = bDir; + + if (!bRecursive & bDir) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Not a plain file\n", expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + debug ("sending %s\n", expTarget); + + if (access (expTarget, 02) != 0) + { + debug ("error\n"); + /* Error condition */ + buff[0] = 1; + if (errno == ENOENT) + sprintf (&buff[1], "rcp: %s: No such file or directory\n", expTarget); + else + sprintf (&buff[1], "rcp: %s: Permission Denied\n", expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + debug ("waiting for '\\0'\n"); + + /* Receive data from the client expecting 0x00. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + debug ("waiting for '\\0' : done\n"); + + if (buff[0] != 0) + { + error ("Remote system failed."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + bProcessing = TRUE; + Target2 = expTarget; + while (Target2 != NULL) + { + if (bDir) + { + /* Notify remote system to create a directory. */ + FileName = strrchr (Target2, '\\'); + if (FileName == NULL) + FileName = Target2; + else + FileName++; + + sprintf (buff, "D0755 0 %s\n", FileName); + + if (write (fileno (stdout), buff, strlen (buff)) < 1) + { + error ("Error sending directory status."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + chdir (Target2); + RcpSvrSend ("*", bRecursive); + chdir (".."); + } + else + { + FileName = strrchr (Target2, '\\'); + if (FileName == NULL) + FileName = Target2; + else + { + *FileName = 0; + chdir (Target2); + FileName++; + } + /* Open the file for reading. */ + FileId = _open (FileName, O_RDONLY | O_BINARY, S_IWRITE); + if (FileId == -1) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Cannot open file\n", FileName); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + else + { + /* Notify remote system to create a file. */ + nValue = _fstat (FileId, &statbuf); + nFileSize = statbuf.st_size; + sprintf (buff, "C0644 %d %s\n", nFileSize, FileName); + if (write (fileno (stdout), buff, strlen (buff)) < 1) + { + error ("Error sending result status."); + close (FileId); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + /* Receive data from the client expecting 0x00. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + close (FileId); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + if (buff[0] != 0) + { + error ("Remote system Failed."); + close (FileId); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + /* Process the contents of the file. */ + nBytesSent = 0; + while (nBytesSent < nFileSize) + { + /* Read the file. */ + nBytesRead = read (FileId, buff, blen); + if (nBytesRead <= 0) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Cannot read source\n", + FileName); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) + < 1) + error ("Error sending result status."); + close (FileId); + Sleep (RCP_ERR_DELAY); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + nBytesSent += nBytesRead; + if (write (fileno (stdout), buff, nBytesRead) < 1) + { + error ("Error sending file."); + close (FileId); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + } + + close (FileId); + + buff[0] = 0; + if (write (fileno (stdout), buff, 1) < 1) + { + error ("Error sending file termination."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + } + + /* Receive data from the client expecting 0x00. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + if (buff[0] != 0) + { + error ("Remote system failed."); + if (bMoreFiles) + CloseTarget (hFile); + return; + } + + } + + Target2 = NextTarget (hFile, &bDir); + if (Target2 == NULL) + CloseTarget (hFile); + } + + if (bRecursive) + { + /* Recursive sends are closed by sending "E\n". */ + sprintf (buff, "E\n"); + if (write (fileno (stdout), buff, strlen (buff)) < 1) + { + error ("Error sending directory status."); + return; + } + + /* Receive data from the client. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + return; + } + if (buff[0] != 0) + { + error ("Remote system Failed."); + return; + } + + } + +} + +/* Process files being sent by a remote system. + TARGET is the target specified in the rcp request. + BRECURSIVE specifies if this request recurses sub-directories + on the remote system. Directories may need to be created. + BTARGDIR specifies if the target specified MUST be a directory. + + Assumptions: + All files are written as BINARY to preserve the file size and + data contained in the files. */ +void +RcpSvrRecv (char *Target, BOOL bRecursive, BOOL bTargDir) +{ + char buff[RCP_BUFFER_SIZE + 1]; + int blen = RCP_BUFFER_SIZE; + int FileId; + DWORD dwFileSize; + DWORD dwBytesRecv; + int dwBytes; + int nValue; + BOOL bMoreFiles; + HANDLE hFile = INVALID_HANDLE_VALUE; + char expTarget[MAX_PATH]; + char *Target2; + char *NewLine; + BOOL bDir; + BOOL bTarget; + BOOL bProcessing; + + debug ("RcpSvrRecv\n"); + + strcpy (expTarget, Target); + bDir = bTargDir; + bMoreFiles = ParseTarget (&hFile, expTarget, &bDir); + if (bMoreFiles) + { + Target2 = NextTarget (hFile, &bTarget); + if (Target2 != NULL) + { + /* Error condition: more than one target. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: ambiguous target\n"); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + { + error ("Error sending result status."); + } + Sleep (RCP_ERR_DELAY); + CloseTarget (hFile); + return; + } + } + CloseTarget (hFile); + bTarget = bDir; + + if (bTargDir & !bDir) + { + /* Error condition: Directory required but file specified. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Not a directory\n", expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + { + error ("Error sending result status."); + } + Sleep (RCP_ERR_DELAY); + return; + } + + if (access (expTarget, 02) != 0) + { + if (bDir || (!bDir && (errno != ENOENT))) + { + /* Error condition: Can't access the target. */ + buff[0] = 1; + if (bDir && (errno == ENOENT)) + sprintf (&buff[1], "rcp: %s: No such file or directory\n", + expTarget); + else + sprintf (&buff[1], "rcp: %s: Permission Denied\n", expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + } + + bProcessing = TRUE; + Target2 = expTarget; + + /* Process files/directories from the remote system. */ + while (bProcessing) + { + debug ("Sending null byte ...\n"); + buff[0] = 0; + if (write (fileno (stdout), buff, 1) < 1) + { + error ("Error sending result status."); + return; + } + debug ("Sent.\n"); + + if (bDir) + { + nValue = chdir (Target2); + if (nValue == -1) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: No such file or directory\n", + expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + } + + debug ("waiting for data.\n"); + + /* Receive data from the client + File/dir specification ends in a '\n', so read byte by byte + until one is reached or a '\0' is received. */ + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data.");; + return; + } + + debug ("got %d bytes.\n", dwBytes); + debug ("got: %d (%c)\n", buff[0], buff[0]); + + /* Process the file or directory specification. */ + switch (buff[0]) + { + case 0: + case 1: + /* Finished processing. */ + return; + + case 'E': + /* Finished with current directory. Backup to the + parent directory. */ + + Target2 = ".."; + bDir = TRUE; + continue; + + case 'T': + /* This is permissions data related to the -p option. + Just ignore it. */ + continue; + + case 'D': + /* A directory is being identified. */ + + bDir = TRUE; + Target2 = strtok (buff, " "); + Target2 = strtok (NULL, " "); + Target2 = strtok (NULL, " "); + NewLine = strchr (Target2, 0x0a); + *NewLine = 0; + strcpy (expTarget, Target2); + Target2 = expTarget; + + if (access (Target2, 02) != 0) + { + if (errno != ENOENT) + { + /* Error condition: Can't access directory. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Directory access failure %d\n", + expTarget, errno); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < + 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + /* Create directory. */ + nValue = mkdir (Target2); + if (nValue == -1) + { + /* Error condition: Can't create directory. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s: Directory creation failed\n", + expTarget); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + } + continue; + + case 'C': + /* A file is being identified. */ + if (bTarget) + { + Target2 = strtok (buff, " "); + Target2 = strtok (NULL, " "); + Target2 = strtok (NULL, " "); + NewLine = strchr (Target2, 0x0a); + *NewLine = 0; + strcpy (expTarget, Target2); + Target2 = expTarget; + } + + bDir = FALSE; + /* Open the file for writing. */ + FileId = + _open (Target2, _O_WRONLY | _O_TRUNC | _O_CREAT | _O_BINARY, + _S_IWRITE); + if (FileId == -1) + { + /* Error condition. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s :Cannot open file\n", Target2); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error sending result status."); + Sleep (RCP_ERR_DELAY); + return; + } + break; + + default: + return; + } + + dwFileSize = atol (&buff[6]); + if (debugFlag) + fprintf (stderr, "Receiving file %s of size %lu.\n", Target2, dwFileSize); + + buff[0] = 0; + if (write (fileno (stdout), buff, 1) < 1) + { + error ("Error sending result status."); + close (FileId); + return; + } + + /* Process the file being transferred. */ + dwBytesRecv = 0; + /* If file size=0, expect 1 byte 0x00. */ + if (dwFileSize == 0) + { + if ((dwBytes = RcpReceive (buff, blen)) == -1) + { + error ("Cannot receive client data."); + close (FileId); + return; + } + else if (buff[0] != 0) + error ("Received data for zero length file"); + } + else + { + while (dwBytesRecv < dwFileSize) + { + /* Receive data from the client. */ + if ((dwBytes = read (fileno (stdin), buff, blen)) == -1) + { + error ("Cannot receive client data."); + close (FileId); + return; + } + + dwBytesRecv += dwBytes; + + /* Write the data to the file. */ + nValue = write (FileId, buff, dwBytes); + + if (nValue != dwBytes) + { + /* Error condition: write failure. */ + buff[0] = 1; + sprintf (&buff[1], "rcp: %s :Cannot write to file\n", + Target2); + if (write (fileno (stdout), buff, strlen (&buff[1]) + 1) < 1) + error ("Error writing error status."); + Sleep (RCP_ERR_DELAY); + close (FileId); + return; + } + } + } + + close (FileId); + } + + return; +} + +/* Determines what type of rcp is being + requested and processes it accordingly. + + Valid rcp requests are in the form: + rcp -t [-d] [-r] [-p] target + rcp -f [r] [-p] target + + NOTE: The -p option is being ignored since there is not a good + correlation between UNIX and NT when it comes to file + permissions and ownership. */ +int +rcp_main (int argc, char **argv) +{ + int i; + char *HomeDir; + + BOOL bTargDir = FALSE; + BOOL bSvrRecv = FALSE; + BOOL bSvrSend = FALSE; + BOOL bRecursive = FALSE; + + /* Get the current working directory. */ + HomeDir = getcwd (NULL, MAX_PATH); + + i = 1; + for (; argv[i] && argv[i][0] == '-'; i++) + { + switch (argv[i][1]) + { + case 'd': + /* Target must be directory. */ + bTargDir = TRUE; + break; + + case 't': + /* rcp is receiving files. */ + bSvrRecv = TRUE; + break; + + case 'f': + /* rcp is sending files. */ + bSvrSend = TRUE; + break; + + case 'p': + /* Preserve Permissions. This option is ignored for now. */ + break; + + case 'r': + /* Recursive send/recv. */ + bRecursive = TRUE; + break; + + default: + fprintf (stderr, "wrong args\n"); + exit (1); + } + } + + if (!bSvrRecv && !bSvrSend) + { + error ("Invalid args"); + exit (1); + } + + if (bSvrRecv) + { + if (bRecursive) + bTargDir = TRUE; + + RcpSvrRecv (argv[i], bRecursive, bTargDir); + } + else + RcpSvrSend (argv[i], bRecursive); + + /* Make sure we end up where we started. */ + chdir (HomeDir); + free (HomeDir); + return 0; +} + +int +main (int argc, char **argv) +{ + return rcp_main (argc, argv); +} Property changes on: trunk/cegcc/tools/rcp/rcp.c ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-25 01:14:18
|
Revision: 1007 http://svn.sourceforge.net/cegcc/?rev=1007&view=rev Author: pedroalves Date: 2007-06-24 18:14:15 -0700 (Sun, 24 Jun 2007) Log Message: ----------- Initial import. * LICENSE, README, TODO, ChangeLog, Makefile, cwd.c cwd.h: New files. Added Paths: ----------- trunk/cegcc/tools/libcwd/ trunk/cegcc/tools/libcwd/ChangeLog trunk/cegcc/tools/libcwd/LICENSE trunk/cegcc/tools/libcwd/Makefile trunk/cegcc/tools/libcwd/README trunk/cegcc/tools/libcwd/TODO trunk/cegcc/tools/libcwd/cwd.c trunk/cegcc/tools/libcwd/cwd.h Added: trunk/cegcc/tools/libcwd/ChangeLog =================================================================== --- trunk/cegcc/tools/libcwd/ChangeLog (rev 0) +++ trunk/cegcc/tools/libcwd/ChangeLog 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,13 @@ +2007-06-25 Pedro Alves <ped...@po...> + + Initial import. + + * LICENSE, README, TODO, ChangeLog, Makefile, cwd.c cwd.h: New files. + + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: Property changes on: trunk/cegcc/tools/libcwd/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/LICENSE =================================================================== --- trunk/cegcc/tools/libcwd/LICENSE (rev 0) +++ trunk/cegcc/tools/libcwd/LICENSE 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,25 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ Added: trunk/cegcc/tools/libcwd/Makefile =================================================================== --- trunk/cegcc/tools/libcwd/Makefile (rev 0) +++ trunk/cegcc/tools/libcwd/Makefile 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,62 @@ +TARGET=arm-wince-mingw32ce +LDFLAGS= +INCLUDES=-I. +CFLAGS=-O0 -g3 +WARNFLAGS=-Wall -Wextra + +ALLFLAGS=$(WARNFLAGS) $(CFLAGS) $(INCLUDES) + +CC=$(TARGET)-gcc +AR=$(TARGET)-ar + +LIBS = libcwd.a +TARGETS = $(LIBS) + +OBJECTS = cwd.o + +all: $(TARGETS) +libs: $(LIBS) + +.c.o: + $(CC) -c -o $@ $< $(ALLFLAGS) + +cwd.o: cwd.c cwd.h Makefile +stat.o: stat.o cwd.h Makefile +open.o: open.o cwd.h Makefile +rename.o: rename.o cwd.h Makefile +stat.o: stat.o cwd.h Makefile +tempnam.o: tempnam.o cwd.h Makefile +unlink.o: unlink.o cwd.h Makefile + +libcwd.a: $(OBJECTS) Makefile + rm -f $@ + $(AR) r $@ $(OBJECTS) + +install: + +clean: + rm -f $(LIBS) $(OBJECTS) + +dist: srcdist bindist + +srcdist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(SRCDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-src$(TARFILEEXT) $(distdir) + +bindist: all + rm -rf $(distdir) + mkdir $(distdir) + chmod 755 $(distdir) + for i in $(BINDIST_FILES); do \ + cp -p $(srcdir)/$$i $(distdir)/$$i ; \ + done + rm -f $(distdir).tar.gz + $(TAR) $(TARFLAGS)cf $(distdir)-bin$(TARFILEEXT) $(distdir) + +.PHONY: all install clean dist bindist srcdist Property changes on: trunk/cegcc/tools/libcwd/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/README =================================================================== --- trunk/cegcc/tools/libcwd/README (rev 0) +++ trunk/cegcc/tools/libcwd/README 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,22 @@ +This is a cwd lib for WinCE. + +This is a lib that serves as a porting aid. It provides chdir and +getcwd calls, thus a current working directory notion. + +Note that this lib is built as a static lib, so be careful with +linking the lib into several dlls/exe. Don't expect the same cwd +to be seen across dlls. For that to work, you'll need to build a +libcwd.dll. + +Have fun! + +Pedro Alves + +-- + +See the file LICENSE in the various directories, for a description of +the license the software is licensed in. + +REPORTING BUGS: +ce...@so... +pe...@po... Property changes on: trunk/cegcc/tools/libcwd/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/TODO =================================================================== --- trunk/cegcc/tools/libcwd/TODO (rev 0) +++ trunk/cegcc/tools/libcwd/TODO 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,2 @@ + + * Add a mutex locking access to cwd. Property changes on: trunk/cegcc/tools/libcwd/TODO ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/cwd.c =================================================================== --- trunk/cegcc/tools/libcwd/cwd.c (rev 0) +++ trunk/cegcc/tools/libcwd/cwd.c 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,320 @@ +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <wchar.h> + +#include <windows.h> + +#include "cwd.h" + +static wchar_t *XCEFixPathW (const wchar_t *wpathin, wchar_t *wpathout); +static wchar_t *XCECanonicalizePathW (wchar_t *target); +static DWORD XCEGetCurrentDirectoryW (DWORD dwSize, wchar_t *buf); + +#define COUNTOF(X) (sizeof (X) / sizeof ((X)[0])) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +#define IS_DIRECTORY_SEP(X) (X == '\\') +#define IS_ANY_SEP(X) (X == '\\') + +/* Per process as on WinNT + ### TODO, we need a mutex here if we ever go multithread. */ + +static wchar_t _current_dirw[MAX_PATH+1] = L"\\"; +#define _CURRENTDIRW _current_dirw + +static DWORD +XCEGetFileAttributesW (const wchar_t *wfname) +{ + wchar_t wpath[MAX_PATH]; + DWORD dwRes; + + XCEFixPathW (wfname, wpath); + dwRes = GetFileAttributesW (wpath); + + return dwRes; +} + +static char * +XCEToUnixPath (char *s, int len) +{ + char *p; + + if (len < 0) + { + for(p = s; *p; p++) + if(*p == '\\') + *p = '/'; + } + else + { + int i; + for(i = 0; i < len ; i++) + if(s[i] == '\\') + s[i] = '/'; + } + + return s; +} + +static void +append_slash_if_needed (wchar_t* wbuf) +{ + int len = wcslen (wbuf); + if (len > 0 + && wbuf[len - 1] != '\\' + && wbuf[len - 1] != '/') + wcscat (wbuf, L"\\"); +} + +static wchar_t * +XCEFixPathW (const wchar_t *wpathin, wchar_t *wpathout) +{ + wchar_t wdir[MAX_PATH+1]; + wchar_t *p; + + wpathout[0] = 0; + append_slash_if_needed (wpathout); + + if(wpathin[0] != '\\' && wpathin[0] != '/') + { + XCEGetCurrentDirectoryW (sizeof(wdir), wdir); + wcscat (wpathout, wdir); + append_slash_if_needed (wpathout); + } + + wcscat (wpathout, wpathin); + + for(p = wpathout; *p; p++) + { + if(*p == '/') + *p = '\\'; + } + + /* don't allow slash at end of directory name... */ + if(p[-1] == '\\' && p != wpathout + 1) + p[-1] = 0; + + /* now remove . and .. */ + XCECanonicalizePathW (wpathout); + + return wpathout; +} + +static wchar_t * +XCECanonicalizePathW (wchar_t *target) +{ + wchar_t *p = target; + wchar_t *o = target; + + while (*p) + { + if (!IS_DIRECTORY_SEP (*p)) + { + *o++ = *p++; + } + else if (IS_DIRECTORY_SEP (p[0]) + && p[1] == '.' + && (IS_DIRECTORY_SEP (p[2]) + || p[2] == 0)) + { + /* If "/." is the entire filename, keep the "/". Otherwise, + just delete the whole "/.". */ + if (o == target && p[2] == '\0') + *o++ = *p; + p += 2; + } + else if (IS_DIRECTORY_SEP (p[0]) && p[1] == '.' && p[2] == '.' + /* `/../' is the "superroot" on certain file systems. */ + /* disabled this test, as it wasn't filtering '/..' because of it. + cegcc should also have the same problem. */ + /* && o != target */ + && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)) + { + while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) + ; + /* Keep initial / only if this is the whole name. */ + if (o == target && IS_ANY_SEP (*o) && p[3] == 0) + ++o; + p += 3; + } + else + { + *o++ = *p++; + } + } + + *o = 0; + + return target; +} + +static DWORD +XCEGetCurrentDirectoryW (DWORD dwSize, wchar_t *buf) +{ + size_t len = wcslen(_CURRENTDIRW); + if (dwSize == 0 && buf == 0) + return len+1; + wcsncpy (buf, _CURRENTDIRW, dwSize - 1); + if (dwSize > len) + return len; + else + return len+1; +} + +static DWORD +XCEGetCurrentDirectoryA (DWORD dwSize, char *buf) +{ + DWORD dwLen; + wchar_t wbuf[MAX_PATH+1]; + + dwLen = XCEGetCurrentDirectoryW (dwSize, wbuf); + if (dwSize == 0 && buf == 0) + return dwSize; + WideCharToMultiByte (CP_ACP, 0, wbuf, -1, + buf, MIN(dwLen, dwSize), NULL, NULL); + buf[MIN(dwLen, dwSize)] = 0; + return dwLen; +} + +static BOOL +XCESetCurrentDirectoryW (const wchar_t *wdir) +{ + DWORD dwAttr; + wchar_t wtmp[MAX_PATH]; + + int wlen = wcslen (wdir); + if (wlen > (MAX_PATH - 1)) + return 0; + else if (wlen > 0 + && !(wdir[wlen-1] == '\\' || wdir[wlen-1] == '/') + && wlen > (MAX_PATH - 2)) + return 0; + + /* Oh great... There is some code generation bug in mingw32ce. Inlining + the call hides the problem. */ + // XCEFixPathW (wdir, wtmp); + const wchar_t *wpathin = wdir; + wchar_t *wpathout = wtmp; + { + wchar_t wdir[MAX_PATH+1]; + wchar_t *p; + + wpathout[0] = 0; + + if(wpathin[0] != '\\' && wpathin[0] != '/') + { + XCEGetCurrentDirectoryW (sizeof(wdir), wdir); + wcscat (wpathout, wdir); + append_slash_if_needed (wpathout); + } + + wcscat (wpathout, wpathin); + + for(p = wpathout; *p; p++) + { + if(*p == '/') + *p = '\\'; + } + + /* Don't allow slash at end of directory name... */ + if(p[-1] == '\\' && p != wpathout + 1) + p[-1] = 0; + + /* Now remove . and .. */ + XCECanonicalizePathW (wpathout); + } + + if((dwAttr = XCEGetFileAttributesW (wtmp)) == 0xFFFFFFFF) + return FALSE; + + if((dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0) + { +// errno = ENOTDIR; + return FALSE; + } + + wcscpy (_CURRENTDIRW, wtmp); + return TRUE; +} + +static BOOL +XCESetCurrentDirectoryA (const char *dir) +{ + wchar_t wdir[MAX_PATH]; + int len = strlen(dir); + if (len > (MAX_PATH - 1)) + return 0; + else if (len>0 + && !(dir[len-1] == '\\' || dir[len-1] == '/') + && len > (MAX_PATH - 2)) + return 0; + + MultiByteToWideChar (CP_ACP, 0, dir, -1, wdir, COUNTOF (wdir)); + return XCESetCurrentDirectoryW (wdir); +} + +int +_chdir (const char *path) +{ + char fpath[MAX_PATH+1]; + + if (path == NULL || strlen (path) == 0) + { + /* errno? */ + return -1; + } + + if (!XCESetCurrentDirectoryA (path)) + return -1; + + XCEGetCurrentDirectoryA (MAX_PATH + 1, fpath); + XCEToUnixPath (fpath, -1); + return 0; +} + +char * +_getcwd (char *buf, int size) +{ + int len; + char *alloced = NULL; + + if (buf == NULL || size == 0) + { + size = MAX_PATH + 1; + buf = alloced = malloc (size); + if (!buf) + return NULL; + } + + len = XCEGetCurrentDirectoryA ((DWORD) size, buf); + + if (len > size) + { + XCEToUnixPath (buf, size - 1); + return NULL; + } + + if (len == 0) + { + if (alloced != NULL) + free (alloced); + return NULL; + } + + XCEToUnixPath (buf, -1); + return buf; +} + +int +chdir (const char *path) +{ + return _chdir (path); +} + +char * +getcwd (char *buf, int size) +{ + return _getcwd (buf, size); +} Property changes on: trunk/cegcc/tools/libcwd/cwd.c ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/libcwd/cwd.h =================================================================== --- trunk/cegcc/tools/libcwd/cwd.h (rev 0) +++ trunk/cegcc/tools/libcwd/cwd.h 2007-06-25 01:14:15 UTC (rev 1007) @@ -0,0 +1,19 @@ +#ifndef __LIB_CE_CWD_H_ +#define __LIB_CE_CWD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> + +extern char *getcwd (char *buf, int size); +extern char *_getcwd (char *buf, int size); +extern int chdir (const char *path); +extern int _chdir (const char *path); + +#ifdef __cplusplus +} +#endif + +#endif /* __LIB_CE_CWD_H_ */ Property changes on: trunk/cegcc/tools/libcwd/cwd.h ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-25 01:06:17
|
Revision: 1006 http://svn.sourceforge.net/cegcc/?rev=1006&view=rev Author: pedroalves Date: 2007-06-24 18:06:15 -0700 (Sun, 24 Jun 2007) Log Message: ----------- Initial import. * LICENSE, README, TODO, ChangeLog, Makefile, errno.c errno.tab, errno_h.awk, errno_str.awk, errno_tab.awk: New files. Added Paths: ----------- trunk/cegcc/tools/errno/ trunk/cegcc/tools/errno/ChangeLog trunk/cegcc/tools/errno/LICENSE trunk/cegcc/tools/errno/Makefile trunk/cegcc/tools/errno/README trunk/cegcc/tools/errno/TODO trunk/cegcc/tools/errno/errno.c trunk/cegcc/tools/errno/errno.tab trunk/cegcc/tools/errno/errno_h.awk trunk/cegcc/tools/errno/errno_str.awk trunk/cegcc/tools/errno/errno_tab.awk Added: trunk/cegcc/tools/errno/ChangeLog =================================================================== --- trunk/cegcc/tools/errno/ChangeLog (rev 0) +++ trunk/cegcc/tools/errno/ChangeLog 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,14 @@ +2007-06-25 Pedro Alves <ped...@po...> + + Initial import. + + * LICENSE, README, TODO, ChangeLog, Makefile, errno.c errno.tab, + errno_h.awk, errno_str.awk, errno_tab.awk: New files. + + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: Property changes on: trunk/cegcc/tools/errno/ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/LICENSE =================================================================== --- trunk/cegcc/tools/errno/LICENSE (rev 0) +++ trunk/cegcc/tools/errno/LICENSE 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,25 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ Added: trunk/cegcc/tools/errno/Makefile =================================================================== --- trunk/cegcc/tools/errno/Makefile (rev 0) +++ trunk/cegcc/tools/errno/Makefile 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,38 @@ +TARGET=arm-wince-mingw32ce + +CC=$(TARGET)-gcc +AR=$(TARGET)-ar + +INCLUDES=-I. +ALLFLAGS=$(CFLAGS) $(INCLUDES) + +GENFILES=errno.h errno_tab.c errno_str.c +OBJECTS=errno.o + +all: liberrno.a + +errno_tab.c: errno.tab errno_tab.awk Makefile + awk '{ print $$2 " " $$1 }' < errno.tab | sort | awk -f errno_tab.awk > $@ + +errno_str.c: errno.tab errno_str.awk Makefile + awk -f errno_str.awk < errno.tab > $@ + +errno.h: errno.tab errno_h.awk Makefile + awk -f errno_h.awk < errno.tab > $@ + +errno.o: errno.c errno_tab.c errno_str.c errno.h Makefile + $(CC) -c -o $@ $< $(ALLFLAGS) + +liberrno.a: errno.o Makefile + rm -f $@ + $(AR) r $@ $< + +clean: + rm -f liberrno.a $(OBJECTS) + +distclean: clean + rm -f $(GENFILES) + +regen: distclean $(GENFILES) + +.PHONY: all clean regen Property changes on: trunk/cegcc/tools/errno/Makefile ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/README =================================================================== --- trunk/cegcc/tools/errno/README (rev 0) +++ trunk/cegcc/tools/errno/README 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,28 @@ +This is an errno <-> {Get|Set}LastError mapper. + +<describe here the technique used> + +Do *not* install errno.h into +/opt/mingw32ce/arm-wince-mingw32ce/include. + +You have been warned. + +This is only used as a porting aid. Ideally you use this as an +interim measure until you finish the port. If you chose to keep using +it, and you are writing a lib to be reused by others, be sure to *NOT* +export any header that includes errno.h. Do *NOT* expect your users +to have errno.h. If needed, copy errno.h and errno.c into your +project, but again, do *NOT* force it into the users. + +Have fun! + +Pedro Alves + +-- + +See the file LICENSE in the various directories, for a description of +the license the software is license in. + +REPORTING BUGS: +ce...@so... +pe...@po... Property changes on: trunk/cegcc/tools/errno/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/TODO =================================================================== --- trunk/cegcc/tools/errno/TODO (rev 0) +++ trunk/cegcc/tools/errno/TODO 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1 @@ + Property changes on: trunk/cegcc/tools/errno/TODO ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/errno.c =================================================================== --- trunk/cegcc/tools/errno/errno.c (rev 0) +++ trunk/cegcc/tools/errno/errno.c 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,112 @@ +/* Pedro Alves */ + +#include "errno.h" +#include <windows.h> + +/* There are more WinErr codes than errno codes. + To prevent having to do stuff like: + +- if (errno == ENOENT) ++ if (errno == ERROR_PATH_NOT_FOUND ++ || errno == ERROR_FILE_NOT_FOUND) + + ... we colapse the multiple WinErr mappings into one. */ + +int +__liberrno_errno (void) +{ + DWORD winerr = GetLastError (); + switch (winerr) + { +#include "errno_tab.c" + default: + return (int) winerr; + } +} + +#ifndef COUNTOF +#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0])) +#endif + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char * +strwinerror (char* buf, DWORD error) +{ + wchar_t *msgbuf; + DWORD lasterr = GetLastError (); + DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) + { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' + && msgbuf[chars - 1] == '\n') + { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > ((COUNTOF (buf)) - 1)) + { + chars = COUNTOF (buf) - 1; + msgbuf [chars] = 0; + } + + wcstombs (buf, msgbuf, chars + 1); + LocalFree (msgbuf); + } + else + sprintf (buf, "unknown win32 error (%ld)", error); + + SetLastError (lasterr); + return buf; +} + +__inline__ static const char* +get_errstr (DWORD winerr) +{ + switch (winerr) + { +#include "errno_str.c" + } + return NULL; +} + +char * +strerror (int error) +{ + static char buf[1024]; + DWORD winerr = (DWORD) error; + const char *str = get_errstr (winerr); + + if (str != NULL) + strcpy (buf, str); + else + strwinerror (buf, winerr); + return buf; +} + +void +perror (const char *s) +{ + if (s && *s) + fprintf (stderr, "%s: %s\n", s, strerror (errno)); + else + fprintf (stderr, "%s\n", strerror (errno)); +} Property changes on: trunk/cegcc/tools/errno/errno.c ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/errno.tab =================================================================== --- trunk/cegcc/tools/errno/errno.tab (rev 0) +++ trunk/cegcc/tools/errno/errno.tab 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,165 @@ +# libceerrno v1.0 +# +# errno to Windows error mapping. + +EACCES ERROR_ACCESS_DENIED "Permission denied" +EACCES ERROR_LOCK_VIOLATION +EACCES ERROR_SHARING_VIOLATION + +EAGAIN ERROR_MORE_DATA "Resource temporarily unavailable" +EAGAIN ERROR_ACTIVE_CONNECTIONS +EAGAIN ERROR_DEVICE_IN_USE +EAGAIN ERROR_MAX_THRDS_REACHED +EAGAIN ERROR_NO_PROC_SLOTS +EAGAIN ERROR_OPEN_FILES + +EBADF ERROR_INVALID_HANDLE "Bad file descriptor" + +EBADRQC ERROR_INVALID_FUNCTION "Invalid request code" + +EBUSY ERROR_BUSY "Device or resource busy" +EBUSY ERROR_CHILD_NOT_COMPLETE +EBUSY ERROR_PIPE_BUSY +EBUSY ERROR_PIPE_CONNECTED +EBUSY ERROR_SIGNAL_PENDING + +ECHILD ERROR_WAIT_NO_CHILDREN "No child processes" + +ECOMM ERROR_PIPE_LISTENING "Communication error on send" +ECOMM ERROR_PIPE_NOT_CONNECTED + +EDEADLOCK ERROR_POSSIBLE_DEADLOCK "File locking deadlock error" + +EEXIST ERROR_FILE_EXISTS "File exists" +EEXIST ERROR_ALREADY_EXISTS + +EFAULT ERROR_PROCESS_ABORTED "Bad address" +EFAULT ERROR_NOACCESS + +EINTR ERROR_INVALID_AT_INTERRUPT_TIME "Interrupted system call" + +EINVAL ERROR_INVALID_PARAMETER "Invalid argument" +EINVAL ERROR_BAD_PIPE +EINVAL ERROR_BAD_USERNAME +EINVAL ERROR_FILENAME_EXCED_RANGE +EINVAL ERROR_INVALID_DATA +EINVAL ERROR_INVALID_SIGNAL_NUMBER +EINVAL ERROR_META_EXPANSION_TOO_LONG +EINVAL ERROR_NEGATIVE_SEEK +EINVAL ERROR_NO_TOKEN +EINVAL ERROR_THREAD_1_INACTIVE + +EIO ERROR_IO_DEVICE "Input/Output error" +EIO ERROR_CRC +EIO ERROR_NO_SIGNAL_SENT +EIO ERROR_OPEN_FAILED +EIO ERROR_SIGNAL_REFUSED + +EMFILE ERROR_TOO_MANY_OPEN_FILES "Too many open files" +ENFILE ERROR_NO_MORE_SEARCH_HANDLES + +ENMFILE ERROR_NO_MORE_FILES "No more files" + +ENODATA ERROR_HANDLE_EOF "No data available" + +ENODEV ERROR_BAD_DEVICE "No such device" +ENODEV ERROR_BAD_UNIT +ENODEV ERROR_INVALID_DRIVE + +ENOENT ERROR_FILE_NOT_FOUND "No such file or directory" +ENOENT ERROR_BAD_PATHNAME +ENOENT ERROR_INVALID_NAME +ENOENT ERROR_PATH_NOT_FOUND + +ENOERR NO_ERROR "No error" + +ENOLCK ERROR_SHARING_BUFFER_EXCEEDED "No locks available" + +ENOLINK ERROR_NOT_CONNECTED "Link has been severed" + +ENOMEDIUM ERROR_NOT_READY "No medium found" + +ENOMEM ERROR_NOT_ENOUGH_MEMORY "Cannot allocate memory" +ENOMEM ERROR_OUTOFMEMORY + +ENONET ERROR_REM_NOT_LIST "Machine is not on the network" + +ENOSHARE ERROR_BAD_NETPATH "No such host or network path" +ENOSHARE ERROR_BAD_NET_NAME + +ENOSPC ERROR_DISK_FULL "No space left on device" +ENOSPC ERROR_END_OF_MEDIA +ENOSPC ERROR_EOM_OVERFLOW +ENOSPC ERROR_HANDLE_DISK_FULL +ENOSPC ERROR_NO_DATA_DETECTED + +ENOSYS ERROR_CALL_NOT_IMPLEMENTED "Function not implemented" +ENOSYS ERROR_NOT_SUPPORTED + +ENOTDIR ERROR_DIRECTORY "Not a directory" + +ENOTEMPTY ERROR_DIR_NOT_EMPTY "Directory not empty" +ENOTEMPTY WSAENOTEMPTY + +ENOTUNIQ ERROR_DUP_NAME "Name not unique on network" + +ENXIO ERROR_FILE_INVALID "No such device or address" + +EOVERFLOW ERROR_ARITHMETIC_OVERFLOW "Value too large for defined data type" + +EPERM ERROR_CANNOT_MAKE "Operation not permitted" +EPERM ERROR_NOT_OWNER + +EPIPE ERROR_BROKEN_PIPE "Broken pipe" +EPIPE ERROR_NO_DATA + +# also defined as EOVERFLOW above +ERANGE ERROR_ARITHMETIC_OVERFLOW + +EROFS ERROR_WRITE_PROTECT "Read-only file system" + +ESPIPE ERROR_BEGINNING_OF_MEDIA "Illegal seek" +ESPIPE ERROR_SETMARK_DETECTED + +EXDEV ERROR_NOT_SAME_DEVICE "Invalid cross-device link" + +# Winsock codes + +EWOULDBLOCK +EINPROGRESS WSAEINPROGRESS +EALREADY WSAEALREADY +ENOTSOCK WSAENOTSOCK +EDESTADDRREQ WSAEDESTADDRREQ +EMSGSIZE WSAEMSGSIZE +EPROTOTYPE WSAEPROTOTYPE +ENOPROTOOPT WSAENOPROTOOPT +EPROTONOSUPPORT WSAEPROTONOSUPPORT +ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +EOPNOTSUPP WSAEOPNOTSUPP +EPFNOSUPPORT WSAEPFNOSUPPORT +EAFNOSUPPORT WSAEAFNOSUPPORT +EADDRINUSE WSAEADDRINUSE +EADDRNOTAVAIL WSAEADDRNOTAVAIL +ENETDOWN WSAENETDOWN +ENETUNREACH WSAENETUNREACH +ENETRESET WSAENETRESET +ECONNABORTED WSAECONNABORTED +ECONNRESET WSAECONNRESET +ENOBUFS WSAENOBUFS +EISCONN WSAEISCONN +ENOTCONN WSAENOTCONN +ESHUTDOWN WSAESHUTDOWN +ETOOMANYREFS WSAETOOMANYREFS +ETIMEDOUT WSAETIMEDOUT +ECONNREFUSED WSAECONNREFUSED +ELOOP WSAELOOP +ENAMETOOLONG WSAENAMETOOLONG +EHOSTDOWN WSAEHOSTDOWN +EHOSTUNREACH WSAEHOSTUNREACH +# Defined above because of conflict. +#ENOTEMPTY WSAENOTEMPTY +EPROCLIM WSAEPROCLIM +EUSERS WSAEUSERS +EDQUOT WSAEDQUOT +ESTALE WSAESTALE +EREMOTE WSAEREMOTE Added: trunk/cegcc/tools/errno/errno_h.awk =================================================================== --- trunk/cegcc/tools/errno/errno_h.awk (rev 0) +++ trunk/cegcc/tools/errno/errno_h.awk 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,41 @@ +BEGIN { + print "\ +#ifndef _LIB_CE_ERRNO_H\n\ +#define _LIB_CE_ERRNO_H\n\ +\n\ +#include <winerror.h>\n\ +\n\ +#define errno __liberrno_errno ()\n\ +#define __set_errno(ERR) SetLastError (ERR)\n\ +\n\ +#ifdef __cplusplus\n\ +extern \"C\" {\n\ +#endif\n\ +\n\ +int __liberrno_errno (void);\n\ +\n\ +char *strerror (int error);\n\ +void perror (const char *s);\n\ +\n\ +#ifdef __cplusplus\n\ +}\n\ +#endif\n\ +\n"; +} + +{ + errno = $1; + winerr = $2; + + if (errno != "" && substr (errno, 1, 1) != "#") + { + if (errno != prev_errno) + print "#define " errno " " winerr; + prev_errno = errno; + } +} + +END { + print ""; + print "#endif /* _LIB_CE_ERRNO_H */"; +} Property changes on: trunk/cegcc/tools/errno/errno_h.awk ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/errno_str.awk =================================================================== --- trunk/cegcc/tools/errno/errno_str.awk (rev 0) +++ trunk/cegcc/tools/errno/errno_str.awk 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,12 @@ +BEGIN { +} + +{ + errno = $1; + winerr = $2; + # get tail beginning at $3 + msg=$0; for (i=1;i<3;i++) sub($i,"",msg); sub(/ */,"",msg) + + if (errno != "" && substr ($1, 1, 1) != "#" && msg != "") + print "case " winerr ": return " msg ";"; +} Property changes on: trunk/cegcc/tools/errno/errno_str.awk ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/errno/errno_tab.awk =================================================================== --- trunk/cegcc/tools/errno/errno_tab.awk (rev 0) +++ trunk/cegcc/tools/errno/errno_tab.awk 2007-06-25 01:06:15 UTC (rev 1006) @@ -0,0 +1,13 @@ +BEGIN { +} + +{ + winerr = $1; + errno = $2; + + if (errno != "" && substr (errno, 1, 1) != "#" && prev_winerr != winerr) + { + print "case " winerr ": return " errno ";"; + prev_winerr = winerr; + } +} Property changes on: trunk/cegcc/tools/errno/errno_tab.awk ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-24 23:49:57
|
Revision: 1005 http://svn.sourceforge.net/cegcc/?rev=1005&view=rev Author: pedroalves Date: 2007-06-24 16:49:55 -0700 (Sun, 24 Jun 2007) Log Message: ----------- * rshd.c (handle_connection): Remove out of sync comment. Modified Paths: -------------- trunk/cegcc/tools/rshd/ChangeLog trunk/cegcc/tools/rshd/rshd.c Modified: trunk/cegcc/tools/rshd/ChangeLog =================================================================== --- trunk/cegcc/tools/rshd/ChangeLog 2007-06-24 23:40:06 UTC (rev 1004) +++ trunk/cegcc/tools/rshd/ChangeLog 2007-06-24 23:49:55 UTC (rev 1005) @@ -1,5 +1,9 @@ 2007-06-25 Pedro Alves <ped...@po...> + * rshd.c (handle_connection): Remove out of sync comment. + +2007-06-25 Pedro Alves <ped...@po...> + * rshd.c (GetStdioPathW, SetStdioPathW): Declare. (SafeCloseHandle): New function. (stdin_thread): Don't close the reading side of the pipe too early. Modified: trunk/cegcc/tools/rshd/rshd.c =================================================================== --- trunk/cegcc/tools/rshd/rshd.c 2007-06-24 23:40:06 UTC (rev 1004) +++ trunk/cegcc/tools/rshd/rshd.c 2007-06-24 23:49:55 UTC (rev 1005) @@ -887,8 +887,6 @@ release_data (client_data); - /* maybe we should wait for all the still alive threads again? */ - return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-24 23:40:09
|
Revision: 1004 http://svn.sourceforge.net/cegcc/?rev=1004&view=rev Author: pedroalves Date: 2007-06-24 16:40:06 -0700 (Sun, 24 Jun 2007) Log Message: ----------- * rshd.c (GetStdioPathW, SetStdioPathW): Declare. (SafeCloseHandle): New function. (stdin_thread): Don't close the reading side of the pipe too early. Use SafeCloseHandle. Don't echo data back. Add debug output into rshd's console. (stdout_thread): Use SafeCloseHandle. Add debug output into rshd's console. (stderr_thread): Use SafeCloseHandle. Add debug output into rshd's console. (create_child): Add PROCESS_INFORMATION* parameter. Create child suspended. Use SafeCloseHandle. (connect_stderr): Make it static. (handle_connection): Don't store the children't pids. Pass a new PROCESS_INFORMATION local var to create_child. Resume child after starting the stdin/stdout/stderr threads. Always wait for the three threads to finish. If the child dies before closing stdin, stdout and stderr, close our ends of the pipe. Use SafeCloseHandle. * tester.c (main): Remove sleeps. * Makefile (STRIP): New. (UNSTRIPPED_BINS): New. (STRIPPED_BINS, LIBS, TARGETS): Delete. (OBJECTS): New. (bins, libs): Delete. (rshd.exe): Rename to ... (rshd_unstripped.exe): ... this. (rshd-stripped.exe): Rename to ... (rshd.exe): ... this. (tester.exe): Rename to ... (tester_unstripped.exe): ... this. (tester-stripped.exe): Rename to ... (tester.exe): ... this. (download-rshd): New rule. (download-tester): New rule. (download): Depend on download-rshd and download-tester to do the work. (clean): Clean $(OBJECTS), $(BINS) and $(UNSTRIPPED_BINS) (.PHONY): Add dependencies on download-rshd and download-tester. * TODO: Remove already implemented items. Modified Paths: -------------- trunk/cegcc/tools/rshd/ChangeLog trunk/cegcc/tools/rshd/Makefile trunk/cegcc/tools/rshd/TODO trunk/cegcc/tools/rshd/rshd.c trunk/cegcc/tools/rshd/tester.c Modified: trunk/cegcc/tools/rshd/ChangeLog =================================================================== --- trunk/cegcc/tools/rshd/ChangeLog 2007-06-24 22:58:14 UTC (rev 1003) +++ trunk/cegcc/tools/rshd/ChangeLog 2007-06-24 23:40:06 UTC (rev 1004) @@ -1,3 +1,44 @@ +2007-06-25 Pedro Alves <ped...@po...> + + * rshd.c (GetStdioPathW, SetStdioPathW): Declare. + (SafeCloseHandle): New function. + (stdin_thread): Don't close the reading side of the pipe too early. + Use SafeCloseHandle. Don't echo data back. Add debug output + into rshd's console. + (stdout_thread): Use SafeCloseHandle. Add debug output + into rshd's console. + (stderr_thread): Use SafeCloseHandle. Add debug output + into rshd's console. + (create_child): Add PROCESS_INFORMATION* parameter. Create child + suspended. Use SafeCloseHandle. + (connect_stderr): Make it static. + (handle_connection): Don't store the children't pids. Pass a new + PROCESS_INFORMATION local var to create_child. Resume child after + starting the stdin/stdout/stderr threads. Always wait for the three + threads to finish. If the child dies before closing stdin, stdout + and stderr, close our ends of the pipe. Use SafeCloseHandle. + * tester.c (main): Remove sleeps. + * Makefile (STRIP): New. + (UNSTRIPPED_BINS): New. + (STRIPPED_BINS, LIBS, TARGETS): Delete. + (OBJECTS): New. + (bins, libs): Delete. + (rshd.exe): Rename to ... + (rshd_unstripped.exe): ... this. + (rshd-stripped.exe): Rename to ... + (rshd.exe): ... this. + (tester.exe): Rename to ... + (tester_unstripped.exe): ... this. + (tester-stripped.exe): Rename to ... + (tester.exe): ... this. + (download-rshd): New rule. + (download-tester): New rule. + (download): Depend on download-rshd and download-tester to do the work. + (clean): Clean $(OBJECTS), $(BINS) and $(UNSTRIPPED_BINS) + (.PHONY): Add dependencies on download-rshd and download-tester. + + * TODO: Remove already implemented items. + 2007-06-20 Pedro Alves <ped...@po...> * rshd.c (init_client_data): Init refcount as 0. Modified: trunk/cegcc/tools/rshd/Makefile =================================================================== --- trunk/cegcc/tools/rshd/Makefile 2007-06-24 22:58:14 UTC (rev 1003) +++ trunk/cegcc/tools/rshd/Makefile 2007-06-24 23:40:06 UTC (rev 1004) @@ -8,12 +8,12 @@ ALLFLAGS=$(CFLAGS) $(INCLUDES) $(WARNFLAGS) CC=$(TARGET)-gcc +STRIP=$(TARGET)-strip +UNSTRIPPED_BINS = rshd_unstripped.exe tester_unstripped.exe BINS = rshd.exe tester.exe -STRIPPED_BINS = rshd-stripped.exe tester-stripped.exe -LIBS = -TARGETS = $(BINS) $(LIBS) +OBJECTS=rshd.o tester.o srcdir=. distdir=rshd-0.1.0 @@ -28,27 +28,29 @@ rshd.exe all: $(TARGETS) -bins: $(BINS) -libs: $(LIBS) -rshd.exe: rshd.c Makefile +rshd_unstripped.exe: rshd.c Makefile $(CC) -o $@ $< $(ALLFLAGS) $(LDFLAGS) -rshd-stripped.exe: rshd.exe - $(TARGET)-strip $< -o $@ +rshd.exe: rshd_unstripped.exe + $(STRIP) $< -o $@ -tester.exe: tester.c Makefile +tester_unstripped.exe: tester.c Makefile $(CC) -o $@ $< $(ALLFLAGS) -tester-stripped.exe: tester.exe +tester.exe: tester_unstripped.exe $(TARGET)-strip $< -o $@ -download: rshd-stripped.exe tester-stripped.exe - pcp rshd-stripped.exe ":/rshd.exe" - pcp tester-stripped.exe ":/tester.exe" +download: download-rshd download-tester +download-rshd: rshd.exe + pcp $< ":/rshd.exe" + +download-tester: tester.exe + pcp $< ":/tester.exe" + clean: - rm -f $(BINS) $(STRIPPED_BINS) $(LIBS) + rm -f $(OBJECTS) $(BINS) $(UNSTRIPPED_BINS) dist: srcdist bindist @@ -73,4 +75,4 @@ $(TAR) $(TARFLAGS)cf $(distdir)-bin$(TARFILEEXT) $(distdir) -.PHONY: all install download clean dist bindist srcdist +.PHONY: all install download download-rshd download-tester clean dist bindist srcdist Modified: trunk/cegcc/tools/rshd/TODO =================================================================== --- trunk/cegcc/tools/rshd/TODO 2007-06-24 22:58:14 UTC (rev 1003) +++ trunk/cegcc/tools/rshd/TODO 2007-06-24 23:40:06 UTC (rev 1004) @@ -1,8 +1,3 @@ -- Handle/test/pass child command line args. - -- What should be done with stdin echo? Should we do it, or not? Need - to test against a real rshd server see what happens there. - - autotoolize. - Write a proper README.txt file. Modified: trunk/cegcc/tools/rshd/rshd.c =================================================================== --- trunk/cegcc/tools/rshd/rshd.c 2007-06-24 22:58:14 UTC (rev 1003) +++ trunk/cegcc/tools/rshd/rshd.c 2007-06-24 23:40:06 UTC (rev 1004) @@ -34,6 +34,10 @@ #include <PipeLib.h> +/* from coredll.dll */ +extern BOOL GetStdioPathW (int, wchar_t*, DWORD*); +extern BOOL SetStdioPathW (int, const wchar_t*); + #ifndef COUNTOF #define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0])) #endif @@ -192,6 +196,19 @@ data->stop = FALSE; } +static BOOL +SafeCloseHandle (HANDLE *h) +{ + if (*h == INVALID_HANDLE_VALUE) + return TRUE; + + if (!CloseHandle (*h)) + return FALSE; + + *h = INVALID_HANDLE_VALUE; + return TRUE; +} + #if 0 /* check if hostname is in users .rhost file */ static int @@ -239,10 +256,6 @@ addref_data (data); - /* We don't need the reading side. */ - CloseHandle (data->readh[0]); - data->readh[0] = INVALID_HANDLE_VALUE; - while (!data->stop) { int read = 0; @@ -274,27 +287,29 @@ if (read) { - int written; DWORD dwwritten; - -#if 1 - /* echo data back ... */ - written = send (data->sockfd, buf, read, 0); - if (written < 0) - logprintf ("%s: write ERROR, winerr %d\n", - thread_name, - GetLastError ()); - else if (written < read) - logprintf ("%s: ERROR only wrote %d of %d bytes\n", - thread_name, written, read); -#endif - - /* ... and stuff it into the child's stdin. */ + /* Stuff it into the child's stdin. */ if (!WriteFile (data->writeh[0], buf, read, &dwwritten, NULL)) { logprintf ("%s: broken pipe (2)\n", thread_name); break; } + else + { + /* We can't close the reading side of the pipe until the + child opens its version. Since it will only be open on the + first stdin access, we have to wait until the write side + returns something - which means the child opened stdin. */ + SafeCloseHandle (&data->readh[0]); + } + + if (debug) + { + printf ("0: (%d)", read); + fflush (stdout); + write (fileno (stdout), buf, read); + printf ("\n"); + } } } @@ -320,14 +335,13 @@ logprintf ("%s: broken pipe\n", thread_name); break; } - else if (data->writeh[1] != INVALID_HANDLE_VALUE) + else { /* We can't close the write side of the pipe until the child opens its version. Since it will only be open on the first stdout access, we have to wait until the read side returns something - which means the child opened stdout. */ - CloseHandle (data->writeh[1]); - data->writeh[1] = INVALID_HANDLE_VALUE; + SafeCloseHandle (&data->writeh[1]); } if (read) { @@ -339,6 +353,14 @@ else if ((DWORD) written < read) logprintf ("%s: ERROR only wrote %d of %d bytes\n", thread_name, written, read); + + if (debug) + { + printf ("1: (%u)", (unsigned)read); + fflush (stdout); + write (fileno (stdout), buf, read); + printf ("\n"); + } } } @@ -372,14 +394,13 @@ logprintf ("%s: broken pipe\n", thread_name); break; } - else if (data->writeh[2] != INVALID_HANDLE_VALUE) + else { /* We can't close the write side of the pipe until the child opens its version. Since it will only be open on the first stderr access, we have to wait until the read side returns something - which means the child opened stderr. */ - CloseHandle (data->writeh[2]); - data->writeh[2] = INVALID_HANDLE_VALUE; + SafeCloseHandle (&data->writeh[2]); } if (read) { @@ -391,6 +412,14 @@ else if ((DWORD) written < read) logprintf ("%s: ERROR only wrote %d of %d bytes\n", thread_name, written, read); + + if (debug) + { + printf ("2: (%u)", (unsigned) read); + fflush (stdout); + write (fileno (stdout), buf, read); + printf ("\n"); + } } } @@ -410,15 +439,15 @@ /* Start a new process. Returns the new process' handle on success, NULL on failure. */ static HANDLE -create_child (char *program, HANDLE *readh, HANDLE *writeh) +create_child (char *program, HANDLE *readh, HANDLE *writeh, PROCESS_INFORMATION *pi) { BOOL ret; char *args; int argslen; - PROCESS_INFORMATION pi; wchar_t *wargs, *wprogram; wchar_t prev_path[3][MAX_PATH]; size_t i; + DWORD flags; if (program == NULL || program[0] == '\0') { @@ -456,17 +485,17 @@ GetStdioPathW (i, prev_path[i], &dwLen); SetStdioPathW (i, devname); } - + flags = CREATE_SUSPENDED; ret = CreateProcessW (wprogram, /* image name */ wargs, /* command line */ NULL, /* security, not supported */ NULL, /* thread, not supported */ FALSE, /* inherit handles, not supported */ - 0, /* start flags */ + flags, /* start flags */ NULL, /* environment, not supported */ NULL, /* current directory, not supported */ NULL, /* start info, not supported */ - &pi); /* proc info */ + pi); /* proc info */ for (i = 0; i < 3; i++) SetStdioPathW (i, prev_path[i]); @@ -479,18 +508,15 @@ for (i = 0; i < 3; i++) { - CloseHandle (readh[i]); - CloseHandle (writeh[i]); + SafeCloseHandle (&readh[i]); + SafeCloseHandle (&writeh[i]); } return NULL; } else logprintf ("Process created: %s\n", program); - CloseHandle (pi.hThread); - pi.hThread = NULL; - - return pi.hProcess; + return pi->hProcess; } static int @@ -524,7 +550,7 @@ } } -int +static int connect_stderr (int in, unsigned short stderr_port) { int s; @@ -572,6 +598,7 @@ static WINAPI DWORD handle_connection (void *arg) { + PROCESS_INFORMATION pi = { 0 }; int s2 = (int) arg; /* sizeof (void*) == sizeof (int) */ int stderrsockfd = -1; unsigned short stderr_port = 0; @@ -590,7 +617,7 @@ HANDLE waith[4]; HANDLE hndproc; - DWORD tid[3]; + DWORD stopped; size_t i; int enabled = 1; /* int disabled = 0; */ @@ -734,7 +761,7 @@ send (s2, "", 1, 0); logprintf ("handle_connection: starting command... \n"); - hndproc = create_child (command, client_data->readh, client_data->writeh); + hndproc = create_child (command, client_data->readh, client_data->writeh, &pi); if (!hndproc) { logprintf ("handle_connection: ERROR can't create child process, " @@ -745,34 +772,96 @@ client_data->sockfd = s2; client_data->stderrsockfd = stderrsockfd; - waith[0] = CreateThread (NULL, 0, stdin_thread, client_data, 0, &tid[0]); - waith[1] = CreateThread (NULL, 0, stdout_thread, client_data, 0, &tid[1]); - waith[2] = CreateThread (NULL, 0, stderr_thread, client_data, 0, &tid[2]); + waith[0] = CreateThread (NULL, 0, stdin_thread, client_data, 0, NULL); + waith[1] = CreateThread (NULL, 0, stdout_thread, client_data, 0, NULL); + waith[2] = CreateThread (NULL, 0, stderr_thread, client_data, 0, NULL); waith[3] = hndproc; - switch (WaitForMultipleObjects (COUNTOF (waith), waith, FALSE, INFINITE)) + ResumeThread (pi.hThread); + CloseHandle (pi.hThread); + pi.hThread = NULL; + + /* Wait for stdin/stdout/stderr to close before exiting. */ + + i = 0; + stopped = 0; + + /* Wait for the three threads (stdin/stdout/stderr) to finish. */ + while (i < 3) { - case WAIT_OBJECT_0: - case WAIT_OBJECT_0 + 1: - case WAIT_OBJECT_0 + 2: - TerminateProcess (hndproc, 0); - break; - case WAIT_OBJECT_0 + 3: - break; - default: - logprintf ("WaitForMultipleObjects' default reached\n"); - break; + DWORD waitCount = COUNTOF (waith) - stopped; + DWORD w; + w = WaitForMultipleObjects (waitCount, waith, FALSE, INFINITE); + if (WAIT_OBJECT_0 <= w && w < WAIT_OBJECT_0 + waitCount) + { + DWORD j = w - WAIT_OBJECT_0; + HANDLE h = waith[j]; + + /* Let's not wait for this handle again. */ + CloseHandle (waith[j]); + for (;j < COUNTOF (waith) - 1; j++) + waith[j] = waith[j + 1]; + waith[COUNTOF (waith) - 1] = INVALID_HANDLE_VALUE; + + stopped++; + + if (h == hndproc && stopped < COUNTOF (waith)) + { + int k; + + /* The child died without ever opening it's side + of the pipe, so our threads didn't see it close, + because we never closed our side. */ + + /* Tell the threads we are stopping. */ + client_data->stop = 1; + + /* Close them now. */ + for (k = 0; k < 3; k++) + { + SafeCloseHandle (&client_data->writeh[k]); + SafeCloseHandle (&client_data->readh[k]); + } + + /* Also close the sockets. At least stdin + will be frequenly blocked in a recv call. */ + if (s2 != -1) + { + shutdown (s2, 2); + closesocket (s2); + s2 = -1; + client_data->sockfd = -1; + } + + if (stderrsockfd != -1) + { + shutdown (stderrsockfd, 2); + closesocket (stderrsockfd); + client_data->stderrsockfd = -1; + } + } + else if (h != hndproc) + i++; + } + else + { + logprintf ("WaitForMultipleObjects' default reached with %d : %u\n", + w, (unsigned)GetLastError ()); + goto break_wait_loop; + } } - client_data->stop = TRUE; + logprintf ("all threads gone\n"); - for (i = 0; i < 4; i++) - CloseHandle (waith[i]); + break_wait_loop: + for (i = 0; i < COUNTOF (waith); i++) + SafeCloseHandle (&waith[i]); + for (i = 0; i < 3; i++) { - CloseHandle (client_data->writeh[i]); - CloseHandle (client_data->readh[i]); + SafeCloseHandle (&client_data->writeh[i]); + SafeCloseHandle (&client_data->readh[i]); } shutdown: @@ -781,14 +870,21 @@ ntohs (client_data->sin.sin_port)); /* close sockets */ - shutdown (s2, 2); - closesocket (s2); + if (s2 != -1) + { + shutdown (s2, 2); + closesocket (s2); + } + if (stderrsockfd != -1) { shutdown (stderrsockfd, 2); closesocket (stderrsockfd); } + if (pi.hThread != NULL) + CloseHandle (pi.hThread); + release_data (client_data); /* maybe we should wait for all the still alive threads again? */ Modified: trunk/cegcc/tools/rshd/tester.c =================================================================== --- trunk/cegcc/tools/rshd/tester.c 2007-06-24 22:58:14 UTC (rev 1003) +++ trunk/cegcc/tools/rshd/tester.c 2007-06-24 23:40:06 UTC (rev 1004) @@ -3,23 +3,16 @@ int main () { - int counter = 0; int i; for (i = 0; i < 3; i++) { - printf ("counter = %d\n", counter++); - Sleep (300); - } - - for (i = 0; i < 3; i++) - { int num; - printf ("write a num:"); + printf ("write a num: "); + fflush (stdout); scanf ("%d", &num); printf ("written = %d\n", num); } printf ("exiting\n"); - Sleep (3000); return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-24 22:58:15
|
Revision: 1003 http://svn.sourceforge.net/cegcc/?rev=1003&view=rev Author: pedroalves Date: 2007-06-24 15:58:14 -0700 (Sun, 24 Jun 2007) Log Message: ----------- * conformtest.c: New file. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Added Paths: ----------- trunk/cegcc/tools/PipeLib/conformtest.c Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-24 22:53:21 UTC (rev 1002) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-24 22:58:14 UTC (rev 1003) @@ -1,4 +1,8 @@ 2007-06-24 Pedro Alves <ped...@po...> + + * conformtest.c: New file. + +2007-06-24 Pedro Alves <ped...@po...> Make PipeLib closer to desktop Windows Pipes. * PipeDev/Makefile (STRIP): New. Added: trunk/cegcc/tools/PipeLib/conformtest.c =================================================================== --- trunk/cegcc/tools/PipeLib/conformtest.c (rev 0) +++ trunk/cegcc/tools/PipeLib/conformtest.c 2007-06-24 22:58:14 UTC (rev 1003) @@ -0,0 +1,171 @@ +/* The plan is to evolve this file into some sort of conformance test. + The test should be performed on 9X/NT, and the results matched to + PipeLib. Currently the #if 0 parts were tested manually. They should + be moved into threads and WaitForSingleObject calls with timeouts, or + something. */ + +#include <windows.h> +#include <stdio.h> + +#ifndef COUNTOF +#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0])) +#endif + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char * +strwinerror (DWORD error) +{ + static char buf[1024]; + wchar_t *msgbuf; + DWORD lasterr = GetLastError (); + DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) + { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' + && msgbuf[chars - 1] == '\n') + { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > ((COUNTOF (buf)) - 1)) + { + chars = COUNTOF (buf) - 1; + msgbuf [chars] = 0; + } + + sprintf (buf, "(%ld) %ls", error, msgbuf); + LocalFree (msgbuf); + } + else + sprintf (buf, "unknown win32 error (%ld)", error); + + SetLastError (lasterr); + return buf; +} + +static DWORD WINAPI +close_handle (HANDLE arg) +{ + + Sleep (3000); + printf ("closing handle\n"); + CloseHandle (arg); + + return 0; +} + +int main () +{ + DWORD written; + DWORD read; + const char str[] = "hello1\n"; + char buf[512]; + + HANDLE readh, writeh; + if (!CreatePipe (&readh, &writeh, NULL, 0)) + { + printf ("CreatePipe failed : %s\n", strwinerror (GetLastError ())); + return 1; + } + +#if 0 + CloseHandle (writeh); + + if (!ReadFile (readh, buf, 1, &read, FALSE)) + { + /* ERROR_BROKEN_PIPE */ + printf ("ReadFile: broken pipe? : %s\n", strwinerror (GetLastError ())); + return 3; + } +#endif + +#if 0 + CloseHandle (readh); + + if (!WriteFile (writeh, str, sizeof (str) - 1, &written, NULL)) + { + /* ERROR_NO_DATA */ + printf ("broken pipe? %s\n", strwinerror (GetLastError ())); + return 2; + } +#endif + +#if 0 + HANDLE thread = CreateThread (NULL, 0, close_handle, writeh, 0, NULL); + CloseHandle (thread); + + if (!ReadFile (readh, buf, 1, &read, FALSE)) + { + /* ERROR_BROKEN_PIPE */ + printf ("broken pipe : %s\n", strwinerror (GetLastError ())); + return 3; + } +#endif + +#if 1 + HANDLE thread = CreateThread (NULL, 0, close_handle, readh, 0, NULL); + CloseHandle (thread); + + DWORD count = 0; + while (1) + { + if (!WriteFile (writeh, str, sizeof (str) - 1, &written, NULL)) + { + /* ERROR_NO_DATA */ + printf ("broken pipe? %s\n", strwinerror (GetLastError ())); + return 2; + } + count += written; + /* Checking if WriteFile returns if *something* was written, or + if it always wait for flushing the buffer. */ + + /* I see that Windows return ERROR_NO_DATA, and reports that + sizeof (str) - 1 was written. I don't think we can do + that with WinCE. */ + if (1 || count % 100 == 0) + { + printf ("count = %d\n", count); + fflush (stdout); + } + } +#endif + + if (!ReadFile (readh, buf, sizeof (buf), &read, FALSE)) + { + printf ("broken pipe? : %s\n", strwinerror (GetLastError ())); + return 4; + } + + fwrite (buf, 1, read, stdout); + fflush (stdout); + + if (!ReadFile (readh, buf, sizeof (buf), &read, FALSE)) + { + printf ("broken pipe? : %s\n", strwinerror (GetLastError ())); + return 4; + } + + fwrite (buf, 1, read, stdout); + fflush (stdout); + + return 0; +} Property changes on: trunk/cegcc/tools/PipeLib/conformtest.c ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |