2003-08-19 15:19:38 -04:00
|
|
|
#include "unix.h"
|
|
|
|
|
2003-08-25 10:17:09 -04:00
|
|
|
#ifdef HAVE_UTIME_H
|
2003-08-19 15:19:38 -04:00
|
|
|
# include <utime.h>
|
|
|
|
#else
|
|
|
|
struct utimbuf {
|
|
|
|
time_t actime, modtime;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2003-08-25 10:17:09 -04:00
|
|
|
#ifdef HAVE_DIRENT
|
2003-08-19 15:19:38 -04:00
|
|
|
# include <dirent.h>
|
|
|
|
#else
|
|
|
|
# include <sys/dir.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(ELOOP)
|
|
|
|
# define SYMLINKS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static SYMDESCR Access_Syms[] = {
|
|
|
|
{ "read", R_OK }, /* Nothing == F_OK */
|
|
|
|
{ "write", W_OK },
|
|
|
|
{ "execute", X_OK },
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static Object P_Accessp(fn, mode) Object fn, mode; {
|
|
|
|
if (access(Get_Strsym(fn), (int)Symbols_To_Bits(mode, 1, Access_Syms))
|
2003-09-02 04:12:11 -04:00
|
|
|
== 0)
|
|
|
|
return True;
|
2003-08-19 15:19:38 -04:00
|
|
|
Saved_Errno = errno;
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Chdir(fn) Object fn; {
|
|
|
|
if (chdir(Get_Strsym(fn)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error1("~s: ~E", fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Chmod(fn, mode) Object fn, mode; {
|
|
|
|
if (chmod(Get_Strsym(fn), Get_Integer(mode)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error1("~s: ~E", fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Chown(fn, uid, gid) Object fn, uid, gid; {
|
|
|
|
if (chown(Get_Strsym(fn), Get_Integer(uid), Get_Integer(gid)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error1("~s: ~E", fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Link(fn1, fn2) Object fn1, fn2; {
|
|
|
|
if (link(Get_Strsym(fn1), Get_Strsym(fn2)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error2("(~s ~s): ~E", fn1, fn2);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Mkdir(fn, mode) Object fn, mode; {
|
|
|
|
if (mkdir(Get_Strsym(fn), Get_Integer(mode)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error1("~s: ~E", fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Read_Directory(fn) Object fn; {
|
|
|
|
DIR *d;
|
2003-08-25 10:17:09 -04:00
|
|
|
#ifdef HAVE_DIRENT
|
2003-08-19 15:19:38 -04:00
|
|
|
struct dirent *dp;
|
|
|
|
#else
|
|
|
|
struct direct *dp;
|
|
|
|
#endif
|
|
|
|
Object ret;
|
|
|
|
GC_Node;
|
|
|
|
|
|
|
|
ret = Null;
|
|
|
|
GC_Link(ret);
|
|
|
|
Disable_Interrupts;
|
|
|
|
if ((d = opendir(Get_Strsym(fn))) == NULL) {
|
2003-09-02 04:12:11 -04:00
|
|
|
Saved_Errno = errno;
|
|
|
|
Enable_Interrupts;
|
|
|
|
Raise_System_Error1("~s: cannot open", fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
while ((dp = readdir(d)) != NULL) {
|
2003-09-02 04:12:11 -04:00
|
|
|
Object x;
|
2003-08-19 15:25:03 -04:00
|
|
|
|
2003-09-02 04:12:11 -04:00
|
|
|
x = Make_String(dp->d_name, strlen(dp->d_name));
|
|
|
|
ret = Cons(x, ret);
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
/* closedir() is void under 4.3BSD, should check result elsewhere.
|
|
|
|
*/
|
|
|
|
(void)closedir(d);
|
|
|
|
Enable_Interrupts;
|
|
|
|
GC_Unlink;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Rename(fromfn, tofn) Object fromfn, tofn; {
|
2003-08-25 10:17:09 -04:00
|
|
|
#ifdef HAVE_RENAME
|
2003-08-19 15:19:38 -04:00
|
|
|
if (rename(Get_Strsym(fromfn), Get_Strsym(tofn)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error2("(~s ~s): ~E", fromfn, tofn);
|
2003-08-19 15:19:38 -04:00
|
|
|
#else
|
|
|
|
char *from = Get_Strsym(fromfn), *to = Get_Strsym(tofn);
|
|
|
|
|
|
|
|
Disable_Interrupts;
|
|
|
|
if (link(from, to) == -1) {
|
2003-09-02 04:12:11 -04:00
|
|
|
Saved_Errno = errno;
|
|
|
|
Enable_Interrupts;
|
|
|
|
Raise_System_Error2("(~s ~s): ~E", fromfn, tofn);
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
if (unlink(from) == -1) {
|
2003-09-02 04:12:11 -04:00
|
|
|
Saved_Errno = errno;
|
|
|
|
(void)unlink(to);
|
|
|
|
Enable_Interrupts;
|
|
|
|
Raise_Error1("~s: ~E", fromfn);
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
Enable_Interrupts;
|
|
|
|
#endif
|
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object General_Stat(obj, ret, l) Object obj, ret; int l; {
|
|
|
|
Object x;
|
|
|
|
struct stat st;
|
|
|
|
char *s, *fn = 0;
|
|
|
|
int fd, result;
|
|
|
|
GC_Node;
|
|
|
|
|
|
|
|
Check_Result_Vector(ret, 11);
|
|
|
|
if (l) {
|
|
|
|
#ifdef SYMLINKS
|
2003-09-02 04:12:11 -04:00
|
|
|
result = lstat(Get_Strsym(obj), &st);
|
2003-08-19 15:19:38 -04:00
|
|
|
#endif
|
|
|
|
} else {
|
2003-09-02 04:12:11 -04:00
|
|
|
Get_Filename_Or_Filedescr(obj, fd, fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
result = fn ? stat(fn, &st) : fstat(fd, &st);
|
|
|
|
}
|
|
|
|
if (result == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error1("~s: ~E", obj);
|
2003-08-19 15:19:38 -04:00
|
|
|
switch (st.st_mode & S_IFMT) {
|
|
|
|
case S_IFDIR: s = "directory"; break;
|
|
|
|
case S_IFCHR: s = "character-special"; break;
|
|
|
|
case S_IFBLK: s = "block-special"; break;
|
|
|
|
case S_IFREG: s = "regular"; break;
|
|
|
|
#ifdef S_IFLNK
|
|
|
|
case S_IFLNK: s = "symlink"; break;
|
|
|
|
#endif
|
|
|
|
#ifdef S_IFSOCK
|
|
|
|
case S_IFSOCK: s = "socket"; break;
|
|
|
|
#endif
|
|
|
|
#ifdef S_IFFIFO
|
|
|
|
case S_IFFIFO: s = "fifo"; break;
|
|
|
|
#endif
|
|
|
|
default: s = "unknown"; break;
|
|
|
|
}
|
|
|
|
/* Bad assumption: any of the st_ fields fits into an unsigned int.
|
|
|
|
*/
|
|
|
|
GC_Link(ret);
|
|
|
|
x = Intern(s);
|
|
|
|
VECTOR(ret)->data[0] = x;
|
|
|
|
x = Make_Unsigned((unsigned)st.st_mode & ~S_IFMT);
|
|
|
|
VECTOR(ret)->data[1] = x;
|
|
|
|
x = Make_Unsigned_Long((unsigned long)st.st_ino);
|
|
|
|
VECTOR(ret)->data[2] = x;
|
|
|
|
x = Make_Unsigned((unsigned)st.st_dev);
|
|
|
|
VECTOR(ret)->data[3] = x;
|
|
|
|
x = Make_Unsigned((unsigned)st.st_nlink);
|
|
|
|
VECTOR(ret)->data[4] = x;
|
|
|
|
x = Make_Unsigned((unsigned)st.st_uid);
|
|
|
|
VECTOR(ret)->data[5] = x;
|
|
|
|
x = Make_Unsigned((unsigned)st.st_gid);
|
|
|
|
VECTOR(ret)->data[6] = x;
|
|
|
|
x = Make_Long((long)st.st_size);
|
|
|
|
VECTOR(ret)->data[7] = x;
|
|
|
|
x = Make_Unsigned_Long((unsigned long)st.st_atime);
|
|
|
|
VECTOR(ret)->data[8] = x;
|
|
|
|
x = Make_Unsigned_Long((unsigned long)st.st_mtime);
|
|
|
|
VECTOR(ret)->data[9] = x;
|
|
|
|
x = Make_Unsigned_Long((unsigned long)st.st_ctime);
|
|
|
|
VECTOR(ret)->data[10] = x;
|
|
|
|
GC_Unlink;
|
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Stat(obj, ret) Object obj, ret; {
|
|
|
|
return General_Stat(obj, ret, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SYMLINKS
|
|
|
|
static Object P_Lstat(obj, ret) Object obj, ret; {
|
|
|
|
return General_Stat(obj, ret, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Readlink(fn) Object fn; {
|
|
|
|
char *buf;
|
|
|
|
int len;
|
|
|
|
Object ret;
|
|
|
|
Alloca_Begin;
|
|
|
|
|
|
|
|
len = Path_Max();
|
|
|
|
Alloca(buf, char*, len);
|
|
|
|
if ((len = readlink(Get_Strsym(fn), buf, len)) == -1) {
|
2003-09-02 04:12:11 -04:00
|
|
|
Alloca_End;
|
|
|
|
Raise_System_Error1("~s: ~E", fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
ret = Make_String(buf, len);
|
|
|
|
Alloca_End;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Rmdir(fn) Object fn; {
|
|
|
|
if (rmdir(Get_Strsym(fn)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error1("~s: ~E", fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Symlink(fn1, fn2) Object fn1, fn2; {
|
|
|
|
if (symlink(Get_Strsym(fn1), Get_Strsym(fn2)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error2("(~s ~s): ~E", fn1, fn2);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static Object P_Unlink(fn) Object fn; {
|
|
|
|
if (unlink(Get_Strsym(fn)) == -1)
|
2003-09-02 04:12:11 -04:00
|
|
|
Raise_System_Error1("~s: ~E", fn);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Utime(argc, argv) int argc; Object *argv; {
|
|
|
|
struct utimbuf ut;
|
|
|
|
|
|
|
|
if (argc == 2)
|
2003-09-02 04:12:11 -04:00
|
|
|
Primitive_Error("wrong number of arguments");
|
2003-08-19 15:19:38 -04:00
|
|
|
if (argc == 3) {
|
2003-09-02 04:12:11 -04:00
|
|
|
ut.actime = (time_t)Get_Unsigned_Long(argv[1]);
|
|
|
|
ut.modtime = (time_t)Get_Unsigned_Long(argv[2]);
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
if (utime(Get_Strsym(argv[0]), argc == 1 ? (struct utimbuf *)0 : &ut)
|
2003-09-02 04:12:11 -04:00
|
|
|
== -1)
|
|
|
|
Raise_System_Error1("~s: ~E", argv[0]);
|
2003-08-19 15:19:38 -04:00
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
elk_init_unix_file() {
|
|
|
|
Def_Prim(P_Accessp, "unix-access?", 2, 2, EVAL);
|
|
|
|
Def_Prim(P_Chdir, "unix-chdir", 1, 1, EVAL);
|
|
|
|
Def_Prim(P_Chmod, "unix-chmod", 2, 2, EVAL);
|
|
|
|
Def_Prim(P_Chown, "unix-chown", 3, 3, EVAL);
|
|
|
|
Def_Prim(P_Link, "unix-link", 2, 2, EVAL);
|
|
|
|
Def_Prim(P_Mkdir, "unix-mkdir", 2, 2, EVAL);
|
|
|
|
Def_Prim(P_Read_Directory, "unix-read-directory", 1, 1, EVAL);
|
|
|
|
Def_Prim(P_Rename, "unix-rename", 2, 2, EVAL);
|
|
|
|
Def_Prim(P_Stat, "unix-stat-vector-fill!", 2, 2, EVAL);
|
|
|
|
#ifdef SYMLINKS
|
|
|
|
Def_Prim(P_Lstat, "unix-lstat-vector-fill!", 2, 2, EVAL);
|
|
|
|
Def_Prim(P_Readlink, "unix-readlink", 1, 1, EVAL);
|
|
|
|
Def_Prim(P_Rmdir, "unix-rmdir", 1, 1, EVAL);
|
|
|
|
Def_Prim(P_Symlink, "unix-symlink", 2, 2, EVAL);
|
|
|
|
P_Provide(Intern("unix:symlinks"));
|
|
|
|
#endif
|
|
|
|
Def_Prim(P_Unlink, "unix-unlink", 1, 1, EVAL);
|
|
|
|
Def_Prim(P_Utime, "unix-utime", 1, 3, VARARGS);
|
|
|
|
}
|