18static char SccsId[] =
"%W% %G%";
33#include "cwalk/cwalk.h"
46#if defined(__MINGW32__) || _MSC_VER
51static Int file_exists(USES_REGS1) {
52 Term tname = Deref(ARG1);
55 if (IsVarTerm(tname)) {
56 Yap_ThrowError(INSTANTIATION_ERROR, tname,
"access");
57 }
else if (!IsAtomTerm(tname)) {
58 Yap_ThrowError(TYPE_ERROR_ATOM, tname,
"access");
62 struct SYSTEM_STAT ss;
64 file_name = RepAtom(AtomOfTerm(tname))->StrOfAE;
65 if (SYSTEM_STAT(file_name, &ss) != 0) {
68 UnixIOError(errno, CREATE_DIRECTORY, tname,
"error %s", strerror(errno));
78static Int time_file(USES_REGS1) {
79 Term tname = Deref(ARG1);
81 if (IsVarTerm(tname)) {
82 Yap_Error(INSTANTIATION_ERROR, tname,
"access");
84 }
else if (!IsAtomTerm(tname)) {
85 Yap_Error(TYPE_ERROR_ATOM, tname,
"access");
88 const char *n = RepAtom(AtomOfTerm(tname))->StrOfAE;
90 if ((
vfs = vfs_owner(n))) {
93 return Yap_unify(ARG2, MkIntegerTerm(s.st_mtimespec.tv_sec));
100 if ((hdl = CreateFile(n, 0, 0, NULL, OPEN_EXISTING, 0, 0)) == 0) {
101 Yap_WinError(
"in time_file");
104 if (GetFileTime(hdl, NULL, NULL, &ft) == 0) {
105 Yap_WinError(
"in time_file");
115 qwResult = (((ULONGLONG)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
117 rc = MkIntegerTerm(qwResult);
122 snprintf(s, 64,
"%I64d", (
long long int)n);
123 mpz_init_set_str(&rop, s, 10);
124 rc = Yap_MkBigIntTerm((
void *)&rop PASS_REGS);
126 rc = MkIntegerTerm(ft.dwHighDateTime);
128 return Yap_unify(ARG2, rc);
130 struct SYSTEM_STAT ss;
132 if (SYSTEM_STAT(n, &ss) != 0) {
136 return Yap_unify(ARG2, MkIntegerTerm(ss.st_mtime));
149static Int get_time(USES_REGS1) {
154 if (GetSystenTimeAsFileTime(&ft) == 0) {
155 Yap_WinError(
"in time_file");
161 qwResult = (((ULONGLONG)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
163 rc = MkIntegerTerm(qwResult);
168 snprintf(s, 64,
"%I64d", (
long long int)n);
169 mpz_init_set_str(&rop, s, 10);
170 rc = Yap_MkBigIntTerm((
void *)&rop PASS_REGS);
172 rc = MkIntegerTerm(ft.dwHighDateTime);
174 return Yap_unify(ARG1, rc);
175#elif HAVE_GETTIMEOFDAY
177 if (gettimeofday(&tv, NULL) != 0) {
181 return Yap_unify(MkIntegerTerm(tv.tv_sec*1000000+tv.tv_usec),ARG1);
185 if (ftime(&ss) != 0) {
189 return Yap_unify(ARG1, MkIntegerTerm(ss.time));
195static Int file_size(USES_REGS1) {
197 Int sno = Yap_CheckStream(
198 ARG1, (Input_Stream_f | Output_Stream_f | Socket_Stream_f),
203 char *s = RepAtom(GLOBAL_Stream[sno].name)->StrOfAE;
206 if ((
vfs = vfs_owner(s))) {
209 UNLOCK(GLOBAL_Stream[sno].streamlock);
210 return Yap_unify_constant(ARG2, MkIntegerTerm(st.st_size));
212 if (GLOBAL_Stream[sno].status & Seekable_Stream_f &&
213 !(GLOBAL_Stream[sno].status &
214 (InMemory_Stream_f | Socket_Stream_f | Pipe_Stream_f))) {
216 struct stat file_stat;
217 if ((rc = fstat(fileno(GLOBAL_Stream[sno].file), &file_stat)) < 0) {
218 UNLOCK(GLOBAL_Stream[sno].streamlock);
220 PlIOError(EXISTENCE_ERROR_SOURCE_SINK, ARG1,
"%s in file_size",
223 PlIOError(PERMISSION_ERROR_INPUT_STREAM, ARG1,
"%s in file_size",
228 UNLOCK(GLOBAL_Stream[sno].streamlock);
229 return Yap_unify_constant(ARG2, MkIntegerTerm(file_stat.st_size));
231 UNLOCK(GLOBAL_Stream[sno].streamlock);
235static Int lines_in_file(USES_REGS1) {
236 Int sno = Yap_CheckStream(ARG1, (Input_Stream_f),
"lines_in_file/2");
239 FILE *f = GLOBAL_Stream[sno].file;
247 while ((ch = getw(f)) >= 0) {
252 return Yap_unify(ARG2, MkIntegerTerm(count));
255static Int access_file(USES_REGS1) {
256 Term tname = Deref(ARG1);
257 Term tmode = Deref(ARG2);
261 if (IsVarTerm(tmode)) {
262 Yap_Error(INSTANTIATION_ERROR, tmode,
"access_file/2");
264 }
else if (!IsAtomTerm(tmode)) {
265 Yap_Error(TYPE_ERROR_ATOM, tname,
"access_file/2");
268 atmode = AtomOfTerm(tmode);
269 if (IsVarTerm(tname)) {
270 Yap_Error(INSTANTIATION_ERROR, tname,
"access_file/2");
272 }
else if (!IsAtomTerm(tname)) {
273 Yap_Error(TYPE_ERROR_ATOM, tname,
"access_file/2");
276 if (atmode == AtomNone)
278 if (!(ares = RepAtom(AtomOfTerm(tname))->StrOfAE))
282 if ((
vfs = vfs_owner(ares))) {
285 if (atmode == AtomExist)
287 else if (atmode == AtomExists)
289 else if (atmode == AtomWrite)
290 return o.st_mode & VFS_CAN_WRITE;
291 else if (atmode == AtomRead)
292 return o.st_mode & VFS_CAN_READ;
293 else if (atmode == AtomAppend)
294 return o.st_mode & VFS_CAN_WRITE;
295 else if (atmode == AtomCsult)
296 return o.st_mode & VFS_CAN_READ;
297 else if (atmode == AtomExecute)
298 return o.st_mode & VFS_CAN_EXEC;
300 Yap_Error(DOMAIN_ERROR_IO_MODE, tmode,
"access_file/2");
312 if (atmode == AtomExist)
314 else if (atmode == AtomExists)
316 else if (atmode == AtomWrite)
318 else if (atmode == AtomRead)
320 else if (atmode == AtomAppend)
322 else if (atmode == AtomCsult)
324 else if (atmode == AtomExecute)
327 Yap_Error(DOMAIN_ERROR_IO_MODE, tmode,
"access_file/2");
330 if (access(ares, mode) < 0) {
340 if (atmode == AtomExist)
342 else if (atmode == AtomExists)
344 else if (atmode == AtomWrite)
346 else if (atmode == AtomRead)
348 else if (atmode == AtomAppend)
350 else if (atmode == AtomCsult)
352 else if (atmode == AtomExecute)
355 Yap_Error(DOMAIN_ERROR_IO_MODE, tmode,
"access_file/2");
358 if (access(ares, mode) < 0) {
367 struct SYSTEM_STAT ss;
369 if (SYSTEM_STAT(ares, &ss) != 0) {
380static Int exists_directory(USES_REGS1) {
387 if ((
vfs = vfs_owner(s))) {
391 UNLOCK(GLOBAL_Stream[sno].streamlock);
395 struct SYSTEM_STAT ss;
397 if (SYSTEM_STAT(s, &ss) != 0) {
401 return (S_ISDIR(ss.st_mode));
407static Int is_absolute_file_name(USES_REGS1) {
408 Term t = Deref(ARG1);
412 Yap_Error(INSTANTIATION_ERROR, t,
"file_base_name/2");
415 int l = push_text_stack();
416 const char *buf = Yap_TextTermToText(t PASS_REGS);
418 rc = Yap_IsAbsolutePath(buf,
true);
422 rc = PathIsRelative(RepAtom(at)->StrOfAE);
424 rc = RepAtom(at)->StrOfAE[0] ==
'/';
431static Int file_base_name(USES_REGS1) {
432 Term t = Deref(ARG1);
435 Yap_Error(INSTANTIATION_ERROR, t,
"file_base_name/2");
439 const char *c = RepAtom(at)->StrOfAE;
441#if HAVE_BASENAME && 0
443 char c1[MAX_PATH + 1];
444 strncpy(c1, c, MAX_PATH);
448 while (i && !Yap_dir_separator((
int)c[--i]))
450 if (Yap_dir_separator((
int)c[i])) {
455 return Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(s)));
458static Int file_directory_name(USES_REGS1) {
459 Term t = Deref(ARG1);
462 Yap_Error(INSTANTIATION_ERROR, t,
"file_directory_name/2");
466 const char *c = RepAtom(at)->StrOfAE;
467#if HAVE_BASENAME && 0
470 char c1[MAX_PATH + 1];
471 strncpy(c1, c, MAX_PATH);
474 char s[MAX_PATH + 1];
476 strncpy(s, c, MAX_PATH);
478 if (Yap_dir_separator((
int)c[i]))
487 return Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(s)));
496static Int make_directory(USES_REGS1) {
497 int lvl = push_text_stack();
499 Term t = Deref(ARG1);
503 fd0 = RepAtom(AtomOfTerm(t))->StrOfAE;
504 else if (IsStringTerm(t))
505 fd0 = StringOfTerm(t);
509 if (!cwk_path_get_first_segment(fd0, &segment)) {
510 printf(
"Path doesn't have any segments.");
513 char *s =
Malloc(MAX_PATH);
516 if (segment.size == 0)
519cwk_path_get_root(fd0, &sz);
523 strncpy(s+sz,
"/", 2);
526 strncpy(s+sz, segment.begin, segment.size);
529 if (!Yap_isDirectory(s)) {
530#if defined(__MINGW32__) || _MSC_VER
531 if (_mkdir(s) == -1) {
533 UnixIOError(errno, CREATE_DIRECTORY, ARG1,
"mkdir failed to create ",
534 fd, strerror(errno));
537 if (mkdir(s, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) {
539 UnixIOError(errno, CREATE_DIRECTORY, ARG1,
540 "mkdir failed to create %s: %s", s, strerror(errno));
544 }
while (cwk_path_get_next_segment(&segment));
554static Int list_directory(USES_REGS1) {
559 if ((vfsp = vfs_owner(buf))) {
563 if ((de = vfsp->
opendir(vfsp, buf)) == NULL) {
564 PlIOError(PERMISSION_ERROR_INPUT_STREAM, ARG1,
"%s in list_directory",
567 while ((dp = vfsp->
nextdir(de))) {
568 YAP_Term ti = MkAtomTerm(Yap_LookupAtom(dp));
569 tf = MkPairTerm(ti, tf);
573#if defined(__MINGW32__) || _MSC_VER
574 struct _finddata_t c_file;
580 strncpy(bs, buf, BUF_SIZE);
585 strncat(bs,
"/*", BUF_SIZE);
589 if ((hFile = _findfirst(bs, &c_file)) == -1L) {
590 return (Yap_unify(ARG2, tf));
592 Yap_PutInSlot(sl, MkPairTerm(MkAtomTerm(Yap_LookupAtom(c_file.name)),
593 Yap_GetFromSlot(sl)));
594 while (_findnext(hFile, &c_file) == 0) {
595 Term ti = MkAtomTerm(Yap_LookupAtom(c_file.name));
596 Yap_PutInSlot(sl, MkPairTerm(ti, Yap_GetFromSlot(sl)));
604 if ((de = opendir(buf)) == NULL) {
605 PlIOError(PERMISSION_ERROR_INPUT_STREAM, ARG1,
"%s in list_directory",
610 while ((dp = readdir(de))) {
611 Term ti = MkAtomTerm(Yap_LookupAtom(dp->d_name));
612 tf = MkPairTerm(ti, tf);
618 return Yap_unify(ARG2, tf);
621static Int p_rmdir(USES_REGS1) {
622 const char *fd = Yap_VFAlloc(AtomName(AtomOfTerm(ARG1)));
623#if defined(__MINGW32__) || _MSC_VER
624 if (_rmdir(fd) == -1) {
626 if (rmdir(fd) == -1) {
629 return (Yap_unify(ARG2, MkIntTerm(errno)));
634static Int access_path(USES_REGS1) {
635 Term tname = Deref(ARG1);
637 if (IsVarTerm(tname)) {
638 Yap_Error(INSTANTIATION_ERROR, tname,
"access");
640 }
else if (!IsAtomTerm(tname)) {
641 Yap_Error(TYPE_ERROR_ATOM, tname,
"access");
645 char *s = RepAtom(AtomOfTerm(tname))->StrOfAE;
648 if ((
vfs = vfs_owner(s))) {
651 UNLOCK(GLOBAL_Stream[sno].streamlock);
655 struct SYSTEM_STAT ss;
658 file_name = RepAtom(AtomOfTerm(tname))->StrOfAE;
659 if (SYSTEM_STAT(file_name, &ss) != 0) {
670static Int same_file(USES_REGS1) {
671 char *f1 = RepAtom(AtomOfTerm(Deref(ARG1)))->StrOfAE;
672 char *f2 = RepAtom(AtomOfTerm(Deref(ARG2)))->StrOfAE;
674 if (strcmp(f1, f2) == 0)
679 struct stat *b1, *b2;
680 while ((
char *)HR +
sizeof(
struct stat) * 2 > (
char *)(ASP - 1024)) {
682 Yap_Error(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
686 b1 = (
struct stat *)HR;
688 if (strcmp(f1,
"user_input") == 0) {
689 if (fstat(fileno(GLOBAL_Stream[0].file), b1) == -1) {
693 }
else if (strcmp(f1,
"user_output") == 0) {
694 if (fstat(fileno(GLOBAL_Stream[1].file), b1) == -1) {
698 }
else if (strcmp(f1,
"user_error") == 0) {
699 if (fstat(fileno(GLOBAL_Stream[2].file), b1) == -1) {
703 }
else if (stat(f1, b1) == -1) {
707 if (strcmp(f2,
"user_input") == 0) {
708 if (fstat(fileno(GLOBAL_Stream[0].file), b2) == -1) {
712 }
else if (strcmp(f2,
"user_output") == 0) {
713 if (fstat(fileno(GLOBAL_Stream[1].file), b2) == -1) {
717 }
else if (strcmp(f2,
"user_error") == 0) {
718 if (fstat(fileno(GLOBAL_Stream[2].file), b2) == -1) {
722 }
else if (stat(f2, b2) == -1) {
726 out = (b1->st_ino == b2->st_ino
728 && memcmp((
const void *)&(b1->st_dev), (
const void *)&(b2->st_dev),
729 sizeof(buf1.st_dev)) == 0
731 && b1->st_dev == b2->st_dev
741static Int exists_file(USES_REGS1) {
742 Term tname = Deref(ARG1);
743 if (IsVarTerm(tname)) {
744 Yap_Error(TYPE_ERROR_ATOM, tname,
"access");
748 char *s = RepAtom(AtomOfTerm(tname))->StrOfAE;
751 if ((
vfs = vfs_owner(s))) {
754 UNLOCK(GLOBAL_Stream[sno].streamlock);
758 struct SYSTEM_STAT ss;
760 const char *file_name = RepAtom(AtomOfTerm(tname))->StrOfAE;
761 if (SYSTEM_STAT(file_name, &ss) != 0) {
766 return ss.st_mode & S_IFREG;
768 return S_ISREG(ss.st_mode);
776static Int delete_file(USES_REGS1) {
779#if defined(__MINGW32__) || _MSC_VER
780 if (_unlink(fd) == -1)
782 if (unlink(fd) == -1)
786 Yap_ThrowError(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
787 "unlink operation failed with error %s", strerror(errno));
793 static Int is_regular_file(USES_REGS1) {
796#if defined(__MINGW32__) || _MSC_VER
800 if (_stat(fd, &buf) != 0) {
801 return PlIOError(EXISTENCE_ERROR_SOURCE_SINK, ARG1,
"%s while verifyng if %s is a regular file", strerror(errno), fd);
805 if (lstat(fd, &buf) == -1) {
807 return PlIOError(EXISTENCE_ERROR_SOURCE_SINK, ARG1,
"%s while verifyng if %s is a regular file", strerror(errno), fd);
809 return S_ISREG(buf.st_mode);
813void Yap_InitFiles(
void) {
814 Yap_InitCPred(
"file_base_name", 2, file_base_name, SafePredFlag);
815 Yap_InitCPred(
"file_directory_name", 2, file_directory_name, SafePredFlag);
816 Yap_InitCPred(
"is_absolute_file_name", 1, is_absolute_file_name,
818 Yap_InitCPred(
"same_file", 2, same_file, SafePredFlag | SyncPredFlag);
819 Yap_InitCPred(
"$access_file", 2, access_file, SafePredFlag | SyncPredFlag);
820 Yap_InitCPred(
"$lines_in_file", 2, lines_in_file,
821 SafePredFlag | SyncPredFlag);
822 Yap_InitCPred(
"access", 1, access_path, SafePredFlag | SyncPredFlag);
823 Yap_InitCPred(
"exists_directory", 1, exists_directory,
824 SafePredFlag | SyncPredFlag);
825 Yap_InitCPred(
"exists_file", 1, exists_file, SafePredFlag | SyncPredFlag);
826 Yap_InitCPred(
"$file_exists", 1, file_exists, SafePredFlag | SyncPredFlag);
827 Yap_InitCPred(
"time_file64", 2, time_file, SafePredFlag | SyncPredFlag);
828 Yap_InitCPred(
"time_file", 2, time_file, SafePredFlag | SyncPredFlag);
829 Yap_InitCPred(
"file_size", 2, file_size, SafePredFlag | SyncPredFlag);
830 Yap_InitCPred(
"make_directory", 1, make_directory, SyncPredFlag);
831 Yap_InitCPred(
"list_directory", 2, list_directory, SyncPredFlag);
832 Yap_InitCPred(
"directory_files", 2, list_directory, SyncPredFlag);
833 Yap_InitCPred(
"delete_file", 1, delete_file, SyncPredFlag);
834 Yap_InitCPred(
"$is_regular_file", 1, is_regular_file, SyncPredFlag);
835 Yap_InitCPred(
"rmdir", 2, p_rmdir, SyncPredFlag);
836 Yap_InitCPred(
"get_time", 1, get_time, SyncPredFlag);
const char * Yap_AbsoluteFile(const char *spec, bool ok)
generate absolute path, if ok first expand SICStus Prolog style
void * Malloc(size_t sz USES_REGS)
allocate a temporary text block
A segment represents a single component of a path.
void *(* opendir)(struct vfs *, const char *s)
jump around the stream
bool(* stat)(struct vfs *, const char *s, vfs_stat *)
close access a directory object
const char *(* nextdir)(void *d)
open a directory object, if one exists
bool(* isdir)(struct vfs *, const char *s)
obtain size, age, permissions of a file
bool(* closedir)(void *d)
walk to the next entry in a directory object