root/trunk/orca/win32/os.c

Revision 411, 9.2 kB (checked in by krobillard, 18 months ago)

Orca - Win32 dir read returns files.

Line 
1/*============================================================================
2    ORCA Interpreter
3    Copyright (C) 2005-2006  Karl Robillard
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18===========================================================================*/
19
20
21#include <windows.h>
22#include <direct.h>
23#include <io.h>
24#include <sys/timeb.h>
25#include <time.h>
26#include "os.h"
27#include "ovalue.h"
28
29
30unsigned long randomSeed()
31{
32    unsigned long seed;
33    seed  = time(NULL);
34    seed += clock();
35    return seed;
36}
37
38
39/**
40  Returns -1 if not present.
41*/
42int orFileSize( const char* path )
43{
44    LARGE_INTEGER lsize;
45    HANDLE fh = CreateFile( path, GENERIC_READ, FILE_SHARE_READ, NULL,
46                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
47    if( fh == INVALID_HANDLE_VALUE)
48        return -1;
49    if( ! GetFileSizeEx( fh, &lsize ) )
50        return -1;
51    CloseHandle( fh );
52    return lsize.LowPart;
53}
54
55
56/**
57  Returns 1 if directory, 0 if file or -1 if error.
58*/
59int orIsDir( const char* path )
60{
61    DWORD attr;
62    attr = GetFileAttributes( path );
63    if( attr == INVALID_FILE_ATTRIBUTES )
64        return -1;
65    return (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
66}
67
68
69/**
70  Returns 0 if result set to file modification time or -1 if error.
71*/
72int orFileModified( const char* path, OValue* res )
73{
74    (void) path;
75    (void) res;
76    /*
77    struct stat buf;
78    if( stat( path, &buf ) == -1 )
79    */
80        return -1;
81
82    /*
83    orSetTF( res, OT_TIME );
84    res->time.sec  = buf.st_mtime;
85    res->time.usec = 0;
86    return 0;
87    */
88}
89
90
91/*
92   change-dir
93*/
94OR_NATIVE_PUB( orChangeDirNative )
95{
96    int logic = 0;
97    OString* str = orSTRING(a1);
98    orTermCStr(str);
99    if( _chdir( str->charArray ) == 0 )
100        logic = 1;
101    orResult( OT_LOGIC, logic );
102}
103
104
105/*
106   what-dir
107*/
108OR_NATIVE_PUB( orWhatDirNative )
109{
110    if( _getcwd( orTmp, OR_TMP_SIZE ) )
111    {
112        int len;
113        OString* str;
114       
115        len = strLen( orTmp );
116        if( len > 0 )
117        {
118            str = orMakeString( len + OR_CTERM_LEN );
119            str->used = len;
120            memCpy( str->charArray, orTmp, len );
121            orResultFILE( orStringN(str) );
122            return;
123        }
124    }
125    orResultFALSE;
126}
127
128
129/*
130  No error if directory exists.
131*/
132OR_NATIVE_PUB( orMakeDirNative )
133{
134    OString* str = orSTRING(a1);
135    orTermCStr(str);
136
137#if 1
138    if( ! CreateDirectory( str->charArray, NULL ) )
139    {
140        DWORD err;
141        err = GetLastError();
142        if( (err != ERROR_FILE_EXISTS) || (orIsDir(str->charArray) != 1) )
143        {
144            orErrorT( OR_ERROR_ACCESS, "CreateDirectory error (%d)", err );
145        }
146    }
147#else
148    int err;
149    err = _mkdir( str->charArray );
150    if( err )
151    {
152        if( (errno != EEXIST) || (orIsDir(str->charArray) != 1) )
153        {
154            orErrorT( OR_ERROR_ACCESS, strerror/*_r*/(errno) );
155        }
156    }
157#endif
158}
159
160
161#define REF_TIME    a1
162
163OR_NATIVE_PUB( orNowNative )
164{
165    struct _timeb tb;
166
167    _ftime( &tb );
168
169    if( orRefineSet( REF_TIME ) )
170        orSetTF( a1, OT_TIME );
171    else
172        orSetTF( a1, OT_DATE );
173    orSeconds(a1) = tb.time + (tb.millitm * 0.001);
174}
175
176
177void orReadDir( OValue* a1, const char* filename )
178{
179    char filespec[ _MAX_PATH ];
180    struct _finddata_t fileinfo;
181    long handle;
182
183    // Look for all files.  We ensure there is a slash before the wildcard.
184    // It's OK if the path is already terminated with a slash - multiple
185    // slashes are filtered by _findfirst.
186
187    strcpy( filespec, filename );
188    strcat( filespec, "\\*.*" );
189
190    handle = _findfirst( filespec, &fileinfo );
191    if( handle != -1 )
192    {
193        OIndex hold;
194        OIndex blkN;
195        OBlock* blk = orMakeBlock( 0 );
196
197        blkN = orBlockN(blk);
198        hold = orHold( OT_BLOCK, blkN );
199
200        do
201        {
202            const char* cp = fileinfo.name;
203            if( cp[0] == '.' && (cp[1] == '.' || cp[1] == '\0') )
204                continue;
205
206            orAppendFile( blk, orMakeCString(fileinfo.name, -1) );
207        }
208        while( _findnext( handle, &fileinfo ) != -1 );
209
210        _findclose( handle );
211
212        orRelease( hold );
213        orResultBLOCK( blkN );
214    }
215    else
216    {
217        orResultFALSE;
218    }
219}
220
221
222#ifdef OR_CONFIG_OS_CALL
223
224#define REF_CALL_OUTPUT     a1+1
225#define REF_CALL_OUT        a1+2
226#define REF_CALL_WAIT       a1+3
227
228
229static void callOutput( OValue* a1 )
230{
231#define BUFSIZE     256
232    OString* str;
233    char* cp;
234    HANDLE childStdOutR;
235    HANDLE childStdOutW;
236    DWORD nr;
237    SECURITY_ATTRIBUTES sec;
238    STARTUPINFO si;
239    PROCESS_INFORMATION pi;
240
241
242    str = orSTRING( a1 );
243    orTermCStr( str );
244    cp  = orStrChars( str, a1 );
245
246
247    sec.nLength              = sizeof(SECURITY_ATTRIBUTES);
248    sec.lpSecurityDescriptor = NULL;
249    sec.bInheritHandle       = TRUE;
250
251    if( ! CreatePipe( &childStdOutR, &childStdOutW, &sec, 0 ) )
252    {
253        orError( "CreatePipe failed\n" );
254        return;
255    }
256
257    SetHandleInformation( childStdOutR, HANDLE_FLAG_INHERIT, 0 );
258
259    ZeroMemory( &si, sizeof(si) );
260    si.cb         = sizeof(si);
261    si.hStdError  = childStdOutW;
262    si.hStdOutput = childStdOutW;
263    si.hStdInput  = NULL;
264    si.dwFlags    = STARTF_USESTDHANDLES;
265
266    ZeroMemory( &pi, sizeof(pi) );
267
268    // Start the child process.
269    if( ! CreateProcess( NULL,   // No module name (use command line).
270        TEXT(cp),         // Command line.
271        NULL,             // Process handle not inheritable.
272        NULL,             // Thread handle not inheritable.
273        TRUE,             // Handle inheritance.
274        DETACHED_PROCESS, // Prevent pop-up of MSDOS windows.
275        NULL,             // Use parent's environment block.
276        NULL,             // Use parent's starting directory.
277        &si,              // Pointer to STARTUPINFO structure.
278        &pi )             // Pointer to PROCESS_INFORMATION structure.
279    )
280    {
281        CloseHandle( childStdOutW );
282        CloseHandle( childStdOutR );
283        orError( "CreateProcess failed (%d).\n", GetLastError() );
284        return;
285    }
286
287    CloseHandle( childStdOutW );
288
289    str = orSTRING(REF_CALL_OUT);
290    str->used = 0;
291    orArrayReserve( str, 1, BUFSIZE );
292
293    while( 1 )
294    {
295        if( ReadFile( childStdOutR, str->charArray + str->used, BUFSIZE,
296                      &nr, NULL ) == 0 )
297        {
298            // GetLastError();
299            break;
300        }
301        if( nr == 0 )
302            break;
303
304        str->used += nr;
305        orArrayReserve( str, 1, str->used + BUFSIZE );
306    }
307
308    // MSDN example does not CloseHandle(childStdOutR);
309
310    {
311    DWORD code;
312
313    // Wait until child process exits.
314    WaitForSingleObject( pi.hProcess, INFINITE );
315
316    if( GetExitCodeProcess( pi.hProcess, &code ) )
317    {
318        orResult( OT_INTEGER, code );
319    }
320    else
321    {
322        orResultNONE;
323    }
324    }
325
326    // Close process and thread handles.
327    CloseHandle( pi.hProcess );
328    CloseHandle( pi.hThread );
329}
330
331
332static void callSimple( OValue* a1 )
333{
334    OString* str;
335    char* cp;
336    STARTUPINFO si;
337    PROCESS_INFORMATION pi;
338
339    str = orSTRING( a1 );
340    orTermCStr( str );
341    cp  = orStrChars( str, a1 );
342
343    ZeroMemory( &si, sizeof(si) );
344    si.cb = sizeof(si);
345
346    ZeroMemory( &pi, sizeof(pi) );
347
348    // Start the child process.
349    if( ! CreateProcess( NULL,   // No module name (use command line).
350        TEXT(cp),         // Command line.
351        NULL,             // Process handle not inheritable.
352        NULL,             // Thread handle not inheritable.
353        FALSE,            // Set handle inheritance to FALSE.
354        0,                // No creation flags.
355        NULL,             // Use parent's environment block.
356        NULL,             // Use parent's starting directory.
357        &si,              // Pointer to STARTUPINFO structure.
358        &pi )             // Pointer to PROCESS_INFORMATION structure.
359    )
360    {
361        orError( "CreateProcess failed (%d).\n", GetLastError() );
362        return;
363    }
364
365    orResultNONE;
366
367    if( orRefineSet(REF_CALL_WAIT) )
368    {
369        DWORD code;
370
371        // Wait until child process exits.
372        WaitForSingleObject( pi.hProcess, INFINITE );
373
374        if( GetExitCodeProcess( pi.hProcess, &code ) )
375        {
376            orResult( OT_INTEGER, code );
377        }
378    }
379
380    // Close process and thread handles.
381    CloseHandle( pi.hProcess );
382    CloseHandle( pi.hThread );
383}
384
385
386OR_NATIVE_PUB( orCallNative )
387{
388    if( a1->type != OT_STRING )
389    {
390        orResultFALSE;
391        return;
392    }
393
394    if( orRefineSet( REF_CALL_OUTPUT ) )
395    {
396        callOutput( a1 );
397    }
398    else
399    {
400        callSimple( a1 );
401    }
402}
403#endif
404
405
406void orInstallExceptionHandlers() {}
407
408
409/*EOF*/
Note: See TracBrowser for help on using the browser.