📄 posixwin.scm
字号:
;;;; posixwin.scm - Miscellaneous file- and process-handling routines, available on Windows;; By Sergey Khorev;; Copyright (c) 2000-2007, Felix L. Winkelmann; Copyright (c) 2008, The Chicken Team; All rights reserved.;; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following; conditions are met:;; Redistributions of source code must retain the above copyright notice, this list of conditions and the following; disclaimer.; 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.; Neither the name of the author nor the names of its contributors may be used to endorse or promote; products derived from this software without specific prior written permission.;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDERS OR; CONTRIBUTORS 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.; Not implemented:;; open/noctty open/nonblock open/fsync open/sync; perm/isvtx perm/isuid perm/isgid; file-select; symbolic-link?; set-signal-mask! signal-mask signal-masked? signal-mask! signal-unmask!; user-information group-information get-groups set-groups! initialize-groups; errno/wouldblock; change-file-owner; current-user-id current-group-id current-effective-user-id current-effective-group-id; current-effective-user-name; set-user-id! set-group-id!; create-session; process-group-id set-process-group-id!; create-symbolic-link read-symbolic-link; file-truncate; file-lock file-lock/blocking file-unlock file-test-lock; create-fifo fifo?; prot/...; map/...; map-file-to-memory unmap-file-from-memory memory-mapped-file-pointer memory-mapped-file?; set-alarm!; terminal-port? terminal-name; process-fork process-wait; parent-process-id; process-signal; Issues;; - Use of a UTF8 encoded string will not work properly. Windows uses a; 16-bit UNICODE character string encoding and specialized system calls; and/or structure settings for the use of such strings.(declare (unit posix) (uses scheduler regex extras utils files) (disable-interrupts) (usual-integrations) (hide ##sys#stat close-handle posix-error $quote-args-list $exec-setup $exec-teardown) (foreign-declare #<<EOF#ifndef WIN32_LEAN_AND_MEAN# define WIN32_LEAN_AND_MEAN#endif/*MinGW should have winsock2.h and ws2tcpip.h as well.The CMake build will set HAVE_WINSOCK2_H and HAVE_WS2TCPIP_H.However, the _MSC_VER test is still needed for vcbuild.bat../configure doesn't test for these. It should, for MinGW.*/#if (_MSC_VER > 1300) || (defined(HAVE_WINSOCK2_H) && defined(HAVE_WS2TCPIP_H))# include <winsock2.h># include <ws2tcpip.h>#else# include <winsock.h>#endif#include <signal.h>#include <errno.h>#include <io.h>#include <stdio.h>#include <process.h>static int C_not_implemented(void);int C_not_implemented() { return -1; }#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <direct.h>#include <time.h>#define ARG_MAX 256#define PIPE_BUF 512#ifndef ENV_MAX# define ENV_MAX 1024#endifstatic C_TLS char *C_exec_args[ ARG_MAX ];static C_TLS char *C_exec_env[ ENV_MAX ];static C_TLS struct group *C_group;static C_TLS int C_pipefds[ 2 ];static C_TLS time_t C_secs;static C_TLS struct tm C_tm;static C_TLS struct stat C_statbuf;/* pipe handles */static C_TLS HANDLE C_rd0, C_wr0, C_wr0_, C_rd1, C_wr1, C_rd1_;static C_TLS HANDLE C_save0, C_save1; /* saved I/O handles */static C_TLS char C_rdbuf; /* one-char buffer for read */static C_TLS int C_exstatus;/* platform information; initialized for cached testing */static C_TLS char C_hostname[256] = "";static C_TLS char C_osver[16] = "";static C_TLS char C_osrel[16] = "";static C_TLS char C_processor[16] = "";static C_TLS char C_shlcmd[256] = "";/* Windows NT or better */static int C_isNT = 0;/* Current user name */static C_TLS TCHAR C_username[255 + 1] = "";/* Directory Operations */#define C_mkdir(str) C_fix(mkdir(C_c_string(str)))#define C_chdir(str) C_fix(chdir(C_c_string(str)))#define C_rmdir(str) C_fix(rmdir(C_c_string(str)))#ifndef __WATCOMC__/* DIRENT stuff */struct dirent{ char * d_name;};typedef struct{ struct _finddata_t fdata; int handle; struct dirent current;} DIR;static DIR * C_fcallopendir(const char *name){ int name_len = strlen(name); DIR *dir = (DIR *)malloc(sizeof(DIR)); char *what; if (!dir) { errno = ENOMEM; return NULL; } what = (char *)malloc(name_len + 3); if (!what) { free(dir); errno = ENOMEM; return NULL; } strcpy(what, name); if (strchr("\\/", name[name_len - 1])) strcat(what, "*"); else strcat(what, "\\*"); dir->handle = _findfirst(what, &dir->fdata); if (dir->handle == -1) { free(what); free(dir); return NULL; } dir->current.d_name = NULL; /* as the first-time indicator */ free(what); return dir;}static int C_fcallclosedir(DIR * dir){ if (dir) { int res = _findclose(dir->handle); free(dir); return res; } return -1;}static struct dirent * C_fcallreaddir(DIR * dir){ if (dir) { if (!dir->current.d_name /* first time after opendir */ || _findnext(dir->handle, &dir->fdata) != -1) { dir->current.d_name = dir->fdata.name; return &dir->current; } } return NULL;}#endif /* ifndef __WATCOMC__ */#ifdef __WATCOMC__# define mktemp _mktemp/* there is no P_DETACH in Watcom CRTL */# define P_DETACH P_NOWAIT#endif#define C_opendir(x,h) C_set_block_item(h, 0, (C_word) opendir(C_c_string(x)))#define C_closedir(h) (closedir((DIR *)C_block_item(h, 0)), C_SCHEME_UNDEFINED)#define C_readdir(h,e) C_set_block_item(e, 0, (C_word) readdir((DIR *)C_block_item(h, 0)))#define C_foundfile(e,b) (strcpy(C_c_string(b), ((struct dirent *) C_block_item(e, 0))->d_name), C_fix(strlen(((struct dirent *) C_block_item(e, 0))->d_name)))#define C_curdir(buf) (getcwd(C_c_string(buf), 256) ? C_fix(strlen(C_c_string(buf))) : C_SCHEME_FALSE)#define open_binary_input_pipe(a, n, name) C_mpointer(a, _popen(C_c_string(name), "r"))#define open_text_input_pipe(a, n, name) open_binary_input_pipe(a, n, name)#define open_binary_output_pipe(a, n, name) C_mpointer(a, _popen(C_c_string(name), "w"))#define open_text_output_pipe(a, n, name) open_binary_output_pipe(a, n, name)#define close_pipe(p) C_fix(_pclose(C_port_file(p)))#define C_set_file_ptr(port, ptr) (C_set_block_item(port, 0, (C_block_item(ptr, 0))), C_SCHEME_UNDEFINED)#define C_getpid getpid#define C_chmod(fn, m) C_fix(chmod(C_data_pointer(fn), C_unfix(m)))#define C_fdopen(a, n, fd, m) C_mpointer(a, fdopen(C_unfix(fd), C_c_string(m)))#define C_C_fileno(p) C_fix(fileno(C_port_file(p)))#define C_dup(x) C_fix(dup(C_unfix(x)))#define C_dup2(x, y) C_fix(dup2(C_unfix(x), C_unfix(y)))#define C_setvbuf(p, m, s) C_fix(setvbuf(C_port_file(p), NULL, C_unfix(m), C_unfix(s)))#define C_access(fn, m) C_fix(access((char *)C_data_pointer(fn), C_unfix(m)))#define C_pipe(d, m) C_fix(_pipe(C_pipefds, PIPE_BUF, C_unfix(m)))#define C_close(fd) C_fix(close(C_unfix(fd)))#define C_getenventry(i) environ[ i ]#define C_putenv(s) C_fix(putenv((char *)C_data_pointer(s)))#define C_stat(fn) C_fix(stat((char *)C_data_pointer(fn), &C_statbuf))#define C_fstat(f) C_fix(fstat(C_unfix(f), &C_statbuf))static C_word C_fcallC_setenv(C_word x, C_word y){ char *sx = C_data_pointer(x), *sy = C_data_pointer(y); int n1 = C_strlen(sx), n2 = C_strlen(sy); char *buf = (char *)C_malloc(n1 + n2 + 2); if (buf == NULL) return(C_fix(0)); else { C_strcpy(buf, sx); buf[ n1 ] = '='; C_strcpy(buf + n1 + 1, sy); return(C_fix(putenv(buf))); }}static void C_fcallC_set_arg_string(char **where, int i, char *dat, int len){ char *ptr; if (dat) { ptr = (char *)C_malloc(len + 1); C_memcpy(ptr, dat, len); ptr[ len ] = '\0'; } else ptr = NULL; where[ i ] = ptr;}static void C_fcallC_free_arg_string(char **where) { while (*where) C_free(*(where++));}#define C_set_exec_arg(i, a, len) C_set_arg_string(C_exec_args, i, a, len)#define C_set_exec_env(i, a, len) C_set_arg_string(C_exec_env, i, a, len)#define C_free_exec_args() (C_free_arg_string(C_exec_args), C_SCHEME_TRUE)#define C_free_exec_env() (C_free_arg_string(C_exec_env), C_SCHEME_TRUE)#define C_execvp(f) C_fix(execvp(C_data_pointer(f), (const char *const *)C_exec_args))#define C_execve(f) C_fix(execve(C_data_pointer(f), (const char *const *)C_exec_args, (const char *const *)C_exec_env))/* MS replacement for the fork-exec pair */#define C_spawnvp(m, f) C_fix(spawnvp(C_unfix(m), C_data_pointer(f), (const char *const *)C_exec_args))#define C_spawnvpe(m, f) C_fix(spawnvpe(C_unfix(m), C_data_pointer(f), (const char *const *)C_exec_args, (const char *const *)C_exec_env))#define C_open(fn, fl, m) C_fix(open(C_c_string(fn), C_unfix(fl), C_unfix(m)))#define C_read(fd, b, n) C_fix(read(C_unfix(fd), C_data_pointer(b), C_unfix(n)))#define C_write(fd, b, n) C_fix(write(C_unfix(fd), C_data_pointer(b), C_unfix(n)))#define C_mkstemp(t) C_fix(mktemp(C_c_string(t)))#define C_ftell(p) C_fix(ftell(C_port_file(p)))#define C_fseek(p, n, w) C_mk_nbool(fseek(C_port_file(p), C_unfix(n), C_unfix(w)))#define C_lseek(fd, o, w) C_fix(lseek(C_unfix(fd), C_unfix(o), C_unfix(w)))#define C_flushall() C_fix(_flushall())#define C_ctime(n) (C_secs = (n), ctime(&C_secs))#define C_tm_set_08(v) \ (memset(&C_tm, 0, sizeof(struct tm)), \ C_tm.tm_sec = C_unfix(C_block_item(v, 0)), \ C_tm.tm_min = C_unfix(C_block_item(v, 1)), \ C_tm.tm_hour = C_unfix(C_block_item(v, 2)), \ C_tm.tm_mday = C_unfix(C_block_item(v, 3)), \ C_tm.tm_mon = C_unfix(C_block_item(v, 4)), \ C_tm.tm_year = C_unfix(C_block_item(v, 5)), \ C_tm.tm_wday = C_unfix(C_block_item(v, 6)), \ C_tm.tm_yday = C_unfix(C_block_item(v, 7)), \ C_tm.tm_isdst = (C_block_item(v, 8) != C_SCHEME_FALSE))#define C_tm_set(v) (C_tm_set_08(v), &C_tm)#define C_asctime(v) (asctime(C_tm_set(v)))#define C_mktime(v) ((C_temporary_flonum = mktime(C_tm_set(v))) != -1)#define TIME_STRING_MAXLENGTH 255static char C_time_string [TIME_STRING_MAXLENGTH + 1];#undef TIME_STRING_MAXLENGTH#define C_strftime(v, f) \ (strftime(C_time_string, sizeof(C_time_string), C_c_string(f), C_tm_set(v)) ? C_time_string : NULL)/* mapping from Win32 error codes to errno*/typedef struct{ DWORD win32; int libc;} errmap_t;static errmap_t errmap[] ={ {ERROR_INVALID_FUNCTION, EINVAL}, {ERROR_FILE_NOT_FOUND, ENOENT}, {ERROR_PATH_NOT_FOUND, ENOENT}, {ERROR_TOO_MANY_OPEN_FILES, EMFILE}, {ERROR_ACCESS_DENIED, EACCES}, {ERROR_INVALID_HANDLE, EBADF}, {ERROR_ARENA_TRASHED, ENOMEM}, {ERROR_NOT_ENOUGH_MEMORY, ENOMEM}, {ERROR_INVALID_BLOCK, ENOMEM}, {ERROR_BAD_ENVIRONMENT, E2BIG}, {ERROR_BAD_FORMAT, ENOEXEC}, {ERROR_INVALID_ACCESS, EINVAL}, {ERROR_INVALID_DATA, EINVAL}, {ERROR_INVALID_DRIVE, ENOENT}, {ERROR_CURRENT_DIRECTORY, EACCES}, {ERROR_NOT_SAME_DEVICE, EXDEV}, {ERROR_NO_MORE_FILES, ENOENT}, {ERROR_LOCK_VIOLATION, EACCES}, {ERROR_BAD_NETPATH, ENOENT}, {ERROR_NETWORK_ACCESS_DENIED, EACCES}, {ERROR_BAD_NET_NAME, ENOENT}, {ERROR_FILE_EXISTS, EEXIST}, {ERROR_CANNOT_MAKE, EACCES}, {ERROR_FAIL_I24, EACCES}, {ERROR_INVALID_PARAMETER, EINVAL}, {ERROR_NO_PROC_SLOTS, EAGAIN}, {ERROR_DRIVE_LOCKED, EACCES}, {ERROR_BROKEN_PIPE, EPIPE}, {ERROR_DISK_FULL, ENOSPC}, {ERROR_INVALID_TARGET_HANDLE, EBADF}, {ERROR_INVALID_HANDLE, EINVAL}, {ERROR_WAIT_NO_CHILDREN, ECHILD}, {ERROR_CHILD_NOT_COMPLETE, ECHILD}, {ERROR_DIRECT_ACCESS_HANDLE, EBADF}, {ERROR_NEGATIVE_SEEK, EINVAL}, {ERROR_SEEK_ON_DEVICE, EACCES}, {ERROR_DIR_NOT_EMPTY, ENOTEMPTY}, {ERROR_NOT_LOCKED, EACCES}, {ERROR_BAD_PATHNAME, ENOENT}, {ERROR_MAX_THRDS_REACHED, EAGAIN},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -