Branch :
/* c3
* Copyright 2022,2023 kmx.io <contact@kmx.io>
*
* Permission is hereby granted to use this software granted the above
* copyright notice and this permission paragraph are included in all
* copies and substantial portions of this software.
*
* THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
* PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
* AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
* THIS SOFTWARE.
*/
#include <assert.h>
#include <fcntl.h>
#include <err.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include "buf.h"
#include "buf_save.h"
#include "env.h"
#include "file.h"
#include "io.h"
#include "list.h"
#include "str.h"
#include "sym.h"
#include "time.h"
bool * file_access (const s_str *path, const s_sym *mode,
bool *dest)
{
sw m;
if (mode == sym_1("r"))
m = R_OK;
else if (mode == sym_1("rw"))
m = R_OK | W_OK;
else if (mode == sym_1("rwx"))
m = R_OK | W_OK | X_OK;
else if (mode == sym_1("rx"))
m = R_OK | X_OK;
else if (mode == sym_1("w"))
m = W_OK;
else if (mode == sym_1("wx"))
m = W_OK | X_OK;
else if (mode == sym_1("x"))
m = X_OK;
else
m = F_OK;
*dest = access(path->ptr.ps8, m) ? false : true;
return dest;
}
sw file_copy_1 (const char *from, const char *to)
{
s8 buf[4096];
sw fd_from = -1;
sw fd_to = -1;
s8 *out;
sw r;
sw saved_errno;
sw w;
if ((fd_from = open(from, O_RDONLY)) < 0) {
warn("cp: %s", from);
return -1;
}
if ((fd_to = open(to, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
warn("cp: %s", to);
goto error;
}
while ((r = read(fd_from, buf, sizeof buf)) > 0) {
out = buf;
do {
if ((w = write(fd_to, out, r)) >= 0) {
r -= w;
out += w;
}
else if (errno != EINTR)
goto error;
} while (r > 0);
}
if (r == 0) {
if (close(fd_to) < 0) {
fd_to = -1;
goto error;
}
close(fd_from);
return 0;
}
error:
saved_errno = errno;
close(fd_from);
if (fd_to >= 0)
close(fd_to);
errno = saved_errno;
return -1;
}
s_tag * file_mtime (const s_str *path, s_tag *dest)
{
struct stat sb;
assert(path);
assert(dest);
if (stat(path->ptr.ps8, &sb)) {
warn("file_mtime: %s", path->ptr.ps8);
return NULL;
}
return time_to_tag(&sb.st_mtim, dest);
}
s_str * file_search (const s_str *suffix, const s_sym *mode,
s_str *dest)
{
bool access;
s8 buf_s[PATH_MAX];
s_buf buf;
const s_list *path;
sw r;
s_buf_save save;
s_str tmp;
buf_init(&buf, false, PATH_MAX, buf_s);
if ((r = buf_write_str(&buf, &g_c3_env.argv0_dir)) < 0)
return NULL;
buf_save_init(&buf, &save);
path = g_c3_env.path;
while (path) {
if (path->tag.type == TAG_STR) {
buf_save_restore_rpos(&buf, &save);
buf_save_restore_wpos(&buf, &save);
if ((r = buf_write_str(&buf, &path->tag.data.str)) < 0 ||
(buf.ptr.ps8[buf.wpos - 1] != '/' &&
(r = buf_write_u8(&buf, '/')) < 0) ||
(r = buf_write_str(&buf, suffix)) < 0)
return NULL;
buf_read_to_str(&buf, &tmp);
io_inspect_str(&tmp);
file_access(&tmp, mode, &access);
if (access) {
*dest = tmp;
return dest;
}
str_clean(&tmp);
}
path = list_next(path);
}
return NULL;
}