urbit/vere/walk.c

342 lines
7.1 KiB
C
Raw Normal View History

2013-09-29 00:21:18 +04:00
/* v/walk.c
**
** This file is in the public domain.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <setjmp.h>
#include <gmp.h>
#include <dirent.h>
#include <stdint.h>
#include <uv.h>
#include <curses.h>
#include <termios.h>
#include <term.h>
#include <errno.h>
#include "all.h"
#include "vere/vere.h"
2013-09-29 00:21:18 +04:00
/* |%
** ++ arch :: fs node
** $% [& p=@uvI q=*] :: file, hash/data
** [| p=(map ,@ta arch)] :: directory
** == ::
** --
*/
#if 0
2014-09-11 04:01:32 +04:00
static u3_noun
_walk_ok(u3_noun nod)
2013-09-29 00:21:18 +04:00
{
2014-11-06 03:20:01 +03:00
u3_noun don = u3n_mung(u3k(u2A->toy.arch), u3k(nod));
2013-09-29 00:21:18 +04:00
2014-11-05 04:18:47 +03:00
if ( c3n == u3_sing(nod, don) ) {
2013-09-29 00:21:18 +04:00
c3_assert(0);
}
2014-09-11 04:01:32 +04:00
u3z(don);
2013-09-29 00:21:18 +04:00
return nod;
}
#endif
2014-09-11 04:01:32 +04:00
/* u3_walk_safe(): load file or 0.
2013-09-29 00:21:18 +04:00
*/
2014-09-11 04:01:32 +04:00
u3_noun
u3_walk_safe(c3_c* pas_c)
2013-09-29 00:21:18 +04:00
{
struct stat buf_b;
c3_i fid_i = open(pas_c, O_RDONLY, 0644);
c3_w fln_w, red_w;
c3_y* pad_y;
if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) {
// uL(fprintf(uH, "%s: %s\n", pas_c, strerror(errno)));
return 0;
}
fln_w = buf_b.st_size;
2014-04-02 04:47:01 +04:00
pad_y = c3_malloc(buf_b.st_size);
2013-09-29 00:21:18 +04:00
red_w = read(fid_i, pad_y, fln_w);
close(fid_i);
if ( fln_w != red_w ) {
free(pad_y);
return 0;
}
else {
2014-11-06 03:20:01 +03:00
u3_noun pad = u3i_bytes(fln_w, (c3_y *)pad_y);
2013-09-29 00:21:18 +04:00
free(pad_y);
return pad;
}
}
2014-09-11 04:01:32 +04:00
/* u3_walk_load(): load file or bail.
2013-09-29 00:21:18 +04:00
*/
2014-09-11 04:01:32 +04:00
u3_noun
u3_walk_load(c3_c* pas_c)
2013-09-29 00:21:18 +04:00
{
struct stat buf_b;
c3_i fid_i = open(pas_c, O_RDONLY, 0644);
c3_w fln_w, red_w;
c3_y* pad_y;
if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) {
uL(fprintf(uH, "%s: %s\n", pas_c, strerror(errno)));
2014-11-06 03:20:01 +03:00
return u3m_bail(c3__fail);
2013-09-29 00:21:18 +04:00
}
fln_w = buf_b.st_size;
2014-04-02 04:47:01 +04:00
pad_y = c3_malloc(buf_b.st_size);
2013-09-29 00:21:18 +04:00
red_w = read(fid_i, pad_y, fln_w);
close(fid_i);
if ( fln_w != red_w ) {
free(pad_y);
2014-11-06 03:20:01 +03:00
return u3m_bail(c3__fail);
2013-09-29 00:21:18 +04:00
}
else {
2014-11-06 03:20:01 +03:00
u3_noun pad = u3i_bytes(fln_w, (c3_y *)pad_y);
2013-09-29 00:21:18 +04:00
free(pad_y);
return pad;
}
}
2018-02-24 08:52:35 +03:00
/* _walk_mkdirp(): recursively make directories in pax at bas_c (RETAIN)
*/
static void
_walk_mkdirp(c3_c* bas_c, u3_noun pax)
{
c3_c* pax_c;
c3_y* waq_y;
c3_w pax_w, fas_w, len_w;
if ( u3_nul == pax ) {
return;
}
pax_w = u3r_met(3, u3h(pax));
fas_w = strlen(bas_c);
len_w = 1 + fas_w + pax_w;
pax_c = c3_malloc(1 + len_w);
strncpy(pax_c, bas_c, len_w);
pax_c[fas_w] = '/';
waq_y = (void*)(1 + pax_c + fas_w);
u3r_bytes(0, pax_w, waq_y, u3h(pax));
pax_c[len_w] = '\0';
if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno ) {
uL(fprintf(uH, "error mkdiring %s: %s\n", pax_c, strerror(errno)));
u3m_bail(c3__fail);
}
_walk_mkdirp(pax_c, u3t(pax));
free(pax_c);
}
2014-09-11 04:01:32 +04:00
/* u3_walk_save(): save file or bail.
2013-09-29 00:21:18 +04:00
*/
void
2018-02-24 08:52:35 +03:00
u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax)
2013-09-29 00:21:18 +04:00
{
c3_i fid_i = open(pas_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
c3_w fln_w, rit_w;
c3_y* pad_y;
if ( fid_i < 0 ) {
2018-02-24 08:52:35 +03:00
if ( ENOENT == errno && u3_nul != pax ) {
_walk_mkdirp(bas_c, pax);
return u3_walk_save(pas_c, tim, pad, 0, u3_nul);
}
2013-09-29 00:21:18 +04:00
uL(fprintf(uH, "%s: %s\n", pas_c, strerror(errno)));
2014-11-06 03:20:01 +03:00
u3m_bail(c3__fail);
2013-09-29 00:21:18 +04:00
}
2014-11-06 03:20:01 +03:00
fln_w = u3r_met(3, pad);
2014-04-02 04:47:01 +04:00
pad_y = c3_malloc(fln_w);
2014-11-06 03:20:01 +03:00
u3r_bytes(0, fln_w, pad_y, pad);
2014-09-11 04:01:32 +04:00
u3z(pad);
2018-02-24 08:52:35 +03:00
u3z(pax);
2013-09-29 00:21:18 +04:00
rit_w = write(fid_i, pad_y, fln_w);
close(fid_i);
free(pad_y);
if ( rit_w != fln_w ) {
uL(fprintf(uH, "%s: %s\n", pas_c, strerror(errno)));
2014-11-06 03:20:01 +03:00
u3m_bail(c3__fail);
2013-09-29 00:21:18 +04:00
}
if ( 0 != tim ) {
struct timeval tim_tv[2];
2014-09-11 04:01:32 +04:00
u3_time_out_tv(&tim_tv[0], u3k(tim));
u3_time_out_tv(&tim_tv[1], tim);
2013-09-29 00:21:18 +04:00
utimes(pas_c, tim_tv);
}
}
/* _walk_in(): inner loop of _walk(), producing map.
*/
2014-09-11 04:01:32 +04:00
static u3_noun
_walk_in(const c3_c* dir_c, c3_w len_w)
2013-09-29 00:21:18 +04:00
{
DIR* dir_d = opendir(dir_c);
2014-09-11 04:01:32 +04:00
u3_noun map = u3_nul;
2013-09-29 00:21:18 +04:00
if ( !dir_d ) {
2014-09-11 04:01:32 +04:00
return u3_nul;
2013-09-29 00:21:18 +04:00
}
else while ( 1 ) {
struct dirent ent_n;
struct dirent* out_n;
if ( readdir_r(dir_d, &ent_n, &out_n) != 0 ) {
uL(fprintf(uH, "%s: %s\n", dir_c, strerror(errno)));
break;
}
2013-09-29 00:21:18 +04:00
else if ( !out_n ) {
break;
}
else if ( !strcmp(out_n->d_name, ".") ||
2013-09-29 00:21:18 +04:00
!strcmp(out_n->d_name, "..") ||
('~' == out_n->d_name[0]) ||
('.' == out_n->d_name[0]) ) // XX restricts some spans
{
continue;
}
else {
c3_c* fil_c = out_n->d_name;
c3_w lef_w = len_w + 1 + strlen(fil_c);
2014-04-02 04:47:01 +04:00
c3_c* pat_c = c3_malloc(lef_w + 1);
2013-09-29 00:21:18 +04:00
struct stat buf_b;
strncpy(pat_c, dir_c, lef_w);
2013-09-29 00:21:18 +04:00
pat_c[len_w] = '/';
strncpy(pat_c + len_w + 1, fil_c, lef_w);
pat_c[lef_w] = '\0';
2013-09-29 00:21:18 +04:00
if ( 0 != stat(pat_c, &buf_b) ) {
free(pat_c);
} else {
2014-09-11 04:01:32 +04:00
u3_noun tim = c3_stat_mtime(&buf_b);
2013-09-29 00:21:18 +04:00
if ( !S_ISDIR(buf_b.st_mode) ) {
c3_c* dot_c = strrchr(fil_c, '.');
c3_c* nam_c = strdup(fil_c);
c3_c* ext_c = strdup(dot_c + 1);
nam_c[dot_c - fil_c] = 0;
{
2014-11-06 03:20:01 +03:00
u3_noun nam = u3i_string(nam_c);
u3_noun ext = u3i_string(ext_c);
2014-11-06 22:13:57 +03:00
u3_noun get = u3kdb_get(u3k(map), u3k(nam));
2014-09-11 04:01:32 +04:00
u3_noun dat = u3_walk_load(pat_c);
u3_noun hax;
2013-09-29 00:21:18 +04:00
if ( !strcmp("noun", ext_c) ) {
2014-11-06 22:13:57 +03:00
dat = u3ke_cue(dat);
2013-09-29 00:21:18 +04:00
}
2014-11-06 06:10:22 +03:00
hax = u3do("sham", u3k(dat));
2014-11-06 02:36:30 +03:00
if ( u3_none == get ) { get = u3_nul; }
2014-11-06 22:13:57 +03:00
get = u3kdb_put(get, ext, u3nt(c3y, hax, dat));
map = u3kdb_put(map, nam, u3nc(c3n, get));
2013-09-29 00:21:18 +04:00
}
free(nam_c);
free(ext_c);
}
else {
2014-09-11 04:01:32 +04:00
u3_noun dir = _walk_in(pat_c, lef_w);
2013-09-29 00:21:18 +04:00
2014-09-11 04:01:32 +04:00
if ( u3_nul != dir ) {
2014-11-06 22:13:57 +03:00
map = u3kdb_put
2014-11-06 03:20:01 +03:00
(map, u3i_string(fil_c), u3nc(c3n, dir));
2013-09-29 00:21:18 +04:00
}
2014-09-11 04:01:32 +04:00
else u3z(tim);
2013-09-29 00:21:18 +04:00
}
free(pat_c);
}
}
}
closedir(dir_d);
return map;
}
2014-09-11 04:01:32 +04:00
/* u3_walk(): traverse `dir_c` to produce an arch, updating `old`.
2013-09-29 00:21:18 +04:00
*/
2014-09-11 04:01:32 +04:00
u3_noun
u3_walk(const c3_c* dir_c, u3_noun old)
2013-09-29 00:21:18 +04:00
{
// XX - obviously, cheaper to update old data.
2014-09-11 04:01:32 +04:00
u3z(old);
2013-09-29 00:21:18 +04:00
{
struct stat buf_b;
if ( 0 != stat(dir_c, &buf_b) ) {
uL(fprintf(uH, "can't stat %s\n", dir_c));
2014-11-06 03:20:01 +03:00
// return u3m_bail(c3__fail);
2013-09-29 00:21:18 +04:00
c3_assert(0);
}
else {
2014-11-05 04:18:47 +03:00
return u3nc(c3n,
2014-09-11 04:01:32 +04:00
_walk_in(dir_c, strlen(dir_c)));
2013-09-29 00:21:18 +04:00
}
}
}
2014-09-11 04:01:32 +04:00
/* u3_path(): C unix path in computer for file or directory.
2013-09-29 00:21:18 +04:00
*/
c3_c*
2014-11-06 06:10:22 +03:00
u3_path(c3_o fyl, u3_noun pax)
2013-09-29 00:21:18 +04:00
{
c3_w len_w;
c3_c *pas_c;
// measure
//
2014-09-11 04:01:32 +04:00
len_w = strlen(u3_Local);
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_noun wiz = pax;
2013-09-29 00:21:18 +04:00
2014-09-11 04:01:32 +04:00
while ( u3_nul != wiz ) {
2014-11-06 03:20:01 +03:00
len_w += (1 + u3r_met(3, u3h(wiz)));
2014-09-11 04:01:32 +04:00
wiz = u3t(wiz);
2013-09-29 00:21:18 +04:00
}
}
// cut
//
2014-04-02 04:47:01 +04:00
pas_c = c3_malloc(len_w + 1);
2014-09-11 04:01:32 +04:00
strncpy(pas_c, u3_Local, len_w);
pas_c[len_w] = '\0';
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_noun wiz = pax;
2013-09-29 00:21:18 +04:00
c3_c* waq_c = (pas_c + strlen(pas_c));
2014-09-11 04:01:32 +04:00
while ( u3_nul != wiz ) {
2014-11-06 03:20:01 +03:00
c3_w tis_w = u3r_met(3, u3h(wiz));
2013-09-29 00:21:18 +04:00
2014-11-05 04:18:47 +03:00
if ( (c3y == fyl) && (u3_nul == u3t(wiz)) ) {
2013-09-29 00:21:18 +04:00
*waq_c++ = '.';
} else *waq_c++ = '/';
2014-11-06 03:20:01 +03:00
u3r_bytes(0, tis_w, (c3_y*)waq_c, u3h(wiz));
2013-09-29 00:21:18 +04:00
waq_c += tis_w;
2014-09-11 04:01:32 +04:00
wiz = u3t(wiz);
2013-09-29 00:21:18 +04:00
}
*waq_c = 0;
}
2014-09-11 04:01:32 +04:00
u3z(pax);
2013-09-29 00:21:18 +04:00
return pas_c;
}