1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-01 12:29:54 +00:00

Add os/stat function.

Allows getting more information about files. This
is really useful for writing software that needs to inspect
the file system (like a static site generator). We still need
a way to iterate directories though.
This commit is contained in:
Calvin Rose 2019-03-30 12:06:14 -04:00
parent bf2d9ae634
commit c5090606a4

View File

@ -384,6 +384,86 @@ static Janet os_touch(int32_t argc, Janet *argv) {
return janet_wrap_boolean(res != -1); return janet_wrap_boolean(res != -1);
} }
#ifdef JANET_WINDOWS
static const uint8_t *janet_decode_permissions(unsigned short m) {
uint8_t flags[9] = {0};
flags[0] = flags[3] = flags[6] = (m & S_IREAD) ? 'r' : '-';
flags[1] = flags[4] = flags[7] = (m & S_IWRITE) ? 'w' : '-';
flags[2] = flags[5] = flags[8] = (m & S_IEXEC) ? 'x' : '-';
return janet_string(flags, sizeof(flags));
}
static const uint8_t *janet_decode_mode(unsigned short m) {
const char *str = "other";
if (_S_ISREG(m)) str = "file";
else if (_S_ISDIR(m)) str = "directory";
return janet_ckeyword(str);
}
#else
static const uint8_t *janet_decode_permissions(mode_t m) {
uint8_t flags[9] = {0};
flags[0] = (m & S_IRUSR) ? 'r' : '-';
flags[1] = (m & S_IWUSR) ? 'w' : '-';
flags[2] = (m & S_IXUSR) ? 'x' : '-';
flags[3] = (m & S_IRGRP) ? 'r' : '-';
flags[4] = (m & S_IWGRP) ? 'w' : '-';
flags[5] = (m & S_IXGRP) ? 'x' : '-';
flags[6] = (m & S_IROTH) ? 'r' : '-';
flags[7] = (m & S_IWOTH) ? 'w' : '-';
flags[8] = (m & S_IXOTH) ? 'x' : '-';
return janet_string(flags, sizeof(flags));
}
static const uint8_t *janet_decode_mode(mode_t m) {
const char *str = "other";
if (S_ISREG(m)) str = "file";
else if (S_ISDIR(m)) str = "directory";
else if (S_ISFIFO(m)) str = "fifo";
else if (S_ISBLK(m)) str = "block";
else if (S_ISSOCK(m)) str = "socket";
else if (S_ISLNK(m)) str = "link";
else if (S_ISCHR(m)) str = "character";
return janet_ckeyword(str);
}
#endif
static Janet os_stat(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 2);
const char *path = janet_getcstring(argv, 0);
JanetTable *tab;
if (argc == 2) {
tab = janet_gettable(argv, 1);
} else {
tab = janet_table(0);
}
/* Build result */
#ifdef JANET_WINDOWS
struct _stat st;
int res = _stat(path, &st);
#else
struct stat st;
int res = stat(path, &st);
#endif
if (-1 == res) {
janet_panicv(janet_cstringv(strerror(errno)));
}
janet_table_put(tab, janet_ckeywordv("dev"), janet_wrap_number(st.st_dev));
janet_table_put(tab, janet_ckeywordv("inode"), janet_wrap_number(st.st_ino));
janet_table_put(tab, janet_ckeywordv("mode"), janet_wrap_keyword(janet_decode_mode(st.st_mode)));
janet_table_put(tab, janet_ckeywordv("permissions"), janet_wrap_string(janet_decode_permissions(st.st_mode)));
janet_table_put(tab, janet_ckeywordv("uid"), janet_wrap_number(st.st_uid));
janet_table_put(tab, janet_ckeywordv("gid"), janet_wrap_number(st.st_gid));
janet_table_put(tab, janet_ckeywordv("size"), janet_wrap_number(st.st_size));
janet_table_put(tab, janet_ckeywordv("nlink"), janet_wrap_number(st.st_nlink));
janet_table_put(tab, janet_ckeywordv("rdev"), janet_wrap_number(st.st_rdev));
janet_table_put(tab, janet_ckeywordv("blocksize"), janet_wrap_number(st.st_blksize));
janet_table_put(tab, janet_ckeywordv("blocks"), janet_wrap_number(st.st_blocks));
janet_table_put(tab, janet_ckeywordv("accessed"), janet_wrap_number(st.st_atime));
janet_table_put(tab, janet_ckeywordv("modified"), janet_wrap_number(st.st_mtime));
janet_table_put(tab, janet_ckeywordv("changed"), janet_wrap_number(st.st_ctime));
return janet_wrap_table(tab);
}
#endif /* JANET_REDUCED_OS */ #endif /* JANET_REDUCED_OS */
static const JanetReg os_cfuns[] = { static const JanetReg os_cfuns[] = {
@ -407,6 +487,11 @@ static const JanetReg os_cfuns[] = {
"Get the string value of an environment variable.") "Get the string value of an environment variable.")
}, },
#ifndef JANET_REDUCED_OS #ifndef JANET_REDUCED_OS
{
"os/stat", os_stat,
JDOC("(os/stat path)\n\n"
"Gets information about a file or directory. Returns a table.")
},
{ {
"os/touch", os_touch, "os/touch", os_touch,
JDOC("(os/touch path [, actime [, modtime]])\n\n" JDOC("(os/touch path [, actime [, modtime]])\n\n"