- eliminated a couple of thread-safety issues and limitations on the
sizes of pathnames produced by expansion of tilde (home-directory) prefixes by replacing S_pathname, S_pathname_impl, and S_homedir with S_malloc_pathname, which always mallocs space for the result. one thread-safety issue involved the use of static strings for expanded pathnames and affected various file-system operations. the other affected the file open routines and involved use of the incoming pathname while deactivated. the incoming pathname is sometimes if not always a pointer into a Scheme bytevector, which can be overwritten if a collection occurs while the thread is deactivated. the size limitation corresponded to the use of the static strings, which were limited to PATH_MAX bytes. (PATH_MAX typically isn't actually the maximum path length in contemporary operating systems.) eliminated similar issues for wide pathnames under Windows by adding S_malloc_wide_pathname. consumers of the old routines have been modified to use the new routines and to free the result strings. the various file operations now consistently treat a pathname with an unresolvable home directory as a pathname that happens to start with a tilde. eliminated unused foreign-symbol binding of "(cs)pathname" to S_pathname. io.c, externs.h, new_io.c, prim5.c, scheme.c, prim.c - various places where a call to close or gzclose was retried when the close operation was interrupted no longer do so, since this can cause problems when another thread has reallocated the same file descriptor. new_io.c - now using vcvarsall type x86_amd64 rather than amd64 when the former appears to supported and the latter does not, as is the case with VS Express 2015. c/Mf-a6nt, c/Mf-ta6nt - commented out one of the thread mats that consistently causes indefinite delays under Windows and OpenBSD due to starvation. thread.ms - increased wait time for a couple of subprocess responses 6.ms - added call to collector to close files opened during iconv mats specifically for when mats are run under Windows with no iconv dll. io.ms original commit: ad44924307c576eb2fc92e7958afe8b615a7f48b
This commit is contained in:
parent
8d28c6afb9
commit
b4d452cc71
37
LOG
37
LOG
|
@ -209,3 +209,40 @@
|
|||
c/Mf.*nt
|
||||
- fixed unnessesary blocking in expeditor on Windows.
|
||||
c/expeditor.c
|
||||
- eliminated a couple of thread-safety issues and limitations on the
|
||||
sizes of pathnames produced by expansion of tilde (home-directory)
|
||||
prefixes by replacing S_pathname, S_pathname_impl, and S_homedir
|
||||
with S_malloc_pathname, which always mallocs space for the result.
|
||||
one thread-safety issue involved the use of static strings for expanded
|
||||
pathnames and affected various file-system operations. the other
|
||||
affected the file open routines and involved use of the incoming
|
||||
pathname while deactivated. the incoming pathname is sometimes if not
|
||||
always a pointer into a Scheme bytevector, which can be overwritten if a
|
||||
collection occurs while the thread is deactivated. the size limitation
|
||||
corresponded to the use of the static strings, which were limited to
|
||||
PATH_MAX bytes. (PATH_MAX typically isn't actually the maximum path
|
||||
length in contemporary operating systems.) eliminated similar issues
|
||||
for wide pathnames under Windows by adding S_malloc_wide_pathname.
|
||||
consumers of the old routines have been modified to use the new
|
||||
routines and to free the result strings. the various file operations
|
||||
now consistently treat a pathname with an unresolvable home directory
|
||||
as a pathname that happens to start with a tilde. eliminated unused
|
||||
foreign-symbol binding of "(cs)pathname" to S_pathname.
|
||||
io.c, externs.h, new_io.c, prim5.c, scheme.c, prim.c
|
||||
- various places where a call to close or gzclose was retried when
|
||||
the close operation was interrupted no longer do so, since this can
|
||||
cause problems when another thread has reallocated the same file
|
||||
descriptor.
|
||||
new_io.c
|
||||
- now using vcvarsall type x86_amd64 rather than amd64 when the
|
||||
former appears to supported and the latter does not, as is the
|
||||
case with VS Express 2015.
|
||||
c/Mf-a6nt, c/Mf-ta6nt
|
||||
- commented out one of the thread mats that consistently causes
|
||||
indefinite delays under Windows and OpenBSD due to starvation.
|
||||
thread.ms
|
||||
- increased wait time for a couple of subprocess responses
|
||||
6.ms
|
||||
- added call to collector to close files opened during iconv mats
|
||||
specifically for when mats are run under Windows with no iconv dll.
|
||||
io.ms
|
||||
|
|
|
@ -37,7 +37,10 @@ vs.bat:
|
|||
echo 'set INCLUDE=' >> $@
|
||||
echo 'set LIB=' >> $@
|
||||
echo 'set LIBPATH=' >> $@
|
||||
echo 'call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" amd64' >> $@
|
||||
echo 'set MACHINETYPE=amd64' >> $@
|
||||
echo 'if exist "%VS140COMNTOOLS%..\..\VC\bin\x86_amd64\vcvarsx86_amd64.bat" set MACHINETYPE=x86_amd64' >> $@
|
||||
echo 'if exist "%VS140COMNTOOLS%..\..\VC\bin\vcvars64.bat" set MACHINETYPE=amd64' >> $@
|
||||
echo 'call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %MACHINETYPE%' >> $@
|
||||
echo '%*' >> $@
|
||||
chmod +x $@
|
||||
|
||||
|
|
|
@ -37,7 +37,10 @@ vs.bat:
|
|||
echo 'set INCLUDE=' >> $@
|
||||
echo 'set LIB=' >> $@
|
||||
echo 'set LIBPATH=' >> $@
|
||||
echo 'call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" amd64' >> $@
|
||||
echo 'set MACHINETYPE=amd64' >> $@
|
||||
echo 'if exist "%VS140COMNTOOLS%..\..\VC\bin\x86_amd64\vcvarsx86_amd64.bat" set MACHINETYPE=x86_amd64' >> $@
|
||||
echo 'if exist "%VS140COMNTOOLS%..\..\VC\bin\vcvars64.bat" set MACHINETYPE=amd64' >> $@
|
||||
echo 'call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %MACHINETYPE%' >> $@
|
||||
echo '%*' >> $@
|
||||
chmod +x $@
|
||||
|
||||
|
|
20
c/externs.h
20
c/externs.h
|
@ -149,20 +149,20 @@ extern void S_intern_gensym PROTO((ptr g));
|
|||
extern void S_retrofit_nonprocedure_code PROTO((void));
|
||||
|
||||
/* io.c */
|
||||
extern IBOOL S_file_existsp PROTO((const char *path, IBOOL followp));
|
||||
extern IBOOL S_file_regularp PROTO((const char *path, IBOOL followp));
|
||||
extern IBOOL S_file_directoryp PROTO((const char *path, IBOOL followp));
|
||||
extern IBOOL S_file_symbolic_linkp PROTO((const char *path));
|
||||
extern const char *S_pathname_impl PROTO((const char *inpath, char *buffer));
|
||||
|
||||
extern IBOOL S_file_existsp PROTO((const char *inpath, IBOOL followp));
|
||||
extern IBOOL S_file_regularp PROTO((const char *inpath, IBOOL followp));
|
||||
extern IBOOL S_file_directoryp PROTO((const char *inpath, IBOOL followp));
|
||||
extern IBOOL S_file_symbolic_linkp PROTO((const char *inpath));
|
||||
#ifdef WIN32
|
||||
extern ptr S_find_files PROTO((const char *wildpath));
|
||||
#else
|
||||
extern ptr S_directory_list PROTO((const char *path));
|
||||
extern ptr S_directory_list PROTO((const char *inpath));
|
||||
#endif
|
||||
extern const char *S_homedir PROTO((void));
|
||||
extern const char *S_pathname PROTO((const char *who, const char *inpath, IBOOL errorp, char *buf));
|
||||
extern IBOOL S_fixedpathp PROTO((const char *p));
|
||||
extern char *S_malloc_pathname PROTO((const char *inpath));
|
||||
#ifdef WIN32
|
||||
extern wchar_t *S_malloc_wide_pathname PROTO((const char *inpath));
|
||||
#endif
|
||||
extern IBOOL S_fixedpathp PROTO((const char *inpath));
|
||||
|
||||
/* new-io.c */
|
||||
extern INT S_gzxfile_fd PROTO((ptr x));
|
||||
|
|
287
c/io.c
287
c/io.c
|
@ -33,172 +33,195 @@ static ptr s_wstring_to_bytevector PROTO((const wchar_t *s));
|
|||
static ptr s_string_to_bytevector PROTO((const char *s));
|
||||
#endif
|
||||
|
||||
/* raises an exception if insufficient space cannot be malloc'd.
|
||||
otherwise returns a freshly allocated version of inpath with ~ (home directory)
|
||||
prefix expanded, if possible */
|
||||
char *S_malloc_pathname(const char *inpath) {
|
||||
char *outpath; const char *ip;
|
||||
|
||||
#ifdef WIN32
|
||||
/* Warning: returns pointer to static string */
|
||||
const char *S_homedir() {
|
||||
static char home[PATH_MAX];
|
||||
const char *homedrive = getenv("HOMEDRIVE");
|
||||
const char *homepath = getenv("HOMEPATH");
|
||||
if (*inpath == '~' && (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip))) {
|
||||
const char *homedrive, *homepath; size_t n1, n2, n3;
|
||||
|
||||
if (snprintf(home, PATH_MAX, "%s%s", homedrive, homepath) < PATH_MAX) return home;
|
||||
return NULL;
|
||||
if ((homedrive = getenv("HOMEDRIVE")) != NULL && (homepath = getenv("HOMEPATH")) != NULL) {
|
||||
n1 = strlen(homedrive);
|
||||
n2 = strlen(homepath);
|
||||
n3 = strlen(ip) + 1;
|
||||
if ((outpath = malloc(n1 + n2 + n3)) == NULL) S_error("expand_pathname", "malloc failed");
|
||||
memcpy(outpath, homedrive, n1);
|
||||
memcpy(outpath + n1, homepath, n2);
|
||||
memcpy(outpath + n1 + n2, ip, n3);
|
||||
return outpath;
|
||||
}
|
||||
#else
|
||||
/* Warning: returns pointer to static string */
|
||||
const char *S_homedir() {
|
||||
const char *home;
|
||||
static struct passwd *pwent;
|
||||
|
||||
if ((home = getenv("HOME"))) return home;
|
||||
if ((pwent = getpwuid(getuid()))) return pwent->pw_dir;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *S_pathname_impl(const char *inpath, char *buffer) {
|
||||
if (*inpath != '~') { return inpath; }
|
||||
else {
|
||||
#define setp(c) if (p > buffer + PATH_MAX) return NULL; else *p++ = (c)
|
||||
static char path[PATH_MAX];
|
||||
char *p;
|
||||
const char *ip, *dir;
|
||||
|
||||
if (buffer == NULL) buffer = path;
|
||||
|
||||
ip = inpath + 1;
|
||||
if (*ip == 0 || DIRMARKERP(*ip)) {
|
||||
if (!(dir = S_homedir())) return NULL;
|
||||
#else /* WIN32 */
|
||||
if (*inpath == '~') {
|
||||
const char *dir; size_t n1, n2; struct passwd *pwent;
|
||||
if (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip)) {
|
||||
if ((dir = getenv("HOME")) == NULL)
|
||||
if ((pwent = getpwuid(getuid())) != NULL)
|
||||
dir = pwent->pw_dir;
|
||||
} else {
|
||||
char *userbuf; const char *user_start = ip;
|
||||
do { ip += 1; } while (*ip != 0 && !DIRMARKERP(*ip));
|
||||
if ((userbuf = malloc(ip - user_start + 1)) == NULL) S_error("expand_pathname", "malloc failed");
|
||||
memcpy(userbuf, user_start, ip - user_start);
|
||||
userbuf[ip - user_start] = 0;
|
||||
dir = (pwent = getpwnam(userbuf)) != NULL ? pwent->pw_dir : NULL;
|
||||
free(userbuf);
|
||||
}
|
||||
if (dir != NULL) {
|
||||
n1 = strlen(dir);
|
||||
n2 = strlen(ip) + 1;
|
||||
if ((outpath = malloc(n1 + n2)) == NULL) S_error("expand_pathname", "malloc failed");
|
||||
memcpy(outpath, dir, n1);
|
||||
memcpy(outpath + n1, ip, n2);
|
||||
return outpath;
|
||||
}
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* if no ~ or tilde dir can't be found, copy inpath */
|
||||
{
|
||||
size_t n = strlen(inpath) + 1;
|
||||
outpath = (char *)malloc(n);
|
||||
memcpy(outpath, inpath, n);
|
||||
return outpath;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
return inpath;
|
||||
#else
|
||||
struct passwd *pwent;
|
||||
p = buffer;
|
||||
while (*ip != 0 && !DIRMARKERP(*ip)) setp(*ip++);
|
||||
setp(0);
|
||||
if (!(pwent = getpwnam(buffer)) || !(dir = pwent->pw_dir))
|
||||
/* raises an exception if insufficient space cannot be malloc'd.
|
||||
returns NULL if utf-8 path cannot be converted to wchars.
|
||||
otherwise returns a freshly allocated, wide-character version
|
||||
of inpath with ~ (home directory) prefix expanded, if possible */
|
||||
wchar_t *S_malloc_wide_pathname(const char *inpath) {
|
||||
size_t n; char *path; wchar_t *wpath;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
n = strlen(path) + 1;
|
||||
/* counting on utf-8 representation having at least as many chars as wchar representation */
|
||||
if ((wpath = (wchar_t *)malloc(n * sizeof(wchar_t))) == NULL) {
|
||||
free(path);
|
||||
S_error("expand_pathname", "malloc failed");
|
||||
}
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, (int)n) == 0) {
|
||||
free(path);
|
||||
free(wpath);
|
||||
return NULL;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
p = buffer;
|
||||
while (*dir != 0) setp(*dir++);
|
||||
while (*ip != 0) setp(*ip++);
|
||||
setp(0);
|
||||
return buffer;
|
||||
#undef setp
|
||||
free(path);
|
||||
return wpath;
|
||||
}
|
||||
}
|
||||
|
||||
/* Warning: may return pointer to static string */
|
||||
const char *S_pathname(const char *who, const char *inpath,
|
||||
IBOOL errorp, char *buffer) {
|
||||
const char *path = S_pathname_impl(inpath, buffer);
|
||||
if (path != NULL) return path;
|
||||
if (errorp) S_error1(who, "unable to expand path name ~s", Sstring(inpath));
|
||||
return inpath;
|
||||
}
|
||||
|
||||
IBOOL S_fixedpathp(p) const char *p; {
|
||||
char c;
|
||||
|
||||
p = S_pathname("", p, 0, (char *)0);
|
||||
|
||||
if ((c = *p) == 0 || DIRMARKERP(c)) return 1;
|
||||
if (c == '.')
|
||||
return (c = *++p) == 0
|
||||
|| DIRMARKERP(c)
|
||||
|| (c == '.' && ((c = *++p) == 0 || DIRMARKERP(c)));
|
||||
#ifdef WIN32
|
||||
if (*++p == ':') return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
IBOOL S_fixedpathp(inpath) const char *inpath; {
|
||||
char c; IBOOL res; char *path;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = (c = *path) == 0
|
||||
|| DIRMARKERP(c)
|
||||
#ifdef WIN32
|
||||
|| ((*(path + 1) == ':') && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'))
|
||||
#endif
|
||||
|| ((c == '.')
|
||||
&& ((c = *(path + 1)) == 0
|
||||
|| DIRMARKERP(c)
|
||||
|| (c == '.' && ((c = *(path + 2)) == 0 || DIRMARKERP(c)))));
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
IBOOL S_file_existsp(path, followp) const char *path; IBOOL followp; {
|
||||
IBOOL S_file_existsp(inpath, followp) const char *inpath; IBOOL followp; {
|
||||
#ifdef WIN32
|
||||
wchar_t wpath[PATH_MAX];
|
||||
wchar_t *wpath; IBOOL res;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
|
||||
path = S_pathname("file-exists?", path, 1, (char *)0);
|
||||
if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0)
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
return 0;
|
||||
|
||||
return GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata);
|
||||
} else {
|
||||
res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata);
|
||||
free(wpath);
|
||||
return res;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
struct STATBUF statbuf;
|
||||
const char *expandedpath = S_pathname("file-exists?", path, 0, (char *)0);
|
||||
struct STATBUF statbuf; char *path; IBOOL res;
|
||||
|
||||
return (followp ?
|
||||
STAT(expandedpath, &statbuf) :
|
||||
LSTAT(expandedpath, &statbuf)) == 0;
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0;
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
IBOOL S_file_regularp(path, followp) const char *path; IBOOL followp; {
|
||||
IBOOL S_file_regularp(inpath, followp) const char *inpath; IBOOL followp; {
|
||||
#ifdef WIN32
|
||||
wchar_t wpath[PATH_MAX];
|
||||
wchar_t *wpath; IBOOL res;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
|
||||
path = S_pathname("file-regular?", path, 1, (char *)0);
|
||||
if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0)
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
return 0;
|
||||
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata))
|
||||
return 0;
|
||||
|
||||
return (filedata.dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == 0;
|
||||
} else {
|
||||
res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)
|
||||
&& (filedata.dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == 0;
|
||||
free(wpath);
|
||||
return res;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
struct STATBUF statbuf;
|
||||
const char *expandedpath = S_pathname("file-regular?", path, 0, (char *)0);
|
||||
struct STATBUF statbuf; char *path; IBOOL res;
|
||||
|
||||
return (followp ?
|
||||
STAT(expandedpath, &statbuf) :
|
||||
LSTAT(expandedpath, &statbuf)) == 0
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0
|
||||
&& (statbuf.st_mode & S_IFMT) == S_IFREG;
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
IBOOL S_file_directoryp(path, followp) const char *path; IBOOL followp; {
|
||||
IBOOL S_file_directoryp(inpath, followp) const char *inpath; IBOOL followp; {
|
||||
#ifdef WIN32
|
||||
wchar_t wpath[PATH_MAX];
|
||||
wchar_t *wpath; IBOOL res;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
|
||||
path = S_pathname("file-directory?", path, 1, (char *)0);
|
||||
if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0)
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
return 0;
|
||||
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata))
|
||||
return 0;
|
||||
|
||||
return filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
} else {
|
||||
res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)
|
||||
&& filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
free(wpath);
|
||||
return res;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
struct STATBUF statbuf;
|
||||
const char *expandedpath = S_pathname("file-directory?", path, 0, (char *)0);
|
||||
struct STATBUF statbuf; char *path; IBOOL res;
|
||||
|
||||
return (followp ?
|
||||
STAT(expandedpath, &statbuf) :
|
||||
LSTAT(expandedpath, &statbuf)) == 0
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0
|
||||
&& (statbuf.st_mode & S_IFMT) == S_IFDIR;
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
IBOOL S_file_symbolic_linkp(const char *path) {
|
||||
IBOOL S_file_symbolic_linkp(const char *inpath) {
|
||||
#ifdef WIN32
|
||||
wchar_t wpath[PATH_MAX];
|
||||
wchar_t *wpath; IBOOL res;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
|
||||
path = S_pathname("file-symbolic-link?", path, 1, (char *)0);
|
||||
if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0)
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
return 0;
|
||||
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata))
|
||||
return 0;
|
||||
|
||||
return filedata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
} else {
|
||||
res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)
|
||||
&& filedata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
free(wpath);
|
||||
return res;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
struct STATBUF statbuf;
|
||||
const char *expandedpath = S_pathname("file-symbolic-link?", path, 0, (char *)0);
|
||||
struct STATBUF statbuf; char *path; IBOOL res;
|
||||
|
||||
return (LSTAT(expandedpath, &statbuf) == 0)
|
||||
&& (statbuf.st_mode & S_IFMT) == S_IFLNK;
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = LSTAT(path, &statbuf) == 0 && (statbuf.st_mode & S_IFMT) == S_IFLNK;
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
|
@ -213,22 +236,23 @@ static ptr s_wstring_to_bytevector(const wchar_t *s) {
|
|||
}
|
||||
|
||||
ptr S_find_files(const char *wildpath) {
|
||||
wchar_t wwildpath[PATH_MAX];
|
||||
wchar_t *wwildpath;
|
||||
intptr_t handle;
|
||||
struct _wfinddata_t fileinfo;
|
||||
|
||||
wildpath = S_pathname("directory-list", wildpath, 1, (char *)0);
|
||||
if (MultiByteToWideChar(CP_UTF8,0,wildpath,-1,wwildpath,PATH_MAX) == 0)
|
||||
if ((wwildpath = S_malloc_wide_pathname(wildpath)) == NULL)
|
||||
return S_LastErrorString();
|
||||
|
||||
if ((handle = _wfindfirst(wwildpath, &fileinfo)) == (intptr_t)-1)
|
||||
if ((handle = _wfindfirst(wwildpath, &fileinfo)) == (intptr_t)-1) {
|
||||
free(wwildpath);
|
||||
return S_strerror(errno);
|
||||
else {
|
||||
} else {
|
||||
ptr ls = Snil;
|
||||
do {
|
||||
ls = Scons(s_wstring_to_bytevector(fileinfo.name), ls);
|
||||
} while (_wfindnext(handle, &fileinfo) == 0);
|
||||
_findclose(handle);
|
||||
free(wwildpath);
|
||||
return ls;
|
||||
}
|
||||
}
|
||||
|
@ -241,18 +265,21 @@ static ptr s_string_to_bytevector(const char *s) {
|
|||
return bv;
|
||||
}
|
||||
|
||||
ptr S_directory_list(const char *path) {
|
||||
DIR *dirp; struct dirent *dep; ptr ls = Snil;
|
||||
ptr S_directory_list(const char *inpath) {
|
||||
char *path; DIR *dirp;
|
||||
|
||||
path = S_pathname("directory-list", path, 1, (char *)0);
|
||||
|
||||
if ((dirp = opendir(path)) == (DIR *)0)
|
||||
path = S_malloc_pathname(inpath);
|
||||
if ((dirp = opendir(path)) == (DIR *)0) {
|
||||
free(path);
|
||||
return S_strerror(errno);
|
||||
} else {
|
||||
struct dirent *dep; ptr ls = Snil;
|
||||
|
||||
while ((dep = readdir(dirp)) != (struct dirent *)0)
|
||||
ls = Scons(s_string_to_bytevector(dep->d_name), ls);
|
||||
|
||||
closedir(dirp);
|
||||
free(path);
|
||||
return ls;
|
||||
}
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
|
80
c/new-io.c
80
c/new-io.c
|
@ -56,14 +56,36 @@ static INT lockfile PROTO((INT fd));
|
|||
static ptr make_gzxfile PROTO((int fd, gzFile file));
|
||||
|
||||
/*
|
||||
check: whether you want gzerror to be called on fd
|
||||
(i.e. whether to double check if errors reported by 'ok' are real)
|
||||
not_ok_is_fatal: !ok definitely implies error, so ignore gzerror
|
||||
ok: whether the result of body seems to be ok
|
||||
flag: will be set when an error is detected and cleared if no error
|
||||
fd: the gzFile object to call gzerror on
|
||||
body: the operation we are checking the error on
|
||||
*/
|
||||
#ifdef EINTR
|
||||
/* like FD_EINTR_GUARD and GZ_EINTR_GUARD but ignores EINTR.
|
||||
used for calls to close so we don't close a file descriptor that
|
||||
might already have been reallocated by a different thread */
|
||||
#define FD_GUARD(ok,flag,body) \
|
||||
do { body; \
|
||||
flag = !(ok) && errno != EINTR; \
|
||||
} while (0)
|
||||
#define GZ_GUARD(not_ok_is_fatal,ok,flag,fd,body) \
|
||||
do { body; \
|
||||
if (ok) { flag = 0; } \
|
||||
else { \
|
||||
INT errnum; \
|
||||
gzerror((fd),&errnum); \
|
||||
gzclearerr((fd)); \
|
||||
if (errnum == Z_ERRNO) { \
|
||||
flag = errno != EINTR; \
|
||||
} else { \
|
||||
flag = not_ok_is_fatal || errnum != Z_OK; \
|
||||
errno = 0; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
/* like FD_GUARD and GZ_GUARD but spins on EINTR */
|
||||
#define FD_EINTR_GUARD(ok,flag,body) \
|
||||
do { body; \
|
||||
if (ok) { flag = 0; break; } \
|
||||
|
@ -86,8 +108,8 @@ static ptr make_gzxfile PROTO((int fd, gzFile file));
|
|||
} \
|
||||
} while (1)
|
||||
#else /* EINTR */
|
||||
#define FD_EINTR_GUARD(ok,flag,body) do { body; flag = !(ok); } while (0)
|
||||
#define GZ_EINTR_GUARD(not_ok_is_fatal,ok,flag,fd,body) \
|
||||
#define FD_GUARD(ok,flag,body) do { body; flag = !(ok); } while (0)
|
||||
#define GZ_GUARD(not_ok_is_fatal,ok,flag,fd,body) \
|
||||
do { body; \
|
||||
if (ok) { flag = 0; } \
|
||||
else { \
|
||||
|
@ -101,6 +123,8 @@ static ptr make_gzxfile PROTO((int fd, gzFile file));
|
|||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#define FD_EINTR_GUARD FD_GUARD
|
||||
#define GZ_EINTR_GUARD GZ_GUARD
|
||||
#endif /* EINTR */
|
||||
|
||||
#ifndef O_BINARY
|
||||
|
@ -140,7 +164,8 @@ gzFile S_gzxfile_gzfile(ptr x) {
|
|||
return gzxfile_gzfile(x);
|
||||
}
|
||||
|
||||
ptr S_new_open_input_fd(const char *filename, IBOOL compressed) {
|
||||
ptr S_new_open_input_fd(const char *infilename, IBOOL compressed) {
|
||||
char *filename;
|
||||
INT saved_errno = 0;
|
||||
INT fd, dupfd, error, result, ok, flag;
|
||||
gzFile file;
|
||||
|
@ -148,15 +173,17 @@ ptr S_new_open_input_fd(const char *filename, IBOOL compressed) {
|
|||
ptr tc = get_thread_context();
|
||||
#endif
|
||||
|
||||
if ((filename = S_pathname_impl(filename, NULL)) == NULL) {
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), Sstring("failed to expand path name"));
|
||||
}
|
||||
filename = S_malloc_pathname(infilename);
|
||||
|
||||
/* NB: don't use infilename, which might point into a Scheme string, after this point */
|
||||
DEACTIVATE(tc)
|
||||
FD_EINTR_GUARD(fd>=0, error, fd=OPEN(filename,O_BINARY|O_RDONLY,0));
|
||||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
|
||||
/* NB: don't use free'd filename after this point */
|
||||
free(filename);
|
||||
|
||||
if (error) {
|
||||
ptr str = S_strerror(saved_errno);
|
||||
switch (saved_errno) {
|
||||
|
@ -175,13 +202,13 @@ ptr S_new_open_input_fd(const char *filename, IBOOL compressed) {
|
|||
|
||||
if ((dupfd = DUP(fd)) == -1) {
|
||||
ptr str = S_strerror(errno);
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), str);
|
||||
}
|
||||
|
||||
if ((file = gzdopen(dupfd, "rb")) == Z_NULL) {
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(dupfd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(dupfd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), Sstring("unable to allocate compression state (too many open files?)"));
|
||||
}
|
||||
|
||||
|
@ -190,15 +217,15 @@ ptr S_new_open_input_fd(const char *filename, IBOOL compressed) {
|
|||
REACTIVATE(tc)
|
||||
|
||||
if (compressed) {
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
/* box indicates gzip'd */
|
||||
return Sbox(make_gzxfile(dupfd, file));
|
||||
}
|
||||
|
||||
GZ_EINTR_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = gzclose(file));
|
||||
GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = gzclose(file));
|
||||
if (flag) {} /* make the compiler happy */
|
||||
if (LSEEK(fd, 0, SEEK_SET) != 0) { /* gzdirect does not leave fd at position 0 */
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER),Sstring("unable to reset after reading header bytes"));
|
||||
}
|
||||
return MAKE_FD(fd);
|
||||
|
@ -216,7 +243,7 @@ ptr S_compress_input_fd(INT fd, I64 pos) {
|
|||
}
|
||||
|
||||
if ((file = gzdopen(dupfd, "rb")) == Z_NULL) {
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(dupfd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(dupfd));
|
||||
return Sstring("unable to allocate compression state (too many open files?)");
|
||||
}
|
||||
|
||||
|
@ -225,12 +252,12 @@ ptr S_compress_input_fd(INT fd, I64 pos) {
|
|||
REACTIVATE(tc)
|
||||
|
||||
if (compressed) {
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
if (error) {} /* make the compiler happy */
|
||||
return Sbox(make_gzxfile(dupfd, file));
|
||||
}
|
||||
|
||||
GZ_EINTR_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = gzclose(file));
|
||||
GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = gzclose(file));
|
||||
if (flag) {} /* make the compiler happy */
|
||||
if (LSEEK(fd, pos, SEEK_SET) != pos) { /* gzdirect does not leave fd at same position */
|
||||
return Sstring("unable to reset after reading header bytes");
|
||||
|
@ -253,9 +280,10 @@ ptr S_compress_output_fd(INT fd) {
|
|||
}
|
||||
|
||||
static ptr new_open_output_fd_helper(
|
||||
const char *filename, INT mode, INT flags,
|
||||
const char *infilename, INT mode, INT flags,
|
||||
IBOOL no_create, IBOOL no_fail, IBOOL no_truncate,
|
||||
IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed) {
|
||||
char *filename;
|
||||
INT saved_errno = 0;
|
||||
iptr error;
|
||||
INT fd, result;
|
||||
|
@ -269,9 +297,7 @@ static ptr new_open_output_fd_helper(
|
|||
(no_truncate ? 0 : O_TRUNC) |
|
||||
((!append) ? 0 : O_APPEND);
|
||||
|
||||
if ((filename = S_pathname_impl(filename, NULL)) == NULL) {
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), Sstring("failed to expand path name"));
|
||||
}
|
||||
filename = S_malloc_pathname(infilename);
|
||||
|
||||
if (replace && UNLINK(filename) != 0 && errno != ENOENT) {
|
||||
ptr str = S_strerror(errno);
|
||||
|
@ -283,11 +309,15 @@ static ptr new_open_output_fd_helper(
|
|||
}
|
||||
}
|
||||
|
||||
/* NB: don't use infilename, which might point into a Scheme string, after this point */
|
||||
DEACTIVATE(tc)
|
||||
FD_EINTR_GUARD(fd >= 0, error, fd = OPEN(filename, flags, mode));
|
||||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
|
||||
/* NB: don't use free'd filename after this point */
|
||||
free(filename);
|
||||
|
||||
if (error) {
|
||||
ptr str = S_strerror(saved_errno);
|
||||
switch (saved_errno) {
|
||||
|
@ -308,7 +338,7 @@ static ptr new_open_output_fd_helper(
|
|||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
if (error) {
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), S_strerror(saved_errno));
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +349,7 @@ static ptr new_open_output_fd_helper(
|
|||
|
||||
gzFile file = gzdopen(fd, append ? "ab" : "wb");
|
||||
if (file == Z_NULL) {
|
||||
FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), Sstring("unable to allocate compression state"));
|
||||
}
|
||||
|
||||
|
@ -367,10 +397,10 @@ ptr S_close_fd(ptr file, IBOOL gzflag) {
|
|||
/* NOTE: close automatically releases locks so we don't to call unlock*/
|
||||
DEACTIVATE(tc)
|
||||
if (!gzflag) {
|
||||
FD_EINTR_GUARD(ok == 0, flag, ok = CLOSE(fd));
|
||||
FD_GUARD(ok == 0, flag, ok = CLOSE(fd));
|
||||
} else {
|
||||
/* zlib 1.2.1 returns Z_BUF_ERROR when closing an empty file opened for reading */
|
||||
GZ_EINTR_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, gzfile, ok = gzclose(gzfile));
|
||||
GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, gzfile, ok = gzclose(gzfile));
|
||||
}
|
||||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
|
|
1
c/prim.c
1
c/prim.c
|
@ -164,7 +164,6 @@ void S_prim_init() {
|
|||
create_c_entry_vector();
|
||||
|
||||
Sforeign_symbol("(cs)fixedpathp", (void *)S_fixedpathp);
|
||||
Sforeign_symbol("(cs)pathname", (void *)S_pathname);
|
||||
Sforeign_symbol("(cs)bytes_allocated", (void *)S_compute_bytes_allocated);
|
||||
Sforeign_symbol("(cs)curmembytes", (void *)S_curmembytes);
|
||||
Sforeign_symbol("(cs)maxmembytes", (void *)S_maxmembytes);
|
||||
|
|
225
c/prim5.c
225
c/prim5.c
|
@ -48,7 +48,7 @@ static ptr sorted_chunk_list PROTO((void));
|
|||
static void s_showalloc PROTO((IBOOL show_dump, const char *outfn));
|
||||
static ptr s_system PROTO((const char *s));
|
||||
static ptr s_process PROTO((char *s, IBOOL stderrp));
|
||||
static I32 s_chdir PROTO((const char *s));
|
||||
static I32 s_chdir PROTO((const char *inpath));
|
||||
static char *s_getwd PROTO((void));
|
||||
static ptr s_set_code_byte PROTO((ptr p, ptr n, ptr x));
|
||||
static ptr s_set_code_word PROTO((ptr p, ptr n, ptr x));
|
||||
|
@ -68,15 +68,15 @@ static ptr s_intern PROTO((ptr x));
|
|||
static ptr s_intern2 PROTO((ptr x, ptr n));
|
||||
static ptr s_strings_to_gensym PROTO((ptr pname_str, ptr uname_str));
|
||||
static ptr s_intern3 PROTO((ptr x, ptr n, ptr m));
|
||||
static ptr s_delete_file PROTO((const char *path));
|
||||
static ptr s_delete_directory PROTO((const char *path));
|
||||
static ptr s_rename_file PROTO((const char *path1, const char *path2));
|
||||
static ptr s_mkdir PROTO((const char *path, INT mode));
|
||||
static ptr s_chmod PROTO((const char *path, INT mode));
|
||||
static ptr s_getmod PROTO((const char *path, IBOOL followp));
|
||||
static ptr s_path_atime PROTO((const char *path, IBOOL followp));
|
||||
static ptr s_path_ctime PROTO((const char *path, IBOOL followp));
|
||||
static ptr s_path_mtime PROTO((const char *path, IBOOL followp));
|
||||
static ptr s_delete_file PROTO((const char *inpath));
|
||||
static ptr s_delete_directory PROTO((const char *inpath));
|
||||
static ptr s_rename_file PROTO((const char *inpath1, const char *inpath2));
|
||||
static ptr s_mkdir PROTO((const char *inpath, INT mode));
|
||||
static ptr s_chmod PROTO((const char *inpath, INT mode));
|
||||
static ptr s_getmod PROTO((const char *inpath, IBOOL followp));
|
||||
static ptr s_path_atime PROTO((const char *inpath, IBOOL followp));
|
||||
static ptr s_path_ctime PROTO((const char *inpath, IBOOL followp));
|
||||
static ptr s_path_mtime PROTO((const char *inpath, IBOOL followp));
|
||||
static ptr s_fd_atime PROTO((INT fd));
|
||||
static ptr s_fd_ctime PROTO((INT fd));
|
||||
static ptr s_fd_mtime PROTO((INT fd));
|
||||
|
@ -773,16 +773,18 @@ static ptr s_process(s, stderrp) char *s; IBOOL stderrp; {
|
|||
return LIST3(FIX(ifd), FIX(ofd), FIX(child));
|
||||
}
|
||||
|
||||
static I32 s_chdir(const char *s) {
|
||||
|
||||
#ifdef EINTR
|
||||
static I32 s_chdir(const char *inpath) {
|
||||
char *path;
|
||||
I32 status;
|
||||
|
||||
while ((status = CHDIR(S_pathname("current-directory", s, 1, (char *)0))) != 0 && errno == EINTR) ;
|
||||
return status;
|
||||
path = S_malloc_pathname(inpath);
|
||||
#ifdef EINTR
|
||||
while ((status = CHDIR(path)) != 0 && errno == EINTR) ;
|
||||
#else /* EINTR */
|
||||
return CHDIR(S_pathname("current-directory", s, 1, (char *)0));
|
||||
status = CHDIR(path);
|
||||
#endif /* EINTR */
|
||||
free(path);
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef GETWD
|
||||
|
@ -931,162 +933,203 @@ static ptr s_strings_to_gensym(ptr pname_str, ptr uname_str) {
|
|||
pname_str, uname_str);
|
||||
}
|
||||
|
||||
static ptr s_mkdir(const char *path, INT mode) {
|
||||
INT status;
|
||||
const char *expandedpath = S_pathname("mkdir", path, 1, (char *)0);
|
||||
static ptr s_mkdir(const char *inpath, INT mode) {
|
||||
INT status; ptr res; char *path;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
#ifdef WIN32
|
||||
status = S_windows_mkdir(expandedpath);
|
||||
status = S_windows_mkdir(path);
|
||||
#else /* WIN32 */
|
||||
status = mkdir(expandedpath, mode);
|
||||
status = mkdir(path, mode);
|
||||
#endif /* WIN32 */
|
||||
|
||||
return status == 0 ? Strue : S_strerror(errno);
|
||||
res = status == 0 ? Strue : S_strerror(errno);
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ptr s_delete_file(const char *path) {
|
||||
const char *extendedpath = S_pathname("delete-file", path, 1, (char *)0);
|
||||
return UNLINK(extendedpath) == 0 ? Strue : S_strerror(errno);
|
||||
static ptr s_delete_file(const char *inpath) {
|
||||
ptr res; char *path;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = UNLINK(path) == 0 ? Strue : S_strerror(errno);
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ptr s_delete_directory(const char *path) {
|
||||
const char *extendedpath = S_pathname("delete-directory", path, 1, (char *)0);
|
||||
return RMDIR(extendedpath) == 0 ? Strue : S_strerror(errno);
|
||||
static ptr s_delete_directory(const char *inpath) {
|
||||
ptr res; char *path;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = RMDIR(path) == 0 ? Strue : S_strerror(errno);
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ptr s_rename_file(const char *path1, const char *path2) {
|
||||
static char buf[PATH_MAX];
|
||||
const char *extendedpath1 = S_pathname("rename-file", path1, 1, buf);
|
||||
const char *extendedpath2 = S_pathname("rename-file", path2, 1, (char *)0);
|
||||
return RENAME(extendedpath1, extendedpath2) == 0 ? Strue : S_strerror(errno);
|
||||
static ptr s_rename_file(const char *inpath1, const char *inpath2) {
|
||||
ptr res; char *path1, *path2;
|
||||
|
||||
path1 = S_malloc_pathname(inpath1);
|
||||
path2 = S_malloc_pathname(inpath2);
|
||||
res = RENAME(path1, path2) == 0 ? Strue : S_strerror(errno);
|
||||
free(path1);
|
||||
free(path2);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ptr s_chmod(const char *path, INT mode) {
|
||||
INT status;
|
||||
const char *extendedpath = S_pathname("chmod", path, 1, (char *)0);
|
||||
static ptr s_chmod(const char *inpath, INT mode) {
|
||||
ptr res; INT status; char *path;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
#ifdef WIN32
|
||||
/* pathetic approximation: (a) only handles user permissions, (b) doesn't
|
||||
handle execute permissions, (c) windows won't make file not readable */
|
||||
status = CHMOD(extendedpath,
|
||||
status = CHMOD(path,
|
||||
(mode & 0400 ? S_IREAD : 0) |
|
||||
(mode & 0200 ? S_IWRITE : 0));
|
||||
#else /* WIN32 */
|
||||
status = CHMOD(extendedpath, mode);
|
||||
status = CHMOD(path, mode);
|
||||
#endif /* WIN32 */
|
||||
return status == 0 ? Strue : S_strerror(errno);
|
||||
res = status == 0 ? Strue : S_strerror(errno);
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ptr s_getmod(const char *path, IBOOL followp) {
|
||||
struct STATBUF statbuf;
|
||||
const char *extendedpath = S_pathname("get-mode", path, 1, (char *)0);
|
||||
static ptr s_getmod(const char *inpath, IBOOL followp) {
|
||||
ptr res; char *path; struct STATBUF statbuf;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
|
||||
/* according to msdn, user read/write bits are set according to the file's
|
||||
permission mode, and user execute bits are set according to the
|
||||
filename extension. it says nothing about group and other execute bits. */
|
||||
|
||||
if ((followp ? STAT(extendedpath, &statbuf) : LSTAT(extendedpath, &statbuf)) != 0)
|
||||
return S_strerror(errno);
|
||||
|
||||
return FIX(statbuf.st_mode & 07777);
|
||||
if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) {
|
||||
res = S_strerror(errno);
|
||||
} else {
|
||||
res = FIX(statbuf.st_mode & 07777);
|
||||
}
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ptr s_path_atime(const char *path, IBOOL followp) {
|
||||
static ptr s_path_atime(const char *inpath, IBOOL followp) {
|
||||
#ifdef WIN32
|
||||
wchar_t wpath[PATH_MAX];
|
||||
ptr res;
|
||||
wchar_t *wpath;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
__int64 total, sec; int nsec;
|
||||
|
||||
path = S_pathname("file-access-time", path, 1, (char *)0);
|
||||
if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0)
|
||||
return S_LastErrorString();
|
||||
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) {
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
res = S_LastErrorString();
|
||||
} else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) {
|
||||
DWORD err = GetLastError();
|
||||
return err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ?
|
||||
res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ?
|
||||
Sstring("no such file or directory") :
|
||||
S_LastErrorString();
|
||||
}
|
||||
|
||||
} else {
|
||||
total = filedata.ftLastAccessTime.dwHighDateTime;
|
||||
total <<= 32;
|
||||
total |= filedata.ftLastAccessTime.dwLowDateTime;
|
||||
sec = total / 10000000 - 11644473600L;
|
||||
nsec = (total % 10000000) * 100;
|
||||
return Scons(Sinteger64(sec), Sinteger32(nsec));
|
||||
res = Scons(Sinteger64(sec), Sinteger32(nsec));
|
||||
}
|
||||
free(wpath);
|
||||
return res;
|
||||
#else /* WIN32 */
|
||||
ptr res;
|
||||
char *path;
|
||||
struct STATBUF statbuf;
|
||||
const char *extendedpath = S_pathname("file-access-time", path, 1, (char *)0);
|
||||
|
||||
if ((followp ? STAT(extendedpath, &statbuf) : LSTAT(extendedpath, &statbuf)) != 0)
|
||||
return S_strerror(errno);
|
||||
|
||||
return Scons(Sinteger64(SECATIME(statbuf)), Sinteger32(NSECATIME(statbuf)));
|
||||
path = S_malloc_pathname(inpath);
|
||||
if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) {
|
||||
res = S_strerror(errno);
|
||||
} else {
|
||||
res = Scons(Sinteger64(SECATIME(statbuf)), Sinteger32(NSECATIME(statbuf)));
|
||||
}
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
static ptr s_path_ctime(const char *path, IBOOL followp) {
|
||||
static ptr s_path_ctime(const char *inpath, IBOOL followp) {
|
||||
#ifdef WIN32
|
||||
wchar_t wpath[PATH_MAX];
|
||||
ptr res;
|
||||
wchar_t *wpath;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
__int64 total, sec; int nsec;
|
||||
|
||||
path = S_pathname("file-change-time", path, 1, (char *)0);
|
||||
if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0)
|
||||
return S_LastErrorString();
|
||||
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) {
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
res = S_LastErrorString();
|
||||
} else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) {
|
||||
DWORD err = GetLastError();
|
||||
return err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ?
|
||||
res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ?
|
||||
Sstring("no such file or directory") :
|
||||
S_LastErrorString();
|
||||
}
|
||||
|
||||
} else {
|
||||
total = filedata.ftLastWriteTime.dwHighDateTime;
|
||||
total <<= 32;
|
||||
total |= filedata.ftLastWriteTime.dwLowDateTime;
|
||||
sec = total / 10000000 - 11644473600L;
|
||||
nsec = (total % 10000000) * 100;
|
||||
return Scons(Sinteger64(sec), Sinteger32(nsec));
|
||||
res = Scons(Sinteger64(sec), Sinteger32(nsec));
|
||||
}
|
||||
free(wpath);
|
||||
return res;
|
||||
#else /* WIN32 */
|
||||
ptr res;
|
||||
char *path;
|
||||
struct STATBUF statbuf;
|
||||
const char *extendedpath = S_pathname("file-change-time", path, 1, (char *)0);
|
||||
|
||||
if ((followp ? STAT(extendedpath, &statbuf) : LSTAT(extendedpath, &statbuf)) != 0)
|
||||
return S_strerror(errno);
|
||||
|
||||
return Scons(Sinteger64(SECCTIME(statbuf)), Sinteger32(NSECCTIME(statbuf)));
|
||||
path = S_malloc_pathname(inpath);
|
||||
if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) {
|
||||
res = S_strerror(errno);
|
||||
} else {
|
||||
res = Scons(Sinteger64(SECCTIME(statbuf)), Sinteger32(NSECCTIME(statbuf)));
|
||||
}
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
static ptr s_path_mtime(const char *path, IBOOL followp) {
|
||||
static ptr s_path_mtime(const char *inpath, IBOOL followp) {
|
||||
#ifdef WIN32
|
||||
wchar_t wpath[PATH_MAX];
|
||||
ptr res;
|
||||
wchar_t *wpath;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
__int64 total, sec; int nsec;
|
||||
|
||||
path = S_pathname("file-modification-time", path, 1, (char *)0);
|
||||
if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0)
|
||||
return S_LastErrorString();
|
||||
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) {
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
res = S_LastErrorString();
|
||||
} else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) {
|
||||
DWORD err = GetLastError();
|
||||
return err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ?
|
||||
res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ?
|
||||
Sstring("no such file or directory") :
|
||||
S_LastErrorString();
|
||||
}
|
||||
|
||||
} else {
|
||||
total = filedata.ftLastWriteTime.dwHighDateTime;
|
||||
total <<= 32;
|
||||
total |= filedata.ftLastWriteTime.dwLowDateTime;
|
||||
sec = total / 10000000 - 11644473600L;
|
||||
nsec = (total % 10000000) * 100;
|
||||
return Scons(Sinteger64(sec), Sinteger32(nsec));
|
||||
res = Scons(Sinteger64(sec), Sinteger32(nsec));
|
||||
}
|
||||
free(wpath);
|
||||
return res;
|
||||
#else /* WIN32 */
|
||||
ptr res;
|
||||
char *path;
|
||||
struct STATBUF statbuf;
|
||||
const char *extendedpath = S_pathname("file-modification-time", path, 1, (char *)0);
|
||||
|
||||
if ((followp ? STAT(extendedpath, &statbuf) : LSTAT(extendedpath, &statbuf)) != 0)
|
||||
return S_strerror(errno);
|
||||
|
||||
return Scons(Sinteger64(SECMTIME(statbuf)), Sinteger32(NSECMTIME(statbuf)));
|
||||
path = S_malloc_pathname(inpath);
|
||||
if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) {
|
||||
res = S_strerror(errno);
|
||||
} else {
|
||||
res = Scons(Sinteger64(SECMTIME(statbuf)), Sinteger32(NSECMTIME(statbuf)));
|
||||
}
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
|
|
15
c/scheme.c
15
c/scheme.c
|
@ -541,6 +541,7 @@ static IBOOL find_boot(name, ext, errorp) const char *name, *ext; IBOOL errorp;
|
|||
char pathbuf[PATH_MAX], buf[PATH_MAX];
|
||||
uptr n; INT c;
|
||||
const char *path;
|
||||
char *expandedpath;
|
||||
gzFile file;
|
||||
|
||||
if (S_fixedpathp(name)) {
|
||||
|
@ -551,7 +552,12 @@ static IBOOL find_boot(name, ext, errorp) const char *name, *ext; IBOOL errorp;
|
|||
|
||||
path = name;
|
||||
|
||||
if (!(file = gzopen(S_pathname("", path, 0, (char *)0), "rb"))) {
|
||||
expandedpath = S_malloc_pathname(path);
|
||||
file = gzopen(expandedpath, "rb");
|
||||
/* assumption (seemingly true based on a glance at the source code):
|
||||
gzopen doesn't squirrel away a pointer to expandedpath. */
|
||||
free(expandedpath);
|
||||
if (!file) {
|
||||
if (errorp) {
|
||||
fprintf(stderr, "cannot open boot file %s\n", path);
|
||||
S_abnormal_exit();
|
||||
|
@ -621,7 +627,12 @@ static IBOOL find_boot(name, ext, errorp) const char *name, *ext; IBOOL errorp;
|
|||
}
|
||||
}
|
||||
|
||||
if (!(file = gzopen(S_pathname("", path, 0, (char *)0), "rb"))) {
|
||||
expandedpath = S_malloc_pathname(path);
|
||||
file = gzopen(expandedpath, "rb");
|
||||
/* assumption (seemingly true based on a glance at the source code):
|
||||
gzopen doesn't squirrel away a pointer to expandedpath. */
|
||||
free(expandedpath);
|
||||
if (!file) {
|
||||
if (verbose) fprintf(stderr, "trying %s...cannot open\n", path);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -3457,14 +3457,14 @@
|
|||
(begin (display "hello " (cadr p))
|
||||
(flush-output-port (cadr p))
|
||||
#t)
|
||||
(begin (sleep (make-time 'time-duration 0 (if (embedded?) 3 1))) #t) ; wait for subprocess to catch up
|
||||
(begin (sleep (make-time 'time-duration 0 3)) #t) ; wait for subprocess to catch up
|
||||
(char-ready? (car p))
|
||||
(eq? (read (car p)) 'hello)
|
||||
(char-ready? (car p))
|
||||
(char=? (read-char (car p)) #\space)
|
||||
(not (char-ready? (car p)))
|
||||
(begin (close-output-port (cadr p)) #t)
|
||||
(begin (sleep (make-time 'time-duration 0 (if (embedded?) 3 1))) #t) ; wait for subprocess to catch up
|
||||
(begin (sleep (make-time 'time-duration 0 3)) #t) ; wait for subprocess to catch up
|
||||
(sanitized-error? (write-char #\a (cadr p)))
|
||||
(sanitized-error? (write-char #\newline (cadr p)))
|
||||
(sanitized-error? (flush-output-port (cadr p)))
|
||||
|
|
|
@ -1040,6 +1040,11 @@
|
|||
(define op (transcoded-port bp transcoder))
|
||||
(newline op)
|
||||
(close-port op)))
|
||||
; NB: keep this last among the iconv-codec mats
|
||||
; close any files left open by failing iconv tests. this is particulary
|
||||
; important on windows when the iconv dll isn't available and where keeping
|
||||
; file open can prevent it from being reopened.
|
||||
(begin (collect (collect-maximum-generation)) #t)
|
||||
))
|
||||
|
||||
(mat port-operations4
|
||||
|
|
|
@ -1026,7 +1026,15 @@
|
|||
(f (+ i 1))
|
||||
(cons (+ (* i thread-count) j) (g (+ j 1))))))))))
|
||||
($thread-check)
|
||||
(eqv?
|
||||
; this mat has some inherent starvation issues, with the main thread
|
||||
; looping rather than waiting on a condition at initialization time and
|
||||
; other threads looping rather than waiting on a condition when looking
|
||||
; for work to steal. these looping threads can hog the cpu without
|
||||
; doing anything useful, causing progress to stall or halt. this
|
||||
; manifests as occasional indefinite delays under Windows and OpenBSD,
|
||||
; and it has the potential to cause the same on other operating systems.
|
||||
; it's not clear how to fix the mat without changing it fundamentally.
|
||||
#;(eqv?
|
||||
(let () ; from Ryan Newton
|
||||
|
||||
(define-syntax ASSERT
|
||||
|
|
Loading…
Reference in New Issue
Block a user