2015-06-18 01:33:55 +01:00
|
|
|
/*************************************************************************
|
|
|
|
* *
|
|
|
|
* YAP Prolog *
|
|
|
|
* *
|
|
|
|
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
|
|
|
* *
|
|
|
|
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
|
|
|
* *
|
|
|
|
**************************************************************************
|
|
|
|
* *
|
|
|
|
* File: iopreds.c *
|
|
|
|
* Last rev: 5/2/88 *
|
|
|
|
* mods: *
|
|
|
|
* comments: Input/Output C implemented predicates *
|
|
|
|
* *
|
|
|
|
*************************************************************************/
|
|
|
|
#ifdef SCCS
|
|
|
|
static char SccsId[] = "%W% %G%";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file includes the definition of a miscellania of standard predicates
|
2016-02-29 03:13:23 +00:00
|
|
|
* for yap refering to: Files and GLOBAL_Streams, Simple Input/Output,
|
2015-06-18 01:33:55 +01:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-01-31 10:37:41 +00:00
|
|
|
#include "sysbits.h"
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
#if _MSC_VER || defined(__MINGW32__)
|
2015-06-18 01:33:55 +01:00
|
|
|
#define SYSTEM_STAT _stat
|
|
|
|
#else
|
|
|
|
#define SYSTEM_STAT stat
|
|
|
|
#endif
|
|
|
|
|
2016-08-29 23:35:01 +01:00
|
|
|
bool Yap_GetFileName(Term t, char *buf, size_t len, encoding_t enc) {
|
|
|
|
while (IsApplTerm(t) && FunctorOfTerm(t) == FunctorSlash) {
|
|
|
|
if (!Yap_GetFileName(ArgOfTerm(1, t), buf, len, enc))
|
|
|
|
return false;
|
|
|
|
size_t szl = strlen(buf);
|
|
|
|
buf += szl;
|
|
|
|
*buf++ = '/';
|
|
|
|
t = ArgOfTerm(2, t);
|
|
|
|
len -= (szl + 1);
|
|
|
|
}
|
|
|
|
return Yap_TextTermToText(t, buf, len, enc);
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int file_name_extension(USES_REGS1) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Term t1 = Deref(ARG1);
|
|
|
|
Term t2 = Deref(ARG2);
|
|
|
|
Term t3 = Deref(ARG3);
|
2016-08-29 23:35:01 +01:00
|
|
|
char f[YAP_FILENAME_MAX + 1];
|
|
|
|
#if __APPLE__ || _WIN32
|
|
|
|
bool lowcase = true;
|
|
|
|
#endif
|
|
|
|
|
2015-06-18 01:33:55 +01:00
|
|
|
if (!IsVarTerm((t3))) {
|
2016-08-29 23:35:01 +01:00
|
|
|
char *f2;
|
|
|
|
if (!Yap_GetFileName(t3, f, YAP_FILENAME_MAX, ENC_ISO_UTF8)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
char *pts = strrchr(f, '/');
|
2016-04-10 14:21:17 +01:00
|
|
|
#if WIN32_
|
2015-06-18 01:33:55 +01:00
|
|
|
char *pts1 = strrchr(f, '\\');
|
2016-02-29 03:13:23 +00:00
|
|
|
if (pts11 > pts)
|
|
|
|
pts = pts1;
|
2015-06-18 01:33:55 +01:00
|
|
|
#endif
|
|
|
|
char *ss = strrchr(f, '.');
|
2016-08-29 23:35:01 +01:00
|
|
|
if (pts > ss) {
|
|
|
|
ss = f + strlen(f);
|
2016-08-30 14:26:14 +01:00
|
|
|
} else if (ss == NULL) {
|
|
|
|
ss = "";
|
|
|
|
} else {
|
2016-08-29 23:35:01 +01:00
|
|
|
ss++;
|
2016-08-30 14:26:14 +01:00
|
|
|
}
|
2016-08-29 23:35:01 +01:00
|
|
|
if (IsVarTerm(t2)) {
|
|
|
|
Term t = Yap_MkTextTerm(ss, ENC_ISO_UTF8, t3);
|
|
|
|
Yap_unify(t2, t);
|
2015-06-18 01:33:55 +01:00
|
|
|
} else {
|
2016-08-29 23:35:01 +01:00
|
|
|
f2 = ss + (strlen(ss) + 1);
|
|
|
|
if (!Yap_TextTermToText(t2, f2, YAP_FILENAME_MAX - 1 - (f2 - f),
|
|
|
|
ENC_ISO_UTF8))
|
|
|
|
return false;
|
|
|
|
#if __APPLE__ || _WIN32
|
|
|
|
Yap_OverwriteUTF8BufferToLowCase(f2);
|
|
|
|
lowcase = true;
|
|
|
|
#endif
|
|
|
|
if (strcmp(f2, ss) != 0 && (ss > f && strcmp(f2, ss - 1) != 0)) {
|
2016-02-29 03:13:23 +00:00
|
|
|
return false;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
}
|
2016-08-30 14:26:14 +01:00
|
|
|
if (f[0] && ss[0] && ss[0] != '.') {
|
2016-08-29 23:35:01 +01:00
|
|
|
ss[-1] = '\0';
|
|
|
|
}
|
2015-06-18 01:33:55 +01:00
|
|
|
if (IsVarTerm(t1)) {
|
2016-08-29 23:35:01 +01:00
|
|
|
Term t = Yap_MkTextTerm(f, ENC_ISO_UTF8, t3);
|
|
|
|
Yap_unify(t1, t);
|
|
|
|
} else {
|
|
|
|
char f1[YAP_FILENAME_MAX + 1];
|
|
|
|
#if __APPLE || _WIN32
|
|
|
|
Yap_OverwriteUTF8BufferToLowCase(f);
|
|
|
|
#endif
|
|
|
|
if (!Yap_GetFileName(t2, f1, YAP_FILENAME_MAX, ENC_ISO_UTF8))
|
|
|
|
return false;
|
|
|
|
#if __APPLE__ || _WIN32
|
|
|
|
if (!lowcase)
|
|
|
|
Yap_OverwriteUTF8BufferToLowCase(f2);
|
|
|
|
#endif
|
|
|
|
if (strcmp(f1, f) != 0) {
|
2016-02-29 03:13:23 +00:00
|
|
|
return false;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-08-29 23:35:01 +01:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
char *f2;
|
|
|
|
if (!Yap_TextTermToText(t1, f, YAP_FILENAME_MAX - 2, ENC_ISO_UTF8)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
return false;
|
|
|
|
}
|
2016-08-29 23:35:01 +01:00
|
|
|
f2 = f + strlen(f);
|
|
|
|
if (!Yap_TextTermToText(t2, f2, YAP_FILENAME_MAX - 2 - (f2 - f),
|
|
|
|
ENC_ISO_UTF8)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
return false;
|
|
|
|
}
|
2016-08-29 23:35:01 +01:00
|
|
|
if (f2[0] != '.') {
|
|
|
|
memmove(f2 + 1, f2, strlen(f2) + 1);
|
|
|
|
f2[0] = '.';
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-08-29 23:35:01 +01:00
|
|
|
Term t = Yap_MkTextTerm(f, ENC_ISO_UTF8, t1);
|
|
|
|
if (!t)
|
|
|
|
return false;
|
|
|
|
return Yap_unify(t, t3);
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int access_path(USES_REGS1) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Term tname = Deref(ARG1);
|
|
|
|
|
|
|
|
if (IsVarTerm(tname)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, tname, "access");
|
2016-04-12 16:04:33 +01:00
|
|
|
return false;
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (!IsAtomTerm(tname)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Yap_Error(TYPE_ERROR_ATOM, tname, "access");
|
2016-04-12 16:04:33 +01:00
|
|
|
return false;
|
2015-06-18 01:33:55 +01:00
|
|
|
} else {
|
|
|
|
#if HAVE_STAT
|
|
|
|
struct SYSTEM_STAT ss;
|
2016-04-12 16:04:33 +01:00
|
|
|
char *file_name;
|
2015-06-18 01:33:55 +01:00
|
|
|
|
|
|
|
file_name = RepAtom(AtomOfTerm(tname))->StrOfAE;
|
|
|
|
if (SYSTEM_STAT(file_name, &ss) != 0) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* ignore errors while checking a file */
|
2016-04-12 16:04:33 +01:00
|
|
|
return true;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-04-12 16:04:33 +01:00
|
|
|
return true;
|
2015-06-18 01:33:55 +01:00
|
|
|
#else
|
2016-04-12 16:04:33 +01:00
|
|
|
return false;
|
2015-06-18 01:33:55 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int exists_file(USES_REGS1) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Term tname = Deref(ARG1);
|
|
|
|
char *file_name;
|
|
|
|
|
|
|
|
if (IsVarTerm(tname)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, tname, "access");
|
|
|
|
return FALSE;
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (!IsAtomTerm(tname)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Yap_Error(TYPE_ERROR_ATOM, tname, "access");
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
#if HAVE_STAT
|
|
|
|
struct SYSTEM_STAT ss;
|
|
|
|
|
|
|
|
file_name = RepAtom(AtomOfTerm(tname))->StrOfAE;
|
|
|
|
if (SYSTEM_STAT(file_name, &ss) != 0) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* ignore errors while checking a file */
|
2015-06-18 01:33:55 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
2016-02-29 03:13:23 +00:00
|
|
|
#if _MSC_VER
|
|
|
|
return ss.st_mode & S_IFREG;
|
2016-02-28 19:32:55 +00:00
|
|
|
#else
|
2016-02-29 03:13:23 +00:00
|
|
|
return S_ISREG(ss.st_mode);
|
2016-02-28 19:32:55 +00:00
|
|
|
#endif
|
2015-06-18 01:33:55 +01:00
|
|
|
#else
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int file_exists(USES_REGS1) {
|
2016-01-04 14:11:09 +00:00
|
|
|
Term tname = Deref(ARG1);
|
|
|
|
char *file_name;
|
|
|
|
|
|
|
|
if (IsVarTerm(tname)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, tname, "access");
|
|
|
|
return FALSE;
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (!IsAtomTerm(tname)) {
|
2016-01-04 14:11:09 +00:00
|
|
|
Yap_Error(TYPE_ERROR_ATOM, tname, "access");
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
#if HAVE_STAT
|
|
|
|
struct SYSTEM_STAT ss;
|
|
|
|
|
|
|
|
file_name = RepAtom(AtomOfTerm(tname))->StrOfAE;
|
|
|
|
if (SYSTEM_STAT(file_name, &ss) != 0) {
|
|
|
|
if (errno == ENOENT)
|
2016-02-29 03:13:23 +00:00
|
|
|
return false;
|
|
|
|
PlIOError(SYSTEM_ERROR_OPERATING_SYSTEM, tname, "error %s",
|
|
|
|
strerror(errno));
|
2016-01-04 14:11:09 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int time_file(USES_REGS1) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Term tname = Deref(ARG1);
|
2016-02-29 03:13:23 +00:00
|
|
|
|
2015-06-18 01:33:55 +01:00
|
|
|
if (IsVarTerm(tname)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, tname, "access");
|
|
|
|
return FALSE;
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (!IsAtomTerm(tname)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Yap_Error(TYPE_ERROR_ATOM, tname, "access");
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
const char *n = RepAtom(AtomOfTerm(tname))->StrOfAE;
|
|
|
|
#if __WIN32
|
2016-01-31 10:37:41 +00:00
|
|
|
FILETIME ft;
|
|
|
|
HANDLE hdl;
|
|
|
|
Term rc;
|
2016-02-29 03:13:23 +00:00
|
|
|
|
2016-04-18 01:09:10 +01:00
|
|
|
if ((hdl = CreateFile(n, 0, 0, NULL, OPEN_EXISTING, 0, 0)) == 0) {
|
|
|
|
Yap_WinError("in time_file");
|
2015-06-18 01:33:55 +01:00
|
|
|
return false;
|
2016-04-18 01:09:10 +01:00
|
|
|
}
|
|
|
|
if (GetFileTime(hdl, NULL, NULL, &ft) == 0) {
|
|
|
|
Yap_WinError("in time_file");
|
2015-06-18 01:33:55 +01:00
|
|
|
return false;
|
2016-04-18 01:09:10 +01:00
|
|
|
}
|
2015-06-18 01:33:55 +01:00
|
|
|
// Convert the last-write time to local time.
|
|
|
|
// FileTimeToSystemTime(&ftWrite, &stUTC);
|
|
|
|
// SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
|
2016-02-29 03:13:23 +00:00
|
|
|
CloseHandle(hdl);
|
|
|
|
ULONGLONG qwResult;
|
|
|
|
|
|
|
|
// Copy the time into a quadword.
|
|
|
|
qwResult = (((ULONGLONG)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
|
|
|
|
#if SIZEOF_INT_P == 8
|
|
|
|
rc = MkIntegerTerm(qwResult);
|
|
|
|
#elif USE_GMP
|
|
|
|
char s[64];
|
|
|
|
MP_INT rop;
|
|
|
|
|
|
|
|
snprintf(s, 64, "%I64d", (long long int)n);
|
|
|
|
mpz_init_set_str(&rop, s, 10);
|
2016-07-31 16:15:55 +01:00
|
|
|
rc = Yap_MkBigIntTerm((void *)&rop PASS_REGS);
|
2016-02-29 03:13:23 +00:00
|
|
|
#else
|
2016-01-31 10:37:41 +00:00
|
|
|
rc = MkIntegerTerm(ft.dwHighDateTime);
|
|
|
|
#endif
|
|
|
|
return Yap_unify(ARG2, rc);
|
2015-06-18 01:33:55 +01:00
|
|
|
#elif HAVE_STAT
|
|
|
|
struct SYSTEM_STAT ss;
|
2016-02-29 03:13:23 +00:00
|
|
|
|
2015-06-18 01:33:55 +01:00
|
|
|
if (SYSTEM_STAT(n, &ss) != 0) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* ignore errors while checking a file */
|
2015-06-18 01:33:55 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return Yap_unify(ARG2, MkIntegerTerm(ss.st_mtime));
|
|
|
|
#else
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int file_size(USES_REGS1) {
|
2015-09-29 23:44:11 +01:00
|
|
|
int rc;
|
2016-02-29 03:13:23 +00:00
|
|
|
Int sno = Yap_CheckStream(
|
|
|
|
ARG1, (Input_Stream_f | Output_Stream_f | Socket_Stream_f),
|
|
|
|
"file_size/2");
|
2015-06-18 01:33:55 +01:00
|
|
|
if (sno < 0)
|
|
|
|
return (FALSE);
|
2016-02-29 03:13:23 +00:00
|
|
|
if (GLOBAL_Stream[sno].status & Seekable_Stream_f &&
|
|
|
|
!(GLOBAL_Stream[sno].status &
|
|
|
|
(InMemory_Stream_f | Socket_Stream_f | Pipe_Stream_f))) {
|
|
|
|
// there
|
|
|
|
struct stat file_stat;
|
|
|
|
if ((rc = fstat(fileno(GLOBAL_Stream[sno].file), &file_stat)) < 0) {
|
|
|
|
UNLOCK(GLOBAL_Stream[sno].streamlock);
|
2015-09-29 23:44:11 +01:00
|
|
|
if (rc == ENOENT)
|
2016-02-29 03:13:23 +00:00
|
|
|
PlIOError(EXISTENCE_ERROR_SOURCE_SINK, ARG1, "%s in file_size",
|
|
|
|
strerror(errno));
|
2015-09-29 23:44:11 +01:00
|
|
|
else
|
2016-02-29 03:13:23 +00:00
|
|
|
PlIOError(PERMISSION_ERROR_INPUT_STREAM, ARG1, "%s in file_size",
|
|
|
|
strerror(errno));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// and back again
|
2015-06-19 10:10:02 +01:00
|
|
|
UNLOCK(GLOBAL_Stream[sno].streamlock);
|
2016-02-29 03:13:23 +00:00
|
|
|
return Yap_unify_constant(ARG2, MkIntegerTerm(file_stat.st_size));
|
|
|
|
}
|
|
|
|
UNLOCK(GLOBAL_Stream[sno].streamlock);
|
2015-06-18 01:33:55 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int access_file(USES_REGS1) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Term tname = Deref(ARG1);
|
|
|
|
Term tmode = Deref(ARG2);
|
2016-02-11 14:15:30 +00:00
|
|
|
char *ares;
|
2015-06-18 01:33:55 +01:00
|
|
|
Atom atmode;
|
|
|
|
|
|
|
|
if (IsVarTerm(tmode)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, tmode, "access_file/2");
|
|
|
|
return FALSE;
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (!IsAtomTerm(tmode)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Yap_Error(TYPE_ERROR_ATOM, tname, "access_file/2");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
atmode = AtomOfTerm(tmode);
|
|
|
|
if (IsVarTerm(tname)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, tname, "access_file/2");
|
|
|
|
return FALSE;
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (!IsAtomTerm(tname)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Yap_Error(TYPE_ERROR_ATOM, tname, "access_file/2");
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
if (atmode == AtomNone)
|
|
|
|
return TRUE;
|
2016-02-29 03:13:23 +00:00
|
|
|
if (!(ares = RepAtom(AtomOfTerm(tname))->StrOfAE))
|
2015-06-18 01:33:55 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#if HAVE_ACCESS
|
2016-02-28 19:32:55 +00:00
|
|
|
#if _WIN32
|
|
|
|
{
|
2016-02-29 03:13:23 +00:00
|
|
|
int mode;
|
|
|
|
|
2016-07-31 16:15:55 +01:00
|
|
|
if (atmode == AtomExist)
|
|
|
|
mode = 00;
|
|
|
|
else if (atmode == AtomExists)
|
|
|
|
mode = 00;
|
2016-02-29 03:13:23 +00:00
|
|
|
else if (atmode == AtomWrite)
|
|
|
|
mode = 02;
|
|
|
|
else if (atmode == AtomRead)
|
|
|
|
mode = 04;
|
|
|
|
else if (atmode == AtomAppend)
|
|
|
|
mode = 03;
|
|
|
|
else if (atmode == AtomCsult)
|
|
|
|
mode = 04;
|
|
|
|
else if (atmode == AtomExecute)
|
|
|
|
mode = 00; // can always execute?
|
|
|
|
else {
|
|
|
|
Yap_Error(DOMAIN_ERROR_IO_MODE, tmode, "access_file/2");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (access(ares, mode) < 0) {
|
|
|
|
/* ignore errors while checking a file */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2016-02-28 19:32:55 +00:00
|
|
|
#else
|
2015-06-18 01:33:55 +01:00
|
|
|
{
|
|
|
|
int mode;
|
|
|
|
|
2016-07-31 16:15:55 +01:00
|
|
|
if (atmode == AtomExist)
|
|
|
|
mode = F_OK;
|
|
|
|
else if (atmode == AtomExists)
|
|
|
|
mode = F_OK;
|
2015-06-18 01:33:55 +01:00
|
|
|
else if (atmode == AtomWrite)
|
|
|
|
mode = W_OK;
|
|
|
|
else if (atmode == AtomRead)
|
|
|
|
mode = R_OK;
|
|
|
|
else if (atmode == AtomAppend)
|
|
|
|
mode = W_OK;
|
|
|
|
else if (atmode == AtomCsult)
|
|
|
|
mode = R_OK;
|
|
|
|
else if (atmode == AtomExecute)
|
|
|
|
mode = X_OK;
|
|
|
|
else {
|
2016-02-11 14:15:30 +00:00
|
|
|
Yap_Error(DOMAIN_ERROR_IO_MODE, tmode, "access_file/2");
|
2016-02-29 03:13:23 +00:00
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
if (access(ares, mode) < 0) {
|
|
|
|
/* ignore errors while checking a file */
|
2016-02-11 14:15:30 +00:00
|
|
|
return false;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-02-11 14:15:30 +00:00
|
|
|
return true;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-02-28 19:32:55 +00:00
|
|
|
#endif
|
2015-06-18 01:33:55 +01:00
|
|
|
#elif HAVE_STAT
|
|
|
|
{
|
|
|
|
struct SYSTEM_STAT ss;
|
|
|
|
|
|
|
|
if (SYSTEM_STAT(ares, &ss) != 0) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* ignore errors while checking a file */
|
2015-06-18 01:33:55 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int exists_directory(USES_REGS1) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Term tname = Deref(ARG1);
|
|
|
|
char *file_name;
|
|
|
|
|
|
|
|
if (IsVarTerm(tname)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, tname, "exists_directory/1");
|
|
|
|
return FALSE;
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (!IsAtomTerm(tname)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
Yap_Error(TYPE_ERROR_ATOM, tname, "exists_directory/1");
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
#if HAVE_STAT
|
|
|
|
struct SYSTEM_STAT ss;
|
|
|
|
|
|
|
|
file_name = RepAtom(AtomOfTerm(tname))->StrOfAE;
|
|
|
|
if (SYSTEM_STAT(file_name, &ss) != 0) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* ignore errors while checking a file */
|
2016-02-11 14:15:30 +00:00
|
|
|
return false;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
return (S_ISDIR(ss.st_mode));
|
|
|
|
#else
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int is_absolute_file_name(USES_REGS1) { /* file_base_name(Stream,N) */
|
2015-06-18 01:33:55 +01:00
|
|
|
Term t = Deref(ARG1);
|
|
|
|
Atom at;
|
2016-05-30 11:24:40 +01:00
|
|
|
bool rc;
|
|
|
|
|
2015-06-18 01:33:55 +01:00
|
|
|
if (IsVarTerm(t)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, t, "file_base_name/2");
|
2016-05-30 11:24:40 +01:00
|
|
|
return false;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-04-10 14:21:17 +01:00
|
|
|
const char *buf = Yap_TextTermToText(t, NULL, 0, LOCAL_encoding);
|
2016-02-13 03:11:25 +00:00
|
|
|
if (buf) {
|
2016-05-30 11:24:40 +01:00
|
|
|
rc = Yap_IsAbsolutePath(buf);
|
2016-02-13 03:11:25 +00:00
|
|
|
} else {
|
|
|
|
at = AtomOfTerm(t);
|
|
|
|
if (IsWideAtom(at)) {
|
2015-06-18 01:33:55 +01:00
|
|
|
#if _WIN32
|
2016-05-30 11:24:40 +01:00
|
|
|
rc = PathIsRelativeW(RepAtom(at)->WStrOfAE);
|
2015-06-18 01:33:55 +01:00
|
|
|
#else
|
2016-05-30 11:24:40 +01:00
|
|
|
rc = RepAtom(at)->WStrOfAE[0] == '/';
|
2015-06-18 01:33:55 +01:00
|
|
|
#endif
|
2016-05-30 11:24:40 +01:00
|
|
|
} else {
|
|
|
|
#if _WIN32
|
|
|
|
rc = PathIsRelative(RepAtom(at)->StrOfAE);
|
|
|
|
#else
|
|
|
|
rc = RepAtom(at)->StrOfAE[0] == '/';
|
2016-07-31 16:15:55 +01:00
|
|
|
#endif
|
2016-02-13 03:11:25 +00:00
|
|
|
}
|
2016-07-31 16:15:55 +01:00
|
|
|
freeBuffer(buf);
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-07-31 16:15:55 +01:00
|
|
|
return rc;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int file_base_name(USES_REGS1) { /* file_base_name(Stream,N) */
|
2015-06-18 01:33:55 +01:00
|
|
|
Term t = Deref(ARG1);
|
|
|
|
Atom at;
|
|
|
|
if (IsVarTerm(t)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, t, "file_base_name/2");
|
2016-02-29 03:13:23 +00:00
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
at = AtomOfTerm(t);
|
|
|
|
if (IsWideAtom(at)) {
|
2016-02-29 03:13:23 +00:00
|
|
|
wchar_t *c = RepAtom(at)->WStrOfAE;
|
|
|
|
Int i = wcslen(c);
|
|
|
|
while (i && !Yap_dir_separator((int)c[--i]))
|
|
|
|
;
|
|
|
|
return Yap_unify(ARG2, MkAtomTerm(Yap_LookupWideAtom(c + i)));
|
2015-06-18 01:33:55 +01:00
|
|
|
} else {
|
2016-02-29 03:13:23 +00:00
|
|
|
const char *c = RepAtom(at)->StrOfAE;
|
|
|
|
const char *s;
|
|
|
|
#if HAVE_BASENAME && 0 // DISABLED: Linux basename is not compatible with
|
|
|
|
// file_base_name in SWI and GNU
|
|
|
|
char c1[YAP_FILENAME_MAX + 1];
|
|
|
|
strncpy(c1, c, YAP_FILENAME_MAX);
|
|
|
|
s = basename(c1);
|
2015-06-18 01:33:55 +01:00
|
|
|
#else
|
2016-02-29 03:13:23 +00:00
|
|
|
Int i = strlen(c);
|
|
|
|
while (i && !Yap_dir_separator((int)c[--i]))
|
|
|
|
;
|
|
|
|
if (Yap_dir_separator((int)c[i])) {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
s = c + i;
|
2015-06-18 01:33:55 +01:00
|
|
|
#endif
|
2016-02-29 03:13:23 +00:00
|
|
|
return Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(s)));
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int file_directory_name(USES_REGS1) { /* file_directory_name(Stream,N) */
|
2015-06-18 01:33:55 +01:00
|
|
|
Term t = Deref(ARG1);
|
|
|
|
Atom at;
|
|
|
|
if (IsVarTerm(t)) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, t, "file_directory_name/2");
|
2016-02-29 03:13:23 +00:00
|
|
|
return false;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
at = AtomOfTerm(t);
|
|
|
|
if (IsWideAtom(at)) {
|
2016-02-29 03:13:23 +00:00
|
|
|
wchar_t s[YAP_FILENAME_MAX + 1];
|
|
|
|
wchar_t *c = RepAtom(at)->WStrOfAE;
|
|
|
|
Int i = wcslen(c);
|
|
|
|
while (i && !Yap_dir_separator((int)c[--i]))
|
|
|
|
;
|
|
|
|
if (Yap_dir_separator((int)c[i])) {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
wcsncpy(s, c, i);
|
|
|
|
return Yap_unify(ARG2, MkAtomTerm(Yap_LookupWideAtom(s)));
|
2015-06-18 01:33:55 +01:00
|
|
|
} else {
|
2016-02-29 03:13:23 +00:00
|
|
|
const char *c = RepAtom(at)->StrOfAE;
|
|
|
|
#if HAVE_BASENAME && 0 // DISABLED: Linux basename is not compatible with
|
|
|
|
// file_base_name in SWI and GNU
|
|
|
|
const char *s;
|
|
|
|
char c1[YAP_FILENAME_MAX + 1];
|
|
|
|
strncpy(c1, c, YAP_FILENAME_MAX);
|
|
|
|
s = dirname(c1);
|
2015-06-18 01:33:55 +01:00
|
|
|
#else
|
2016-02-29 03:13:23 +00:00
|
|
|
char s[YAP_FILENAME_MAX + 1];
|
|
|
|
Int i = strlen(c);
|
2016-04-18 01:09:10 +01:00
|
|
|
strncpy(s, c, YAP_FILENAME_MAX);
|
|
|
|
while (--i) {
|
|
|
|
if (Yap_dir_separator((int)c[i]))
|
2016-07-31 16:15:55 +01:00
|
|
|
break;
|
2016-04-18 01:09:10 +01:00
|
|
|
}
|
2016-02-29 03:13:23 +00:00
|
|
|
s[i] = '\0';
|
2015-06-18 01:33:55 +01:00
|
|
|
#endif
|
2016-02-29 03:13:23 +00:00
|
|
|
return Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(s)));
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
static Int same_file(USES_REGS1) {
|
2015-06-18 01:33:55 +01:00
|
|
|
char *f1 = RepAtom(AtomOfTerm(Deref(ARG1)))->StrOfAE;
|
|
|
|
char *f2 = RepAtom(AtomOfTerm(Deref(ARG2)))->StrOfAE;
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
if (strcmp(f1, f2) == 0)
|
2015-06-18 01:33:55 +01:00
|
|
|
return TRUE;
|
2016-02-29 03:13:23 +00:00
|
|
|
#if HAVE_LSTAT
|
2015-06-18 01:33:55 +01:00
|
|
|
{
|
|
|
|
int out;
|
|
|
|
struct stat *b1, *b2;
|
2016-02-29 03:13:23 +00:00
|
|
|
while ((char *)HR + sizeof(struct stat) * 2 > (char *)(ASP - 1024)) {
|
|
|
|
if (!Yap_gcl(2 * sizeof(struct stat), 2, ENV, Yap_gcP())) {
|
|
|
|
Yap_Error(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
|
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
b1 = (struct stat *)HR;
|
2016-02-29 03:13:23 +00:00
|
|
|
b2 = b1 + 1;
|
|
|
|
if (strcmp(f1, "user_input") == 0) {
|
2015-06-18 01:33:55 +01:00
|
|
|
if (fstat(fileno(GLOBAL_Stream[0].file), b1) == -1) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* file does not exist, but was opened? Return -1 */
|
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (strcmp(f1, "user_output") == 0) {
|
2015-06-18 01:33:55 +01:00
|
|
|
if (fstat(fileno(GLOBAL_Stream[1].file), b1) == -1) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* file does not exist, but was opened? Return -1 */
|
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (strcmp(f1, "user_error") == 0) {
|
2015-06-18 01:33:55 +01:00
|
|
|
if (fstat(fileno(GLOBAL_Stream[2].file), b1) == -1) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* file does not exist, but was opened? Return -1 */
|
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
} else if (stat(f1, b1) == -1) {
|
|
|
|
/* file does not exist, but was opened? Return -1 */
|
|
|
|
return FALSE;
|
|
|
|
}
|
2016-02-29 03:13:23 +00:00
|
|
|
if (strcmp(f2, "user_input") == 0) {
|
2015-06-18 01:33:55 +01:00
|
|
|
if (fstat(fileno(GLOBAL_Stream[0].file), b2) == -1) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* file does not exist, but was opened? Return -1 */
|
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (strcmp(f2, "user_output") == 0) {
|
2015-06-18 01:33:55 +01:00
|
|
|
if (fstat(fileno(GLOBAL_Stream[1].file), b2) == -1) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* file does not exist, but was opened? Return -1 */
|
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
2016-02-29 03:13:23 +00:00
|
|
|
} else if (strcmp(f2, "user_error") == 0) {
|
2015-06-18 01:33:55 +01:00
|
|
|
if (fstat(fileno(GLOBAL_Stream[2].file), b2) == -1) {
|
2016-02-29 03:13:23 +00:00
|
|
|
/* file does not exist, but was opened? Return -1 */
|
|
|
|
return FALSE;
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|
|
|
|
} else if (stat(f2, b2) == -1) {
|
|
|
|
/* file does not exist, but was opened? Return -1 */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
out = (b1->st_ino == b2->st_ino
|
|
|
|
#ifdef __LCC__
|
2016-02-29 03:13:23 +00:00
|
|
|
&&
|
|
|
|
memcmp((const void *)&(b1->st_dev), (const void *)&(b2->st_dev),
|
|
|
|
sizeof(buf1.st_dev)) == 0
|
2015-06-18 01:33:55 +01:00
|
|
|
#else
|
2016-02-29 03:13:23 +00:00
|
|
|
&& b1->st_dev == b2->st_dev
|
2015-06-18 01:33:55 +01:00
|
|
|
#endif
|
2016-02-29 03:13:23 +00:00
|
|
|
);
|
2015-06-18 01:33:55 +01:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
#else
|
2016-02-29 03:13:23 +00:00
|
|
|
return (FALSE);
|
2015-06-18 01:33:55 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-02-29 03:13:23 +00:00
|
|
|
void Yap_InitFiles(void) {
|
|
|
|
Yap_InitCPred("file_base_name", 2, file_base_name, SafePredFlag);
|
|
|
|
Yap_InitCPred("file_directory_name", 2, file_directory_name, SafePredFlag);
|
|
|
|
Yap_InitCPred("is_absolute_file_name", 1, is_absolute_file_name,
|
|
|
|
SafePredFlag);
|
|
|
|
Yap_InitCPred("same_file", 2, same_file, SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("$access_file", 2, access_file, SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("access", 1, access_path, SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("exists_directory", 1, exists_directory,
|
|
|
|
SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("exists_file", 1, exists_file, SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("$file_exists", 1, file_exists, SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("time_file64", 2, time_file, SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("time_file", 2, time_file, SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("file_size", 2, file_size, SafePredFlag | SyncPredFlag);
|
|
|
|
Yap_InitCPred("file_name_extension", 3, file_name_extension,
|
|
|
|
SafePredFlag | SyncPredFlag);
|
2015-06-18 01:33:55 +01:00
|
|
|
}
|