From d2fc42c3ea461e403d2577c086e308ef9e78e9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Fri, 28 Jan 2022 22:59:17 -0800 Subject: [PATCH 01/34] unix: asserting wrappers around unix fs calls --- pkg/urbit/include/c/defs.h | 23 +++++++++++++ pkg/urbit/include/vere/vere.h | 5 +++ pkg/urbit/tests/unix_tests.c | 64 +++++++++++++++++++++++++++++++++++ pkg/urbit/vere/io/unix.c | 35 +++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 pkg/urbit/tests/unix_tests.c diff --git a/pkg/urbit/include/c/defs.h b/pkg/urbit/include/c/defs.h index 245bfcf2f..69fd43f65 100644 --- a/pkg/urbit/include/c/defs.h +++ b/pkg/urbit/include/c/defs.h @@ -122,4 +122,27 @@ } \ rut;}) + /* Asserting unix fs wrappers. + */ + // defined in vere/io/unix.c. + c3_t u3_unix_safe(const c3_c* pax_c); +# define c3_open(a, ...) ({ \ + c3_assert(u3_unix_safe(a)); \ + open(a, __VA_ARGS__);}) +# define c3_opendir(a) ({ \ + c3_assert(u3_unix_safe(a)); \ + opendir(a);}) +# define c3_mkdir(a, b) ({ \ + c3_assert(u3_unix_safe(a)); \ + mkdir(a, b);}) +# define c3_rmdir(a) ({ \ + c3_assert(u3_unix_safe(a)); \ + rmdir(a);}) +# define c3_unlink(a) ({ \ + c3_assert(u3_unix_safe(a)); \ + unlink(a);}) +# define c3_fopen(a, b) ({ \ + c3_assert(u3_unix_safe(a)); \ + fopen(a, b);}) + #endif /* ifndef C3_DEFS_H */ diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index 64eea8eac..9514d4b33 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -1168,6 +1168,11 @@ /** Storage, new school. **/ + /* u3_unix_safe(): true iff path is canonical. + */ + c3_t + u3_unix_safe(const c3_c* pax_c); + /* u3_unix_initial_into_card(): create initial filesystem sync card. */ u3_noun diff --git a/pkg/urbit/tests/unix_tests.c b/pkg/urbit/tests/unix_tests.c new file mode 100644 index 000000000..ec0dde82c --- /dev/null +++ b/pkg/urbit/tests/unix_tests.c @@ -0,0 +1,64 @@ +#include "all.h" +#include "vere/vere.h" + +/* _setup(): prepare for tests. +*/ +static void +_setup(void) +{ +} + +/* _test_safe(): +*/ +static c3_i +_test_safe() +{ + c3_i ret_i = 1; + + if ( !u3_unix_safe("a") || + !u3_unix_safe("a/b") || + !u3_unix_safe("a/b/c/defg/h/ijklmnop") ) + { + fprintf(stderr, "_safe fail 1\n"); + ret_i = 0; + } + + if ( u3_unix_safe("") || + u3_unix_safe(".") || + u3_unix_safe("..") || + u3_unix_safe("/.") || + u3_unix_safe("a/b/c//") || + u3_unix_safe("a/b/.") || + u3_unix_safe("/././../.") || + u3_unix_safe("a\\b\\c") || + u3_unix_safe("/../etc") ) + { + fprintf(stderr, "_safe fail 2\r\n"); + ret_i = 0; + } + + if ( !u3_unix_safe(".a") || + !u3_unix_safe("/.a.b.c/..c") ) + { + fprintf(stderr, "_safe fail 3\r\n"); + ret_i = 0; + } + + return ret_i; +} + +/* main(): run all test cases. +*/ +int +main(int argc, char* argv[]) +{ + _setup(); + + if ( !_test_safe() ) { + fprintf(stderr, "test unix: failed\r\n"); + exit(1); + } + + fprintf(stderr, "test unix: ok\r\n"); + return 0; +} diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 4526298bc..622ce06bc 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -72,6 +72,41 @@ struct _u3_ufil; void u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all); +/* u3_unix_safe(): true iff path is canonical. +*/ +c3_t +u3_unix_safe(const c3_c* pax_c) +{ + if ( 0 == pax_c || + 0 != strchr(pax_c, '\\') ) + { + return 0; + } + // allow root. + // + if ( 0 == strcmp("/", pax_c) ) { + return 1; + } + // allow absolute paths. + // + if ( '/' == *pax_c ) { + pax_c++; + } + do { + if ( 0 == *pax_c + || 0 == strcmp(".", pax_c) + || 0 == strcmp("..", pax_c) + || 0 == strncmp("/", pax_c, 1) + || 0 == strncmp("./", pax_c, 2) + || 0 == strncmp("../", pax_c, 3) ) + { + return 0; + } + pax_c = strchr(pax_c, '/'); + } while ( 0 != pax_c++ ); + return 1; +} + /* u3_readdir_r(): */ c3_w From 741e1d3e8b00a9aadc98e5eed832a73d7a16304d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Sat, 29 Jan 2022 00:16:59 -0800 Subject: [PATCH 02/34] vere: replace fs calls with asserting counterparts --- pkg/urbit/compat/mingw/daemon.c | 2 +- pkg/urbit/noun/events.c | 50 ++++++++++++++++----------------- pkg/urbit/noun/manage.c | 2 +- pkg/urbit/noun/trace.c | 4 +-- pkg/urbit/noun/urth.c | 16 +++++------ pkg/urbit/vere/dawn.c | 2 +- pkg/urbit/vere/disk.c | 4 +-- pkg/urbit/vere/io/http.c | 4 +-- pkg/urbit/vere/io/unix.c | 34 +++++++++++----------- pkg/urbit/vere/king.c | 4 +-- pkg/urbit/vere/walk.c | 10 +++---- pkg/urbit/worker/main.c | 2 +- pkg/urbit/worker/serf.c | 8 +++--- 13 files changed, 71 insertions(+), 71 deletions(-) diff --git a/pkg/urbit/compat/mingw/daemon.c b/pkg/urbit/compat/mingw/daemon.c index 0220cb75a..46e73b0ea 100644 --- a/pkg/urbit/compat/mingw/daemon.c +++ b/pkg/urbit/compat/mingw/daemon.c @@ -10,7 +10,7 @@ _dup_std_handle(HANDLE* new_u, DWORD typ_u) HANDLE han_u = GetStdHandle(typ_u); BOOL con_u = GetConsoleMode(han_u, &dum_u); if ( con_u ) { - han_u = (HANDLE)_get_osfhandle(open(c3_dev_null, O_RDWR, 0)); + han_u = (HANDLE)_get_osfhandle(c3_open(c3_dev_null, O_RDWR, 0)); } if ( !DuplicateHandle(GetCurrentProcess(), han_u, GetCurrentProcess(), new_u, 0, TRUE, DUPLICATE_SAME_ACCESS) ) { diff --git a/pkg/urbit/noun/events.c b/pkg/urbit/noun/events.c index bd9ee1b96..a58b5537d 100644 --- a/pkg/urbit/noun/events.c +++ b/pkg/urbit/noun/events.c @@ -174,17 +174,17 @@ _ce_image_open(u3e_image* img_u) c3_c ful_c[8193]; snprintf(ful_c, 8192, "%s", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/chk", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/chk/%s.bin", u3P.dir_c, img_u->nam_c); - if ( -1 == (img_u->fid_i = open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno)); + if ( -1 == (img_u->fid_i = c3_open(ful_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); return c3n; } else { @@ -268,20 +268,20 @@ _ce_patch_create(u3_ce_patch* pat_u) c3_c ful_c[8193]; snprintf(ful_c, 8192, "%s", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c); - if ( -1 == (pat_u->ctl_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) { - fprintf(stderr, "loom: patch open control.bin: %s\r\n", strerror(errno)); + if ( -1 == (pat_u->ctl_i = c3_open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) { + fprintf(stderr, "loom: patch c3_open control.bin: %s\r\n", strerror(errno)); c3_assert(0); } snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c); - if ( -1 == (pat_u->mem_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) { - fprintf(stderr, "loom: patch open memory.bin: %s\r\n", strerror(errno)); + if ( -1 == (pat_u->mem_i = c3_open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0600)) ) { + fprintf(stderr, "loom: patch c3_open memory.bin: %s\r\n", strerror(errno)); c3_assert(0); } } @@ -294,10 +294,10 @@ _ce_patch_delete(void) c3_c ful_c[8193]; snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c); - unlink(ful_c); + c3_unlink(ful_c); snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c); - unlink(ful_c); + c3_unlink(ful_c); } /* _ce_patch_verify(): check patch data mug. @@ -366,18 +366,18 @@ _ce_patch_open(void) c3_i ctl_i, mem_i; snprintf(ful_c, 8192, "%s", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c); - mkdir(ful_c, 0700); + c3_mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c); - if ( -1 == (ctl_i = open(ful_c, O_RDWR)) ) { + if ( -1 == (ctl_i = c3_open(ful_c, O_RDWR)) ) { return 0; } snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c); - if ( -1 == (mem_i = open(ful_c, O_RDWR)) ) { + if ( -1 == (mem_i = c3_open(ful_c, O_RDWR)) ) { close(ctl_i); _ce_patch_delete(); @@ -773,7 +773,7 @@ _ce_backup(void) snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); - if ( mkdir(ful_c, 0700) ) { + if ( c3_mkdir(ful_c, 0700) ) { if ( EEXIST != errno ) { fprintf(stderr, "loom: image backup: %s\r\n", strerror(errno)); } @@ -782,15 +782,15 @@ _ce_backup(void) snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c); - if ( -1 == (nop_u.fid_i = open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno)); + if ( -1 == (nop_u.fid_i = c3_open(ful_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); return; } snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, sop_u.nam_c); - if ( -1 == (sop_u.fid_i = open(ful_c, mod_i, 0666)) ) { - fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno)); + if ( -1 == (sop_u.fid_i = c3_open(ful_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: c3_open %s: %s\r\n", ful_c, strerror(errno)); return; } @@ -798,11 +798,11 @@ _ce_backup(void) || (c3n == _ce_image_copy(&u3P.sou_u, &sop_u)) ) { - unlink(ful_c); + c3_unlink(ful_c); snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c); - unlink(ful_c); + c3_unlink(ful_c); snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); - rmdir(ful_c); + c3_rmdir(ful_c); } close(nop_u.fid_i); diff --git a/pkg/urbit/noun/manage.c b/pkg/urbit/noun/manage.c index f6e692824..e424d33ab 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -432,7 +432,7 @@ u3_noun u3m_file(c3_c* pas_c) { struct stat buf_b; - c3_i fid_i = open(pas_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(pas_c, O_RDONLY, 0644); c3_w fln_w, red_w; c3_y* pad_y; diff --git a/pkg/urbit/noun/trace.c b/pkg/urbit/noun/trace.c index 1ee8168c7..f3eca5c5f 100644 --- a/pkg/urbit/noun/trace.c +++ b/pkg/urbit/noun/trace.c @@ -282,13 +282,13 @@ u3t_trace_open(c3_c* dir_c) struct stat st; if ( -1 == stat(fil_c, &st) ) { - mkdir(fil_c, 0700); + c3_mkdir(fil_c, 0700); } c3_c lif_c[2056]; snprintf(lif_c, 2056, "%s/%d.json", fil_c, u3_Host.tra_u.fun_w); - u3_Host.tra_u.fil_u = fopen(lif_c, "w"); + u3_Host.tra_u.fil_u = c3_fopen(lif_c, "w"); u3_Host.tra_u.nid_w = (int)getpid(); fprintf(u3_Host.tra_u.fil_u, "[ "); diff --git a/pkg/urbit/noun/urth.c b/pkg/urbit/noun/urth.c index f6df4910f..30ab44817 100644 --- a/pkg/urbit/noun/urth.c +++ b/pkg/urbit/noun/urth.c @@ -509,7 +509,7 @@ _cu_rock_path_make(c3_c* dir_c, c3_d eve_d, c3_c** out_c) return c3n; } - if ( mkdir(nam_c, 0700) + if ( c3_mkdir(nam_c, 0700) && (EEXIST != errno) ) { fprintf(stderr, "rock: directory create failed (%s, %" PRIu64 "): %s\r\n", @@ -552,8 +552,8 @@ _cu_rock_save(c3_c* dir_c, c3_d eve_d, c3_d len_d, c3_y* byt_y) return c3n; } - if ( -1 == (fid_i = open(nam_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) { - fprintf(stderr, "rock: open failed (%s, %" PRIu64 "): %s\r\n", + if ( -1 == (fid_i = c3_open(nam_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) { + fprintf(stderr, "rock: c3_open failed (%s, %" PRIu64 "): %s\r\n", dir_c, eve_d, strerror(errno)); c3_free(nam_c); return c3n; @@ -691,8 +691,8 @@ u3u_mmap_read(c3_c* cap_c, c3_c* pat_c, c3_d* out_d, c3_y** out_y) // open file // - if ( -1 == (fid_i = open(pat_c, O_RDONLY, 0644)) ) { - fprintf(stderr, "%s: open failed (%s): %s\r\n", + if ( -1 == (fid_i = c3_open(pat_c, O_RDONLY, 0644)) ) { + fprintf(stderr, "%s: c3_open failed (%s): %s\r\n", cap_c, pat_c, strerror(errno)); return c3n; } @@ -744,8 +744,8 @@ u3u_mmap(c3_c* cap_c, c3_c* pat_c, c3_d len_d, c3_y** out_y) // open file // - if ( -1 == (fid_i = open(pat_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) { - fprintf(stderr, "%s: open failed (%s): %s\r\n", + if ( -1 == (fid_i = c3_open(pat_c, O_RDWR | O_CREAT | O_TRUNC, 0644)) ) { + fprintf(stderr, "%s: c3_open failed (%s): %s\r\n", cap_c, pat_c, strerror(errno)); return c3n; } @@ -895,7 +895,7 @@ u3u_uncram(c3_c* dir_c, c3_d eve_d) // leave rocks on disk // - // if ( 0 != unlink(nam_c) ) { + // if ( 0 != c3_unlink(nam_c) ) { // fprintf(stderr, "uncram: failed to delete rock (%s, %" PRIu64 "): %s\r\n", // dir_c, eve_d, strerror(errno)); // c3_free(nam_c); diff --git a/pkg/urbit/vere/dawn.c b/pkg/urbit/vere/dawn.c index 6ad296341..ca6eb31a7 100644 --- a/pkg/urbit/vere/dawn.c +++ b/pkg/urbit/vere/dawn.c @@ -462,7 +462,7 @@ _dawn_come(u3_noun stars) c3_c pat_c[64]; snprintf(pat_c, 64, "%s.key", who_c + 1); - FILE* fil_u = fopen(pat_c, "w"); + FILE* fil_u = c3_fopen(pat_c, "w"); fprintf(fil_u, "%s\n", key_c); fclose(fil_u); } diff --git a/pkg/urbit/vere/disk.c b/pkg/urbit/vere/disk.c index a8dc413a1..ae6f23cd4 100644 --- a/pkg/urbit/vere/disk.c +++ b/pkg/urbit/vere/disk.c @@ -721,11 +721,11 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) strcpy(dir_c, pax_c); strcat(dir_c, "/.urb/put"); - mkdir(dir_c, 0700); + c3_mkdir(dir_c, 0700); strcpy(dir_c, pax_c); strcat(dir_c, "/.urb/get"); - mkdir(dir_c, 0700); + c3_mkdir(dir_c, 0700); c3_free(dir_c); } diff --git a/pkg/urbit/vere/io/http.c b/pkg/urbit/vere/io/http.c index f0d2f0ea2..92352d427 100644 --- a/pkg/urbit/vere/io/http.c +++ b/pkg/urbit/vere/io/http.c @@ -1608,7 +1608,7 @@ _http_write_ports_file(u3_httd* htd_u, c3_c *pax_c) c3_c* paf_c = c3_malloc(len_w); snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c); - c3_i por_i = open(paf_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); + c3_i por_i = c3_open(paf_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); c3_free(paf_c); u3_http* htp_u = htd_u->htp_u; @@ -1639,7 +1639,7 @@ _http_release_ports_file(c3_c *pax_c) c3_c* paf_c = c3_malloc(len_w); snprintf(paf_c, len_w, "%s/%s", pax_c, nam_c); - unlink(paf_c); + c3_unlink(paf_c); c3_free(paf_c); } diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 622ce06bc..f31e03315 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -200,7 +200,7 @@ _unix_rm_r_cb(const c3_c* pax_c, u3l_log("bad file type in rm_r: %s\r\n", pax_c); break; case FTW_F: - if ( 0 != unlink(pax_c) && ENOENT != errno ) { + if ( 0 != c3_unlink(pax_c) && ENOENT != errno ) { u3l_log("error unlinking (in rm_r) %s: %s\n", pax_c, strerror(errno)); c3_assert(0); @@ -216,7 +216,7 @@ _unix_rm_r_cb(const c3_c* pax_c, u3l_log("couldn't stat path: %s\r\n", pax_c); break; case FTW_DP: - if ( 0 != rmdir(pax_c) && ENOENT != errno ) { + if ( 0 != c3_rmdir(pax_c) && ENOENT != errno ) { u3l_log("error rmdiring %s: %s\n", pax_c, strerror(errno)); c3_assert(0); } @@ -248,7 +248,7 @@ _unix_rm_r(c3_c* pax_c) static void _unix_mkdir(c3_c* pax_c) { - if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno) { + if ( 0 != c3_mkdir(pax_c, 0755) && EEXIST != errno) { u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno)); c3_assert(0); } @@ -259,7 +259,7 @@ _unix_mkdir(c3_c* pax_c) static c3_w _unix_write_file_hard(c3_c* pax_c, u3_noun mim) { - c3_i fid_i = open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); + c3_i fid_i = c3_open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); c3_w len_w, rit_w, siz_w, mug_w = 0; c3_y* dat_y; @@ -302,7 +302,7 @@ static void _unix_write_file_soft(u3_ufil* fil_u, u3_noun mim) { struct stat buf_u; - c3_i fid_i = open(fil_u->pax_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(fil_u->pax_c, O_RDONLY, 0644); c3_ws len_ws, red_ws; c3_w old_w; c3_y* old_y; @@ -409,7 +409,7 @@ _unix_get_mount_point(u3_unix* unx_u, u3_noun mon) static void _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) { - DIR* rid_u = opendir(mon_u->dir_u.pax_c); + DIR* rid_u = c3_opendir(mon_u->dir_u.pax_c); if ( !rid_u ) { u3l_log("error opening pier directory: %s: %s\r\n", mon_u->dir_u.pax_c, strerror(errno)); @@ -487,7 +487,7 @@ static u3_noun _unix_free_node(u3_unix* unx_u, u3_unod* nod_u); static void _unix_free_file(u3_ufil *fil_u) { - if ( 0 != unlink(fil_u->pax_c) && ENOENT != errno ) { + if ( 0 != c3_unlink(fil_u->pax_c) && ENOENT != errno ) { u3l_log("error unlinking %s: %s\n", fil_u->pax_c, strerror(errno)); c3_assert(0); } @@ -725,7 +725,7 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) fil_u->dry = c3n; struct stat buf_u; - c3_i fid_i = open(fil_u->pax_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(fil_u->pax_c, O_RDONLY, 0644); c3_ws len_ws, red_ws; c3_y* dat_y; @@ -808,7 +808,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) } else { if ( c3y == nod_u->dir ) { - DIR* red_u = opendir(nod_u->pax_c); + DIR* red_u = c3_opendir(nod_u->pax_c); if ( 0 == red_u ) { u3_unod* nex_u = nod_u->nex_u; can = u3kb_weld(_unix_free_node(unx_u, nod_u), can); @@ -821,7 +821,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) } else { struct stat buf_u; - c3_i fid_i = open(nod_u->pax_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(nod_u->pax_c, O_RDONLY, 0644); if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) { if ( ENOENT != errno ) { @@ -848,7 +848,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) // Check for new nodes - DIR* rid_u = opendir(dir_u->pax_c); + DIR* rid_u = c3_opendir(dir_u->pax_c); if ( !rid_u ) { u3l_log("error opening directory %s: %s\r\n", dir_u->pax_c, strerror(errno)); @@ -991,7 +991,7 @@ static u3_noun _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) { struct stat buf_u; - c3_i fid_i = open(pax_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(pax_c, O_RDONLY, 0644); c3_ws len_ws, red_ws; c3_y* dat_y; @@ -1048,7 +1048,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) { u3_noun can = u3_nul; - DIR* rid_u = opendir(pax_c); + DIR* rid_u = c3_opendir(pax_c); if ( !rid_u ) { u3l_log("error opening initial directory: %s: %s\r\n", pax_c, strerror(errno)); @@ -1307,7 +1307,7 @@ u3_unix_acquire(c3_c* pax_c) c3_w pid_w; FILE* loq_u; - if ( NULL != (loq_u = fopen(paf_c, "r")) ) { + if ( NULL != (loq_u = c3_fopen(paf_c, "r")) ) { if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) { u3l_log("lockfile %s is corrupt!\n", paf_c); kill(getpid(), SIGTERM); @@ -1342,10 +1342,10 @@ u3_unix_acquire(c3_c* pax_c) } } fclose(loq_u); - unlink(paf_c); + c3_unlink(paf_c); } - if ( NULL == (loq_u = fopen(paf_c, "w")) ) { + if ( NULL == (loq_u = c3_fopen(paf_c, "w")) ) { u3l_log("unix: unable to open %s\n", paf_c); c3_assert(0); } @@ -1368,7 +1368,7 @@ u3_unix_release(c3_c* pax_c) { c3_c* paf_c = _unix_down(pax_c, ".vere.lock"); - unlink(paf_c); + c3_unlink(paf_c); c3_free(paf_c); } diff --git a/pkg/urbit/vere/king.c b/pkg/urbit/vere/king.c index e857d6040..ff9e85ce0 100644 --- a/pkg/urbit/vere/king.c +++ b/pkg/urbit/vere/king.c @@ -924,13 +924,13 @@ u3_king_grab(void* vod_p) struct stat st; if ( -1 == stat(nam_c, &st) ) { - mkdir(nam_c, 0700); + c3_mkdir(nam_c, 0700); } c3_c man_c[2048]; snprintf(man_c, 2048, "%s/%s-daemon.txt", nam_c, wen_c); - fil_u = fopen(man_c, "w"); + fil_u = c3_fopen(man_c, "w"); fprintf(fil_u, "%s\r\n", wen_c); c3_free(wen_c); diff --git a/pkg/urbit/vere/walk.c b/pkg/urbit/vere/walk.c index 5c113cbac..1e0eb1f47 100644 --- a/pkg/urbit/vere/walk.c +++ b/pkg/urbit/vere/walk.c @@ -32,7 +32,7 @@ u3_noun u3_walk_safe(c3_c* pas_c) { struct stat buf_b; - c3_i fid_i = open(pas_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(pas_c, O_RDONLY, 0644); c3_w fln_w, red_w; c3_y* pad_y; @@ -64,7 +64,7 @@ u3_noun u3_walk_load(c3_c* pas_c) { struct stat buf_b; - c3_i fid_i = open(pas_c, O_RDONLY, 0644); + c3_i fid_i = c3_open(pas_c, O_RDONLY, 0644); c3_w fln_w, red_w; c3_y* pad_y; @@ -116,7 +116,7 @@ _walk_mkdirp(c3_c* bas_c, u3_noun pax) u3r_bytes(0, pax_w, waq_y, u3h(pax)); pax_c[len_w] = '\0'; - if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno ) { + if ( 0 != c3_mkdir(pax_c, 0755) && EEXIST != errno ) { u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno)); u3m_bail(c3__fail); } @@ -130,7 +130,7 @@ _walk_mkdirp(c3_c* bas_c, u3_noun pax) void u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax) { - c3_i fid_i = open(pas_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); + c3_i fid_i = c3_open(pas_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); c3_w fln_w, rit_w; c3_y* pad_y; @@ -174,7 +174,7 @@ u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax) static u3_noun _walk_in(const c3_c* dir_c, c3_w len_w) { - DIR* dir_d = opendir(dir_c); + DIR* dir_d = c3_opendir(dir_c); u3_noun map = u3_nul; if ( !dir_d ) { diff --git a/pkg/urbit/worker/main.c b/pkg/urbit/worker/main.c index 428e22a9a..6d76db26b 100644 --- a/pkg/urbit/worker/main.c +++ b/pkg/urbit/worker/main.c @@ -131,7 +131,7 @@ _cw_serf_stdio(c3_i* inn_i, c3_i* out_i) // we replace [FD 0] (stdin) with a fd pointing to /dev/null // we replace [FD 1] (stdout) with a dup of [FD 2] (stderr) // - c3_i nul_i = open(c3_dev_null, O_RDWR, 0); + c3_i nul_i = c3_open(c3_dev_null, O_RDWR, 0); *inn_i = dup(0); *out_i = dup(1); diff --git a/pkg/urbit/worker/serf.c b/pkg/urbit/worker/serf.c index 55cb3ad7d..982cb8ec9 100644 --- a/pkg/urbit/worker/serf.c +++ b/pkg/urbit/worker/serf.c @@ -204,13 +204,13 @@ _serf_grab(u3_noun sac) struct stat st; if ( -1 == stat(nam_c, &st) ) { - mkdir(nam_c, 0700); + c3_mkdir(nam_c, 0700); } c3_c man_c[2054]; snprintf(man_c, 2053, "%s/%s-serf.txt", nam_c, wen_c); - fil_u = fopen(man_c, "w"); + fil_u = c3_fopen(man_c, "w"); fprintf(fil_u, "%s\r\n", wen_c); c3_free(wen_c); @@ -835,13 +835,13 @@ _serf_writ_live_exit(u3_serf* sef_u, c3_w cod_w) struct stat st; if ( -1 == stat(nam_c, &st) ) { - mkdir(nam_c, 0700); + c3_mkdir(nam_c, 0700); } c3_c man_c[2054]; snprintf(man_c, 2053, "%s/%s.txt", nam_c, wen_c); - fil_u = fopen(man_c, "w"); + fil_u = c3_fopen(man_c, "w"); c3_free(wen_c); u3z(wen); From a74d08f489a009b78aafdbc66d9a3725689d5a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Sat, 29 Jan 2022 00:41:35 -0800 Subject: [PATCH 03/34] vere: extra fs calls --- pkg/urbit/vere/db/lmdb.c | 2 ++ pkg/urbit/vere/foil.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pkg/urbit/vere/db/lmdb.c b/pkg/urbit/vere/db/lmdb.c index a6acbba6d..11d3e67b4 100644 --- a/pkg/urbit/vere/db/lmdb.c +++ b/pkg/urbit/vere/db/lmdb.c @@ -42,6 +42,8 @@ u3_lmdb_init(const c3_c* pax_c, size_t siz_i) MDB_env* env_u; c3_w ret_w; + c3_assert(u3_unix_safe(pax_c)); + if ( (ret_w = mdb_env_create(&env_u)) ) { mdb_logerror(stderr, ret_w, "lmdb: init fail"); return 0; diff --git a/pkg/urbit/vere/foil.c b/pkg/urbit/vere/foil.c index 1d844f5d4..8161a4507 100644 --- a/pkg/urbit/vere/foil.c +++ b/pkg/urbit/vere/foil.c @@ -84,6 +84,8 @@ u3_foil_folder(const c3_c* pax_c) uv_dirent_t den_u; c3_i err_i; + c3_assert(u3_unix_safe(pax_c)); + /* open directory, synchronously */ { From c8f8ced2493b9f40d066707dc8918cfa59d41a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Sat, 29 Jan 2022 21:30:28 -0600 Subject: [PATCH 04/34] main: canonicalize paths from command line --- pkg/urbit/daemon/main.c | 74 +++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index 6e3bbcd1d..4ecc3b4d2 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -54,6 +54,40 @@ _main_presig(c3_c* txt_c) return new_c; } +/* _main_repath(): canonicalize path, using dirname if needed. +*/ +c3_c* +_main_repath(c3_c* pax_c) +{ + c3_c* rel_c; + c3_c* fas_c; + c3_c* dir_c; + c3_w len_w; + c3_i wit_i; + + if ( 0 != (rel_c = realpath(pax_c, 0)) ) { + return rel_c; + } + fas_c = strrchr(pax_c, '/'); + if ( !fas_c ) { + fprintf(stderr, "invalid path %s\n", pax_c); + return 0; + } + c3_assert(u3_unix_safe(fas_c + 1)); + *fas_c = 0; + if ( 0 == (dir_c = realpath(pax_c, 0)) ) { + *fas_c = '/'; + return 0; + } + len_w = strlen(dir_c) + strlen(fas_c + 1) + 2; + rel_c = c3_malloc(len_w); + wit_i = snprintf(rel_c, len_w, "%s/%s", dir_c, fas_c + 1); + c3_assert(wit_i >= 0 && (c3_w)wit_i + 1 == len_w); + *fas_c = '/'; + c3_free(dir_c); + return rel_c; +} + /* _main_getopt(): extract option map from command line. */ static u3_noun @@ -104,11 +138,11 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'J': { - u3_Host.ops_u.lit_c = strdup(optarg); + u3_Host.ops_u.lit_c = _main_repath(optarg); break; } case 'B': { - u3_Host.ops_u.pil_c = strdup(optarg); + u3_Host.ops_u.pil_c = _main_repath(optarg); break; } case 'b': { @@ -120,7 +154,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'A': { - u3_Host.ops_u.arv_c = strdup(optarg); + u3_Host.ops_u.arv_c = _main_repath(optarg); break; } case 'H': { @@ -128,7 +162,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'I': { - u3_Host.ops_u.jin_c = strdup(optarg); + u3_Host.ops_u.jin_c = _main_repath(optarg); break; } case 'C': { @@ -166,7 +200,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'k': { - u3_Host.ops_u.key_c = strdup(optarg); + u3_Host.ops_u.key_c = _main_repath(optarg); break; } case 'n': { @@ -188,7 +222,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'i': { - u3_Host.ops_u.imp_c = strdup(optarg); + u3_Host.ops_u.imp_c = _main_repath(optarg); break; } case 'L': { u3_Host.ops_u.net = c3n; break; } @@ -248,7 +282,7 @@ _main_getopt(c3_i argc, c3_c** argv) } } - u3_Host.dir_c = strdup(argv[optind]); + u3_Host.dir_c = _main_repath(argv[optind]); } // daemon mode (-d) implies disabling terminal assumptions (-t) @@ -663,31 +697,7 @@ main(c3_i argc, printf("~\n"); // printf("welcome.\n"); printf("urbit %s\n", URBIT_VERSION); - - // prints the absolute path of the pier - // - c3_c* abs_c = realpath(u3_Host.dir_c, 0); - - // if the ship is being booted, we use realpath(). Otherwise, we use getcwd() - // with a memory-allocation loop - // - if (abs_c == NULL) { - c3_i mprint_i = 1000; - abs_c = c3_malloc(mprint_i); - - // allocates more memory as needed if the path is too large - // - while ( abs_c != getcwd(abs_c, mprint_i) ) { - c3_free(abs_c); - mprint_i *= 2; - abs_c = c3_malloc(mprint_i); - } - printf("boot: home is %s/%s\n", abs_c, u3_Host.dir_c); - c3_free(abs_c); - } else { - printf("boot: home is %s\n", abs_c); - c3_free(abs_c); - } + printf("boot: home is %s\n", u3_Host.dir_c); // printf("vere: hostname is %s\n", u3_Host.ops_u.nam_c); if ( c3y == u3_Host.ops_u.dem ) { From 3d36582fdab3fed567776ad35b9c3e0f4d17a471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Sat, 29 Jan 2022 22:50:36 -0600 Subject: [PATCH 05/34] unix: whitespace cleanup --- pkg/urbit/vere/io/unix.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index f31e03315..f7d520e52 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -460,12 +460,12 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) } } else { - if ( '.' != out_u->d_name[len_w] - || '\0' == out_u->d_name[len_w + 1] - || '~' == out_u->d_name[strlen(out_u->d_name) - 1] - || ('#' == out_u->d_name[0] && - '#' == out_u->d_name[strlen(out_u->d_name) - 1]) - ) { + if ( '.' != out_u->d_name[len_w] + || '\0' == out_u->d_name[len_w + 1] + || '~' == out_u->d_name[strlen(out_u->d_name) - 1] + || ('#' == out_u->d_name[0] && + '#' == out_u->d_name[strlen(out_u->d_name) - 1]) ) + { c3_free(pax_c); continue; } From 0248f57f0b1c4e3b0c7e9c4a7f37865006c3570c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Sat, 29 Jan 2022 23:23:00 -0600 Subject: [PATCH 06/34] unix: comment format --- pkg/urbit/vere/io/unix.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index f7d520e52..4fab704fc 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -144,8 +144,8 @@ _unix_down(c3_c* pax_c, c3_c* sub_c) } /* _unix_string_to_path(): convert c string to u3_noun path - * - * c string must begin with the pier path plus mountpoint +** +** c string must begin with the pier path plus mountpoint */ static u3_noun _unix_string_to_path_helper(c3_c* pax_c) @@ -517,8 +517,8 @@ _unix_free_dir(u3_udir *dir_u) } /* _unix_free_node(): free node, deleting everything within - * - * also deletes from parent list if in it +** +** also deletes from parent list if in it */ static u3_noun _unix_free_node(u3_unix* unx_u, u3_unod* nod_u) @@ -561,12 +561,12 @@ _unix_free_node(u3_unix* unx_u, u3_unod* nod_u) } /* _unix_free_mount_point(): free mount point - * - * this process needs to happen in a very careful order. in particular, - * we must recurse before we get to the callback, so that libuv does all - * the child directories before it does us. - * - * tread carefully +** +** this process needs to happen in a very careful order. in particular, +** we must recurse before we get to the callback, so that libuv does all +** the child directories before it does us. +** +** tread carefully */ static void _unix_free_mount_point(u3_unix* unx_u, u3_umon* mon_u) @@ -706,12 +706,12 @@ _unix_create_dir(u3_udir* dir_u, u3_udir* par_u, u3_noun nam) static u3_noun _unix_update_node(u3_unix* unx_u, u3_unod* nod_u); /* _unix_update_file(): update file, producing list of changes - * - * when scanning through files, if dry, do nothing. otherwise, mark as - * dry, then check if file exists. if not, remove self from node list - * and add path plus sig to %into event. otherwise, read the file and - * get a mug checksum. if same as gum_w, move on. otherwise, overwrite - * add path plus data to %into event. +** +** when scanning through files, if dry, do nothing. otherwise, mark as +** dry, then check if file exists. if not, remove self from node list +** and add path plus sig to %into event. otherwise, read the file and +** get a mug checksum. if same as gum_w, move on. otherwise, overwrite +** add path plus data to %into event. */ static u3_noun _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) @@ -780,9 +780,9 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) } /* _unix_update_dir(): update directory, producing list of changes - * - * when changing this, consider whether to also change - * _unix_initial_update_dir() +** +** when changing this, consider whether to also change +** _unix_initial_update_dir() */ static u3_noun _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) From a4b40d104ce574ebac8751eec82365504abbe185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Sun, 30 Jan 2022 13:09:20 -0600 Subject: [PATCH 07/34] noun: noop, C 'types' being what they are... --- pkg/urbit/include/noun/imprison.h | 4 ++-- pkg/urbit/noun/imprison.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/urbit/include/noun/imprison.h b/pkg/urbit/include/noun/imprison.h index c68088eee..2123fb813 100644 --- a/pkg/urbit/include/noun/imprison.h +++ b/pkg/urbit/include/noun/imprison.h @@ -127,12 +127,12 @@ /* u3i_string(): Produce an LSB-first atom from the C string [a]. */ - u3_noun + u3_atom u3i_string(const c3_c* a_c); /* u3i_tape(): from a C string, to a list of bytes. */ - u3_atom + u3_noun u3i_tape(const c3_c* txt_c); /* u3i_list(): list from `u3_none`-terminated varargs. diff --git a/pkg/urbit/noun/imprison.c b/pkg/urbit/noun/imprison.c index 77feae7f6..b34b9d884 100644 --- a/pkg/urbit/noun/imprison.c +++ b/pkg/urbit/noun/imprison.c @@ -541,7 +541,7 @@ u3i_qual(u3_noun a, u3_noun b, u3_noun c, u3_noun d) /* u3i_string(): Produce an LSB-first atom from the C string [a]. */ -u3_noun +u3_atom u3i_string(const c3_c* a_c) { return u3i_bytes(strlen(a_c), (c3_y *)a_c); @@ -549,7 +549,7 @@ u3i_string(const c3_c* a_c) /* u3i_tape(): from a C string, to a list of bytes. */ -u3_atom +u3_noun u3i_tape(const c3_c* txt_c) { if ( !*txt_c ) { From d4b4504ae42e20d5c5fb9f6e298fede99750db65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Sun, 30 Jan 2022 19:26:45 -0600 Subject: [PATCH 08/34] vere: move lockfile from unix to disk --- pkg/urbit/vere/disk.c | 94 ++++++++++++++++++++++++++++++++++++++++ pkg/urbit/vere/io/unix.c | 82 ----------------------------------- 2 files changed, 94 insertions(+), 82 deletions(-) diff --git a/pkg/urbit/vere/disk.c b/pkg/urbit/vere/disk.c index ae6f23cd4..13a208bda 100644 --- a/pkg/urbit/vere/disk.c +++ b/pkg/urbit/vere/disk.c @@ -585,6 +585,94 @@ u3_disk_read_meta(u3_disk* log_u, return c3y; } +/* _disk_lock(): lockfile path. +*/ +static c3_c* +_disk_lock(c3_c* pax_c) +{ + c3_w len_w = strlen(pax_c) + sizeof("/.vere.lock"); + c3_c* paf_c = c3_malloc(len_w); + c3_i wit_i; + + wit_i = snprintf(paf_c, len_w, "%s/.vere.lock", pax_c); + c3_assert(wit_i + 1 == len_w); + return paf_c; +} + +/* u3_disk_acquire(): acquire a lockfile, killing anything that holds it. +*/ +static void +u3_disk_acquire(c3_c* pax_c) +{ + c3_c* paf_c = _disk_lock(pax_c); + c3_w pid_w; + FILE* loq_u; + + if ( NULL != (loq_u = c3_fopen(paf_c, "r")) ) { + if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) { + u3l_log("lockfile %s is corrupt!\n", paf_c); + kill(getpid(), SIGTERM); + sleep(1); c3_assert(0); + } + else if (pid_w != getpid()) { + c3_w i_w; + + if ( -1 != kill(pid_w, SIGTERM) ) { + u3l_log("disk: stopping process %d, live in %s...\n", + pid_w, pax_c); + + for ( i_w = 0; i_w < 16; i_w++ ) { + sleep(1); + if ( -1 == kill(pid_w, SIGTERM) ) { + break; + } + } + if ( 16 == i_w ) { + for ( i_w = 0; i_w < 16; i_w++ ) { + if ( -1 == kill(pid_w, SIGKILL) ) { + break; + } + sleep(1); + } + } + if ( 16 == i_w ) { + u3l_log("disk: process %d seems unkillable!\n", pid_w); + c3_assert(0); + } + u3l_log("disk: stopped old process %u\n", pid_w); + } + } + fclose(loq_u); + c3_unlink(paf_c); + } + + if ( NULL == (loq_u = c3_fopen(paf_c, "w")) ) { + u3l_log("disk: unable to open %s\n", paf_c); + c3_assert(0); + } + + fprintf(loq_u, "%u\n", getpid()); + + { + c3_i fid_i = fileno(loq_u); + c3_sync(fid_i); + } + + fclose(loq_u); + c3_free(paf_c); +} + +/* u3_disk_release(): release a lockfile. +*/ +static void +u3_disk_release(c3_c* pax_c) +{ + c3_c* paf_c = _disk_lock(pax_c); + + c3_unlink(paf_c); + c3_free(paf_c); +} + /* u3_disk_exit(): close the log. */ void @@ -633,6 +721,8 @@ u3_disk_exit(u3_disk* log_u) } } + u3_disk_release(log_u->dir_u->pax_c); + u3_dire_free(log_u->dir_u); u3_dire_free(log_u->urb_u); u3_dire_free(log_u->com_u); @@ -697,6 +787,10 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) } } + // acquire lockfile. + // + u3_disk_acquire(pax_c); + // create/load $pier/.urb // { diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 4fab704fc..b81b8f768 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -1298,80 +1298,6 @@ u3_unix_ef_hill(u3_unix* unx_u, u3_noun hil) u3z(hil); } -/* u3_unix_acquire(): acquire a lockfile, killing anything that holds it. -*/ -static void -u3_unix_acquire(c3_c* pax_c) -{ - c3_c* paf_c = _unix_down(pax_c, ".vere.lock"); - c3_w pid_w; - FILE* loq_u; - - if ( NULL != (loq_u = c3_fopen(paf_c, "r")) ) { - if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) { - u3l_log("lockfile %s is corrupt!\n", paf_c); - kill(getpid(), SIGTERM); - sleep(1); c3_assert(0); - } - else if (pid_w != getpid()) { - c3_w i_w; - - if ( -1 != kill(pid_w, SIGTERM) ) { - u3l_log("unix: stopping process %d, live in %s...\n", - pid_w, pax_c); - - for ( i_w = 0; i_w < 16; i_w++ ) { - sleep(1); - if ( -1 == kill(pid_w, SIGTERM) ) { - break; - } - } - if ( 16 == i_w ) { - for ( i_w = 0; i_w < 16; i_w++ ) { - if ( -1 == kill(pid_w, SIGKILL) ) { - break; - } - sleep(1); - } - } - if ( 16 == i_w ) { - u3l_log("unix: process %d seems unkillable!\n", pid_w); - c3_assert(0); - } - u3l_log("unix: stopped old process %u\n", pid_w); - } - } - fclose(loq_u); - c3_unlink(paf_c); - } - - if ( NULL == (loq_u = c3_fopen(paf_c, "w")) ) { - u3l_log("unix: unable to open %s\n", paf_c); - c3_assert(0); - } - - fprintf(loq_u, "%u\n", getpid()); - - { - c3_i fid_i = fileno(loq_u); - c3_sync(fid_i); - } - - fclose(loq_u); - c3_free(paf_c); -} - -/* u3_unix_release(): release a lockfile. -*/ -static void -u3_unix_release(c3_c* pax_c) -{ - c3_c* paf_c = _unix_down(pax_c, ".vere.lock"); - - c3_unlink(paf_c); - c3_free(paf_c); -} - /* u3_unix_ef_look(): update the root of a specific mount point. */ void @@ -1466,10 +1392,6 @@ _unix_io_exit(u3_auto* car_u) { u3_unix* unx_u = (u3_unix*)car_u; - // XX move to disk.c? - // - u3_unix_release(unx_u->pax_c); - c3_free(unx_u->pax_c); c3_free(unx_u); } @@ -1485,10 +1407,6 @@ u3_unix_io_init(u3_pier* pir_u) unx_u->alm = c3n; unx_u->dyr = c3n; - // XX move to disk.c? - // - u3_unix_acquire(unx_u->pax_c); - u3_auto* car_u = &unx_u->car_u; car_u->nam_m = c3__unix; car_u->liv_o = c3n; From 00f7407a5e233d3808095736db9a9671b15d28c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 08:34:43 -0600 Subject: [PATCH 09/34] unix: escape overloaded paths unix cannot represent the file with empty name, and it has special mappings for '.' and '..'. as these three are all valid arvo `+knot`s, we need to escape them if we come across them. the method we use to escape is: if we encounter any of those three `+knot`s, or any `+knot` starting with '~', we prepend its filename with a '~'. and when going from filename to `+knot`, we do the reverse; i.e. we ignore a '~' if it is the first character of a filename. the current implementation just crashes if it encounters a `+knot` containing '/' or '\\', neither of which are valid under the current implementation of `@ta` (which only accepts numbers, lowercase, '-', '~', '.', and '_'.) it also crashes if it encounters a file containing '\\'. something else should happen here; most likely vere should just ignore the file. --- pkg/urbit/vere/io/unix.c | 91 ++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index b81b8f768..da418860e 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -126,6 +126,45 @@ u3_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) return(0); } +/* _unix_string_to_knot(): convert c unix path component to +knot +*/ +static u3_atom +_unix_string_to_knot(c3_c* pax_c) +{ + c3_assert(pax_c); + c3_assert(*pax_c); + c3_assert(!strchr(pax_c, '/')); + c3_assert(!strchr(pax_c, '\\')); + if ( '~' == *pax_c ) { + pax_c++; + } + return u3i_string(pax_c); +} + +/* _unix_knot_to_string(): convert +knot to c unix path component +*/ +static c3_c* +_unix_knot_to_string(u3_atom pon) +{ + c3_w met_w = u3r_met(3, pon); + c3_w add_w = ( 0 == met_w + || '~' == u3r_byte(0, pon) + || c3_s1('.') == pon + || c3_s2('.','.') == pon ); + c3_c* ret_c = c3_malloc(met_w + add_w + 1); + + if ( add_w ) { + *ret_c = '~'; + } + u3r_bytes(0, met_w, (c3_y*)ret_c + add_w, pon); + ret_c[met_w + add_w] = 0; + // |(((sane %ta) '/') ((sane %ta) '\\')) -> %.n + // + c3_assert(!strchr(ret_c, '/')); + c3_assert(!strchr(ret_c, '\\')); + return ret_c; +} + /* _unix_down(): descend path. */ static c3_c* @@ -143,29 +182,34 @@ _unix_down(c3_c* pax_c, c3_c* sub_c) return don_c; } -/* _unix_string_to_path(): convert c string to u3_noun path +/* _unix_string_to_path(): convert c string to u3_noun +path ** ** c string must begin with the pier path plus mountpoint */ static u3_noun _unix_string_to_path_helper(c3_c* pax_c) { + u3_noun not; + c3_assert(pax_c[-1] == '/'); - c3_c* end_w = strchr(pax_c, '/'); - if ( !end_w ) { - end_w = strrchr(pax_c, '.'); - if ( !end_w ) { - return u3nc(u3i_string(pax_c), u3_nul); + c3_c* end_c = strchr(pax_c, '/'); + if ( !end_c ) { + end_c = strrchr(pax_c, '.'); + if ( !end_c ) { + return u3nc(_unix_string_to_knot(pax_c), u3_nul); } else { - return u3nt(u3i_bytes(end_w - pax_c, (c3_y*) pax_c), - u3i_string(end_w + 1), - u3_nul); + *end_c = 0; + not = _unix_string_to_knot(pax_c); + *end_c = '.'; + return u3nt(not, _unix_string_to_knot(end_c + 1), u3_nul); } } else { - return u3nc(u3i_bytes(end_w - pax_c, (c3_y*) pax_c), - _unix_string_to_path_helper(end_w + 1)); + *end_c = 0; + not = _unix_string_to_knot(pax_c); + *end_c = '/'; + return u3nc(not, _unix_string_to_path_helper(end_c + 1)); } } static u3_noun @@ -179,7 +223,7 @@ _unix_string_to_path(u3_unix* unx_u, c3_c* pax_c) return u3_nul; } else { - return u3nc(u3i_string(pox_c + 1), u3_nul); + return u3nc(_unix_string_to_knot(pox_c + 1), u3_nul); } } else { @@ -374,7 +418,7 @@ _unix_get_mount_point(u3_unix* unx_u, u3_noun mon) return NULL; } - c3_c* nam_c = u3r_string(mon); + c3_c* nam_c = _unix_knot_to_string(mon); u3_umon* mon_u; for ( mon_u = unx_u->mon_u; @@ -594,7 +638,7 @@ _unix_delete_mount_point(u3_unix* unx_u, u3_noun mon) return; } - c3_c* nam_c = u3r_string(mon); + c3_c* nam_c = _unix_knot_to_string(mon); u3_umon* mon_u; u3_umon* tem_u; @@ -686,7 +730,7 @@ _unix_watch_dir(u3_udir* dir_u, u3_udir* par_u, c3_c* pax_c) static void _unix_create_dir(u3_udir* dir_u, u3_udir* par_u, u3_noun nam) { - c3_c* nam_c = u3r_string(nam); + c3_c* nam_c = _unix_knot_to_string(nam); c3_w nam_w = strlen(nam_c); c3_w pax_w = strlen(par_u->pax_c); c3_c* pax_c = c3_malloc(pax_w + 1 + nam_w + 1); @@ -977,7 +1021,8 @@ _unix_update_mount(u3_unix* unx_u, u3_umon* mon_u, u3_noun all) u3_noun wir = u3nt(c3__sync, u3dc("scot", c3__uv, unx_u->sev_l), u3_nul); - u3_noun cad = u3nq(c3__into, u3i_string(mon_u->nam_c), all, can); + u3_noun cad = u3nq(c3__into, _unix_string_to_knot(mon_u->nam_c), all, + can); u3_auto_plan(&unx_u->car_u, u3_ovum_init(0, c3__c, wir, cad)); } @@ -1124,8 +1169,8 @@ _unix_sync_file(u3_unix* unx_u, u3_udir* par_u, u3_noun nam, u3_noun ext, u3_nou // form file path - c3_c* nam_c = u3r_string(nam); - c3_c* ext_c = u3r_string(ext); + c3_c* nam_c = _unix_knot_to_string(nam); + c3_c* ext_c = _unix_knot_to_string(ext); c3_w par_w = strlen(par_u->pax_c); c3_w nam_w = strlen(nam_c); c3_w ext_w = strlen(ext_c); @@ -1242,7 +1287,7 @@ static void _unix_sync_ergo(u3_unix* unx_u, u3_umon* mon_u, u3_noun can) { u3_noun nac = can; - u3_noun nam = u3i_string(mon_u->nam_c); + u3_noun nam = _unix_string_to_knot(mon_u->nam_c); while ( u3_nul != nac) { _unix_sync_change(unx_u, &mon_u->dir_u, @@ -1304,18 +1349,18 @@ void u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all) { if ( c3y == unx_u->dyr ) { + c3_c* nam_c = _unix_knot_to_string(mon); + unx_u->dyr = c3n; u3_umon* mon_u = unx_u->mon_u; - - while ( mon_u && ( c3n == u3r_sing_c(mon_u->nam_c, mon) ) ) { + while ( mon_u && 0 != strcmp(nam_c, mon_u->nam_c) ) { mon_u = mon_u->nex_u; } - + c3_free(nam_c); if ( mon_u ) { _unix_update_mount(unx_u, mon_u, all); } } - u3z(mon); } From c04108072935539a0dfcc983ebfc5857085fd483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 09:47:59 -0600 Subject: [PATCH 10/34] unix: bugfixes - Don't test for '\\' in u3_unix_safe. Doing otherwise was crashing vere when unmounting a mountpoint that had come to contain a file with '\\' in its path. This might mean you can do bad things on Windows if other checks fail. - Ignore any files whose names do not pass `(sane %ta)` when scanning directories. (This reimplements `(sane %ta)` in C. Perhaps it should instead call `(sane %ta)`.) - Use '~.' rather than '~' for the escape. We ignore files that end in '~', probably for vim backup-file reasons. - Add a _unix_string_to_knot missed in the prior conversion. --- pkg/urbit/include/vere/vere.h | 2 +- pkg/urbit/tests/unix_tests.c | 1 - pkg/urbit/vere/io/unix.c | 59 ++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index 9514d4b33..f294dd0ec 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -1168,7 +1168,7 @@ /** Storage, new school. **/ - /* u3_unix_safe(): true iff path is canonical. + /* u3_unix_safe(): true iff (unix) path is canonical. */ c3_t u3_unix_safe(const c3_c* pax_c); diff --git a/pkg/urbit/tests/unix_tests.c b/pkg/urbit/tests/unix_tests.c index ec0dde82c..e67e9cf47 100644 --- a/pkg/urbit/tests/unix_tests.c +++ b/pkg/urbit/tests/unix_tests.c @@ -30,7 +30,6 @@ _test_safe() u3_unix_safe("a/b/c//") || u3_unix_safe("a/b/.") || u3_unix_safe("/././../.") || - u3_unix_safe("a\\b\\c") || u3_unix_safe("/../etc") ) { fprintf(stderr, "_safe fail 2\r\n"); diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index da418860e..89abfd45f 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -2,6 +2,7 @@ ** */ #include "all.h" +#include #include #include "vere/vere.h" @@ -72,14 +73,12 @@ struct _u3_ufil; void u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all); -/* u3_unix_safe(): true iff path is canonical. +/* u3_unix_safe(): true iff (unix) path is canonical. */ c3_t u3_unix_safe(const c3_c* pax_c) { - if ( 0 == pax_c || - 0 != strchr(pax_c, '\\') ) - { + if ( 0 == pax_c ) { return 0; } // allow root. @@ -107,6 +106,26 @@ u3_unix_safe(const c3_c* pax_c) return 1; } +/* _unix_sane_ta(): true iff all len_w characters of pax_c are (sane %ta). +** +** %ta is parsed by: +** (star ;~(pose nud low hep dot sig cab)) +*/ +static c3_t +_unix_sane_ta(c3_c* pax_c, c3_w len_w) +{ + for ( ; len_w; pax_c++, len_w-- ) { + if ( !islower(*pax_c) + && !isdigit(*pax_c) + && '-' != *pax_c && '.' != *pax_c + && '~' != *pax_c && '_' != *pax_c ) + { + return 0; + } + } + return 1; +} + /* u3_readdir_r(): */ c3_w @@ -135,8 +154,8 @@ _unix_string_to_knot(c3_c* pax_c) c3_assert(*pax_c); c3_assert(!strchr(pax_c, '/')); c3_assert(!strchr(pax_c, '\\')); - if ( '~' == *pax_c ) { - pax_c++; + if ( 0 == strncmp("~.", pax_c, 2) ) { + pax_c += 2; } return u3i_string(pax_c); } @@ -147,14 +166,16 @@ static c3_c* _unix_knot_to_string(u3_atom pon) { c3_w met_w = u3r_met(3, pon); - c3_w add_w = ( 0 == met_w - || '~' == u3r_byte(0, pon) - || c3_s1('.') == pon - || c3_s2('.','.') == pon ); + c3_w add_w = 2 * + ( 0 == met_w + || ( '~' == u3r_byte(0, pon) + && '.' == u3r_byte(1, pon) ) + || c3_s1('.') == pon + || c3_s2('.','.') == pon ); c3_c* ret_c = c3_malloc(met_w + add_w + 1); if ( add_w ) { - *ret_c = '~'; + memcpy(ret_c, "~.", 2); } u3r_bytes(0, met_w, (c3_y*)ret_c + add_w, pon); ret_c[met_w + add_w] = 0; @@ -507,8 +528,7 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) if ( '.' != out_u->d_name[len_w] || '\0' == out_u->d_name[len_w + 1] || '~' == out_u->d_name[strlen(out_u->d_name) - 1] - || ('#' == out_u->d_name[0] && - '#' == out_u->d_name[strlen(out_u->d_name) - 1]) ) + || !_unix_sane_ta(out_u->d_name, len_w) ) { c3_free(pax_c); continue; @@ -948,11 +968,12 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( !nod_u ) { if ( !S_ISDIR(buf_u.st_mode) ) { - if ( !strchr(out_u->d_name,'.') - || '~' == out_u->d_name[strlen(out_u->d_name) - 1] - || ('#' == out_u->d_name[0] && - '#' == out_u->d_name[strlen(out_u->d_name) - 1]) - ) { + c3_w len_w = strlen(out_u->d_name); + + if ( !strchr(out_u->d_name,'.') + || !_unix_sane_ta(out_u->d_name, len_w) + || '~' == out_u->d_name[len_w - 1] ) + { c3_free(pax_c); continue; } @@ -1254,7 +1275,7 @@ _unix_sync_change(u3_unix* unx_u, u3_udir* dir_u, u3_noun pax, u3_noun mim) _unix_sync_file(unx_u, dir_u, u3k(i_pax), u3k(it_pax), mim); } else { - c3_c* nam_c = u3r_string(i_pax); + c3_c* nam_c = _unix_knot_to_string(i_pax); c3_w pax_w = strlen(dir_u->pax_c); u3_unod* nod_u; From 19002c72dd8aefc44e464907f2567145f950c028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 10:13:39 -0600 Subject: [PATCH 11/34] compat: mingw realpath --- pkg/urbit/compat/mingw/compat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/urbit/compat/mingw/compat.c b/pkg/urbit/compat/mingw/compat.c index 0a60b5666..2caa9ed65 100644 --- a/pkg/urbit/compat/mingw/compat.c +++ b/pkg/urbit/compat/mingw/compat.c @@ -350,6 +350,7 @@ intmax_t mdb_get_filesize(HANDLE han_u) char *realpath(const char *path, char *resolved_path) { - // TODO - return strdup(path); + // XX MAX_PATH + // + return _fullpath(resolved_path, path, MAX_PATH); } From b5a49a159f6dd3e78b46d127d1a643bdbbef867c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 10:38:16 -0600 Subject: [PATCH 12/34] unix: use (sane %ta) out of arvo --- pkg/urbit/vere/io/unix.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 89abfd45f..b26ef7533 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -2,7 +2,6 @@ ** */ #include "all.h" -#include #include #include "vere/vere.h" @@ -59,6 +58,7 @@ struct _u3_ufil; c3_c* pax_c; // pier directory c3_o alm; // timer set c3_o dyr; // ready to update + u3_noun sat; // (sane %ta) handle #ifdef SYNCLOG c3_w lot_w; // sync-slot struct _u3_sylo { @@ -112,18 +112,9 @@ u3_unix_safe(const c3_c* pax_c) ** (star ;~(pose nud low hep dot sig cab)) */ static c3_t -_unix_sane_ta(c3_c* pax_c, c3_w len_w) +_unix_sane_ta(u3_unix* unx_u, c3_c* pax_c, c3_w len_w) { - for ( ; len_w; pax_c++, len_w-- ) { - if ( !islower(*pax_c) - && !isdigit(*pax_c) - && '-' != *pax_c && '.' != *pax_c - && '~' != *pax_c && '_' != *pax_c ) - { - return 0; - } - } - return 1; + return _(u3n_slam_on(u3k(unx_u->sat), u3i_bytes(len_w, (c3_y*)pax_c))); } /* u3_readdir_r(): @@ -528,7 +519,7 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) if ( '.' != out_u->d_name[len_w] || '\0' == out_u->d_name[len_w + 1] || '~' == out_u->d_name[strlen(out_u->d_name) - 1] - || !_unix_sane_ta(out_u->d_name, len_w) ) + || !_unix_sane_ta(unx_u, out_u->d_name, len_w) ) { c3_free(pax_c); continue; @@ -971,7 +962,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) c3_w len_w = strlen(out_u->d_name); if ( !strchr(out_u->d_name,'.') - || !_unix_sane_ta(out_u->d_name, len_w) + || !_unix_sane_ta(unx_u, out_u->d_name, len_w) || '~' == out_u->d_name[len_w - 1] ) { c3_free(pax_c); @@ -1458,6 +1449,7 @@ _unix_io_exit(u3_auto* car_u) { u3_unix* unx_u = (u3_unix*)car_u; + u3z(unx_u->sat); c3_free(unx_u->pax_c); c3_free(unx_u); } @@ -1472,6 +1464,7 @@ u3_unix_io_init(u3_pier* pir_u) unx_u->pax_c = strdup(pir_u->pax_c); unx_u->alm = c3n; unx_u->dyr = c3n; + unx_u->sat = u3do("sane", c3__ta); u3_auto* car_u = &unx_u->car_u; car_u->nam_m = c3__unix; From 2a5baa9e3f626c612b5eb44401754cebb3ab49d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 10:59:23 -0600 Subject: [PATCH 13/34] main: simplify _main_repath --- pkg/urbit/daemon/main.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index 4ecc3b4d2..b3afde9f0 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -63,7 +63,6 @@ _main_repath(c3_c* pax_c) c3_c* fas_c; c3_c* dir_c; c3_w len_w; - c3_i wit_i; if ( 0 != (rel_c = realpath(pax_c, 0)) ) { return rel_c; @@ -75,16 +74,16 @@ _main_repath(c3_c* pax_c) } c3_assert(u3_unix_safe(fas_c + 1)); *fas_c = 0; - if ( 0 == (dir_c = realpath(pax_c, 0)) ) { - *fas_c = '/'; + dir_c = realpath(pax_c, 0); + *fas_c = '/'; + if ( 0 == dir_c ) { return 0; } - len_w = strlen(dir_c) + strlen(fas_c + 1) + 2; + len_w = strlen(dir_c) + strlen(fas_c) + 1; rel_c = c3_malloc(len_w); - wit_i = snprintf(rel_c, len_w, "%s/%s", dir_c, fas_c + 1); - c3_assert(wit_i >= 0 && (c3_w)wit_i + 1 == len_w); - *fas_c = '/'; + strcpy(rel_c, dir_c); c3_free(dir_c); + strcat(rel_c, fas_c); return rel_c; } From 0d9264ea1c8509246f562c7e2a9a6552c10e3625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 11:13:57 -0600 Subject: [PATCH 14/34] unix: don't require that string is non-empty Fixes an assert failure if you try to commit a file named `~.`. --- pkg/urbit/vere/io/unix.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index b26ef7533..9ec342bf0 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -142,7 +142,9 @@ static u3_atom _unix_string_to_knot(c3_c* pax_c) { c3_assert(pax_c); - c3_assert(*pax_c); + // XX this can happen if we encounter a file without an extension. + // + // c3_assert(*pax_c); c3_assert(!strchr(pax_c, '/')); c3_assert(!strchr(pax_c, '\\')); if ( 0 == strncmp("~.", pax_c, 2) ) { From 60f1a44910221dfb97f493169d25957764efd9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 11:14:54 -0600 Subject: [PATCH 15/34] unix: remove extra layer of conditional --- pkg/urbit/vere/io/unix.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 9ec342bf0..a18d0fa0f 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -167,9 +167,7 @@ _unix_knot_to_string(u3_atom pon) || c3_s2('.','.') == pon ); c3_c* ret_c = c3_malloc(met_w + add_w + 1); - if ( add_w ) { - memcpy(ret_c, "~.", 2); - } + memcpy(ret_c, "~.", add_w); u3r_bytes(0, met_w, (c3_y*)ret_c + add_w, pon); ret_c[met_w + add_w] = 0; // |(((sane %ta) '/') ((sane %ta) '\\')) -> %.n From 443315f401954a9d88de622740981cadd0ed503a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 12:25:42 -0600 Subject: [PATCH 16/34] vere: rename u3_unix_{safe,cane} --- pkg/urbit/daemon/main.c | 2 +- pkg/urbit/include/c/defs.h | 14 +++++++------- pkg/urbit/include/vere/vere.h | 4 ++-- pkg/urbit/tests/unix_tests.c | 26 +++++++++++++------------- pkg/urbit/vere/db/lmdb.c | 2 +- pkg/urbit/vere/foil.c | 2 +- pkg/urbit/vere/io/unix.c | 4 ++-- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index b3afde9f0..3454b7110 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -72,7 +72,7 @@ _main_repath(c3_c* pax_c) fprintf(stderr, "invalid path %s\n", pax_c); return 0; } - c3_assert(u3_unix_safe(fas_c + 1)); + c3_assert(u3_unix_cane(fas_c + 1)); *fas_c = 0; dir_c = realpath(pax_c, 0); *fas_c = '/'; diff --git a/pkg/urbit/include/c/defs.h b/pkg/urbit/include/c/defs.h index 69fd43f65..470d01227 100644 --- a/pkg/urbit/include/c/defs.h +++ b/pkg/urbit/include/c/defs.h @@ -125,24 +125,24 @@ /* Asserting unix fs wrappers. */ // defined in vere/io/unix.c. - c3_t u3_unix_safe(const c3_c* pax_c); + c3_t u3_unix_cane(const c3_c* pax_c); # define c3_open(a, ...) ({ \ - c3_assert(u3_unix_safe(a)); \ + c3_assert(u3_unix_cane(a)); \ open(a, __VA_ARGS__);}) # define c3_opendir(a) ({ \ - c3_assert(u3_unix_safe(a)); \ + c3_assert(u3_unix_cane(a)); \ opendir(a);}) # define c3_mkdir(a, b) ({ \ - c3_assert(u3_unix_safe(a)); \ + c3_assert(u3_unix_cane(a)); \ mkdir(a, b);}) # define c3_rmdir(a) ({ \ - c3_assert(u3_unix_safe(a)); \ + c3_assert(u3_unix_cane(a)); \ rmdir(a);}) # define c3_unlink(a) ({ \ - c3_assert(u3_unix_safe(a)); \ + c3_assert(u3_unix_cane(a)); \ unlink(a);}) # define c3_fopen(a, b) ({ \ - c3_assert(u3_unix_safe(a)); \ + c3_assert(u3_unix_cane(a)); \ fopen(a, b);}) #endif /* ifndef C3_DEFS_H */ diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index f294dd0ec..3bf787856 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -1168,10 +1168,10 @@ /** Storage, new school. **/ - /* u3_unix_safe(): true iff (unix) path is canonical. + /* u3_unix_cane(): true iff (unix) path is canonical. */ c3_t - u3_unix_safe(const c3_c* pax_c); + u3_unix_cane(const c3_c* pax_c); /* u3_unix_initial_into_card(): create initial filesystem sync card. */ diff --git a/pkg/urbit/tests/unix_tests.c b/pkg/urbit/tests/unix_tests.c index e67e9cf47..963e301a9 100644 --- a/pkg/urbit/tests/unix_tests.c +++ b/pkg/urbit/tests/unix_tests.c @@ -15,29 +15,29 @@ _test_safe() { c3_i ret_i = 1; - if ( !u3_unix_safe("a") || - !u3_unix_safe("a/b") || - !u3_unix_safe("a/b/c/defg/h/ijklmnop") ) + if ( !u3_unix_cane("a") || + !u3_unix_cane("a/b") || + !u3_unix_cane("a/b/c/defg/h/ijklmnop") ) { fprintf(stderr, "_safe fail 1\n"); ret_i = 0; } - if ( u3_unix_safe("") || - u3_unix_safe(".") || - u3_unix_safe("..") || - u3_unix_safe("/.") || - u3_unix_safe("a/b/c//") || - u3_unix_safe("a/b/.") || - u3_unix_safe("/././../.") || - u3_unix_safe("/../etc") ) + if ( u3_unix_cane("") || + u3_unix_cane(".") || + u3_unix_cane("..") || + u3_unix_cane("/.") || + u3_unix_cane("a/b/c//") || + u3_unix_cane("a/b/.") || + u3_unix_cane("/././../.") || + u3_unix_cane("/../etc") ) { fprintf(stderr, "_safe fail 2\r\n"); ret_i = 0; } - if ( !u3_unix_safe(".a") || - !u3_unix_safe("/.a.b.c/..c") ) + if ( !u3_unix_cane(".a") || + !u3_unix_cane("/.a.b.c/..c") ) { fprintf(stderr, "_safe fail 3\r\n"); ret_i = 0; diff --git a/pkg/urbit/vere/db/lmdb.c b/pkg/urbit/vere/db/lmdb.c index 11d3e67b4..308ba3783 100644 --- a/pkg/urbit/vere/db/lmdb.c +++ b/pkg/urbit/vere/db/lmdb.c @@ -42,7 +42,7 @@ u3_lmdb_init(const c3_c* pax_c, size_t siz_i) MDB_env* env_u; c3_w ret_w; - c3_assert(u3_unix_safe(pax_c)); + c3_assert(u3_unix_cane(pax_c)); if ( (ret_w = mdb_env_create(&env_u)) ) { mdb_logerror(stderr, ret_w, "lmdb: init fail"); diff --git a/pkg/urbit/vere/foil.c b/pkg/urbit/vere/foil.c index 8161a4507..f8a7c406a 100644 --- a/pkg/urbit/vere/foil.c +++ b/pkg/urbit/vere/foil.c @@ -84,7 +84,7 @@ u3_foil_folder(const c3_c* pax_c) uv_dirent_t den_u; c3_i err_i; - c3_assert(u3_unix_safe(pax_c)); + c3_assert(u3_unix_cane(pax_c)); /* open directory, synchronously */ diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index a18d0fa0f..edef8798e 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -73,10 +73,10 @@ struct _u3_ufil; void u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all); -/* u3_unix_safe(): true iff (unix) path is canonical. +/* u3_unix_cane(): true iff (unix) path is canonical. */ c3_t -u3_unix_safe(const c3_c* pax_c) +u3_unix_cane(const c3_c* pax_c) { if ( 0 == pax_c ) { return 0; From 7fc9db8c9a62779b9789c66a84aad1b57fa79711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 12:28:45 -0600 Subject: [PATCH 17/34] unix: reformat comments --- pkg/urbit/vere/io/unix.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index edef8798e..e6423f495 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -196,7 +196,7 @@ _unix_down(c3_c* pax_c, c3_c* sub_c) /* _unix_string_to_path(): convert c string to u3_noun +path ** -** c string must begin with the pier path plus mountpoint +** c string must begin with the pier path plus mountpoint */ static u3_noun _unix_string_to_path_helper(c3_c* pax_c) @@ -573,7 +573,7 @@ _unix_free_dir(u3_udir *dir_u) /* _unix_free_node(): free node, deleting everything within ** -** also deletes from parent list if in it +** also deletes from parent list if in it */ static u3_noun _unix_free_node(u3_unix* unx_u, u3_unod* nod_u) @@ -617,11 +617,11 @@ _unix_free_node(u3_unix* unx_u, u3_unod* nod_u) /* _unix_free_mount_point(): free mount point ** -** this process needs to happen in a very careful order. in particular, -** we must recurse before we get to the callback, so that libuv does all -** the child directories before it does us. +** this process needs to happen in a very careful order. in +** particular, we must recurse before we get to the callback, so +** that libuv does all the child directories before it does us. ** -** tread carefully +** tread carefully */ static void _unix_free_mount_point(u3_unix* unx_u, u3_umon* mon_u) @@ -762,11 +762,12 @@ static u3_noun _unix_update_node(u3_unix* unx_u, u3_unod* nod_u); /* _unix_update_file(): update file, producing list of changes ** -** when scanning through files, if dry, do nothing. otherwise, mark as -** dry, then check if file exists. if not, remove self from node list -** and add path plus sig to %into event. otherwise, read the file and -** get a mug checksum. if same as gum_w, move on. otherwise, overwrite -** add path plus data to %into event. +** when scanning through files, if dry, do nothing. otherwise, +** mark as dry, then check if file exists. if not, remove +** self from node list and add path plus sig to %into event. +** otherwise, read the file and get a mug checksum. if same as +** gum_w, move on. otherwise, overwrite add path plus data to +** %into event. */ static u3_noun _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) @@ -836,8 +837,8 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) /* _unix_update_dir(): update directory, producing list of changes ** -** when changing this, consider whether to also change -** _unix_initial_update_dir() +** when changing this, consider whether to also change +** _unix_initial_update_dir() */ static u3_noun _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) @@ -1042,7 +1043,7 @@ _unix_update_mount(u3_unix* unx_u, u3_umon* mon_u, u3_noun all) } /* _unix_initial_update_file(): read file, but don't watch -** XX deduplicate with _unix_update_file() +** XX deduplicate with _unix_update_file() */ static u3_noun _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) @@ -1098,7 +1099,7 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) } /* _unix_initial_update_dir(): read directory, but don't watch -** XX deduplicate with _unix_update_dir() +** XX deduplicate with _unix_update_dir() */ static u3_noun _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) From b8277be5b23fb2bb8979f649021b846391d7432d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 13:19:32 -0600 Subject: [PATCH 18/34] vere: remove walk, move save to unix --- pkg/urbit/include/vere/vere.h | 32 +--- pkg/urbit/vere/io/term.c | 29 +-- pkg/urbit/vere/io/unix.c | 77 ++++++++ pkg/urbit/vere/pier.c | 9 +- pkg/urbit/vere/walk.c | 326 ---------------------------------- 5 files changed, 91 insertions(+), 382 deletions(-) delete mode 100644 pkg/urbit/vere/walk.c diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index 3bf787856..5f1ad15e0 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -1034,33 +1034,6 @@ void u3_lord_peek(u3_lord* god_u, u3_pico* pic_u); - /** Filesystem (new api). - **/ - /* u3_walk_load(): load file or bail. - */ - u3_noun - u3_walk_load(c3_c* pas_c); - - /* u3_walk_safe(): load file or 0. - */ - u3_noun - u3_walk_safe(c3_c* pas_c); - - /* u3_walk_save(): save file or bail. - */ - void - u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax); - - /* u3_walk(): traverse `dir_c` to produce an arch, updating `old`. - */ - u3_noun - u3_walk(const c3_c* dir_c, u3_noun old); - - /* u3_path(): C unix path in computer for file or directory. - */ - c3_c* - u3_path(c3_o fyl, u3_noun pax); - /** Filesystem (async) **/ /* u3_foil_folder(): load directory, blockingly. create if nonexistent. @@ -1168,6 +1141,11 @@ /** Storage, new school. **/ + /* u3_unix_save(): save file undir .../.urb/[bas_m] or bail. + */ + void + u3_unix_save(c3_m bas_m, c3_c* pax_c, u3_atom pad); + /* u3_unix_cane(): true iff (unix) path is canonical. */ c3_t diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index fcccf748a..a4c16daed 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -549,14 +549,13 @@ _term_it_show_more(u3_utty* uty_u) /* _term_it_path(): path for console file. */ static c3_c* -_term_it_path(c3_o fyl, u3_noun pax) +_term_it_path(u3_noun pax) { - c3_w len_w; + c3_w len_w = 0; c3_c *pas_c; // measure // - len_w = strlen(u3_Host.dir_c); { u3_noun wiz = pax; @@ -569,7 +568,6 @@ _term_it_path(c3_o fyl, u3_noun pax) // cut // pas_c = c3_malloc(len_w + 1); - strncpy(pas_c, u3_Host.dir_c, len_w); pas_c[len_w] = '\0'; { u3_noun wiz = pax; @@ -578,7 +576,7 @@ _term_it_path(c3_o fyl, u3_noun pax) while ( u3_nul != wiz ) { c3_w tis_w = u3r_met(3, u3h(wiz)); - if ( (c3y == fyl) && (u3_nul == u3t(wiz)) ) { + if ( (u3_nul == u3t(wiz)) ) { *waq_c++ = '.'; } else *waq_c++ = '/'; @@ -598,27 +596,10 @@ _term_it_path(c3_o fyl, u3_noun pax) static void _term_it_save(u3_noun pax, u3_noun pad) { - c3_c* pax_c; - c3_c* bas_c = 0; - c3_w xap_w = u3kb_lent(u3k(pax)); - u3_noun xap = u3_nul; - u3_noun urb = c3_s4('.','u','r','b'); - u3_noun put = c3_s3('p','u','t'); - - // directory base and relative path - if ( 2 < xap_w ) { - u3_noun bas = u3nt(urb, put, u3_nul); - bas_c = _term_it_path(c3n, bas); - xap = u3qb_scag(xap_w - 2, pax); - } - - pax = u3nt(urb, put, pax); - pax_c = _term_it_path(c3y, pax); - - u3_walk_save(pax_c, 0, pad, bas_c, xap); + c3_c* pax_c = _term_it_path(pax); + u3_unix_save(c3__put, pax_c, pad); c3_free(pax_c); - c3_free(bas_c); } /* _term_ovum_plan(): plan term ovums, configuring spinner. diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index e6423f495..26067ea56 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -243,6 +243,83 @@ _unix_string_to_path(u3_unix* unx_u, c3_c* pax_c) } } +/* _unix_mkdirp(): recursive mkdir of dirname of pax_c. +*/ +static void +_unix_mkdirp(c3_c* pax_c) +{ + c3_c* fas_c = strchr(pax_c + 1, '/'); + + while ( fas_c ) { + *fas_c = 0; + if ( 0 != mkdir(pax_c, 0777) && EEXIST != errno ) { + u3l_log("unix: mkdir %s: %s\n", pax_c, strerror(errno)); + u3m_bail(c3__fail); + } + *fas_c++ = '/'; + fas_c = strchr(fas_c, '/'); + } +} + +/* u3_unix_save(): save file under .../.urb/[bas_m] or bail. +** +** XX this is quite bad, and doesn't share much in common with +** the rest of unix.c. at minimum it should instead take pax as +** a noun and build the C path from that. it would also be nice +** if it could take a u3_udir or something corresponding to the +** base directory. +*/ +void +u3_unix_save(c3_m bas_m, c3_c* pax_c, u3_atom pad) +{ + c3_i fid_i; + c3_w lod_w, len_w, fln_w, rit_w; + c3_y* pad_y; + c3_c* ful_c; + + c3_assert(3 == u3r_met(3, bas_m)); + c3_assert(c3_s3('b','h','k') != bas_m && + c3_s3('c','h','k') != bas_m && + c3_s3('g','e','t') != bas_m && + c3_s3('l','o','g') != bas_m); + if ( '/' == *pax_c) { + pax_c++; + } + if ( !u3_unix_cane(pax_c) ) { + u3l_log("%s: non-canonical path\n", pax_c); + u3z(pad); u3m_bail(c3__fail); + } + lod_w = strlen(u3_Host.dir_c); + len_w = lod_w + sizeof("/.urb/xxx/") + strlen(pax_c); + ful_c = c3_malloc(len_w); + rit_w = snprintf(ful_c, len_w, "%s/.urb/xxx/%s", u3_Host.dir_c, pax_c); + c3_assert(len_w == rit_w + 1); + u3r_bytes(0, 3, (c3_y*)ful_c + lod_w + sizeof("/.urb/") - 1, bas_m); + + _unix_mkdirp(ful_c); + fid_i = c3_open(ful_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if ( fid_i < 0 ) { + u3l_log("%s: %s\n", ful_c, strerror(errno)); + c3_free(ful_c); + u3z(pad); u3m_bail(c3__fail); + } + + fln_w = u3r_met(3, pad); + pad_y = c3_malloc(fln_w); + u3r_bytes(0, fln_w, pad_y, pad); + u3z(pad); + rit_w = write(fid_i, pad_y, fln_w); + close(fid_i); + c3_free(pad_y); + + if ( rit_w != fln_w ) { + u3l_log("%s: %s\n", ful_c, strerror(errno)); + c3_free(ful_c); + u3m_bail(c3__fail); + } + c3_free(ful_c); +} + /* _unix_rm_r_cb(): callback to delete individual files/directories */ static c3_i diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index 9aad54105..2f7fc5b85 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -526,12 +526,11 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) // if serialization and export path succeeded, write to disk // if ( (u3_none != out) && (u3_none != pad) ) { - c3_c fil_c[2048]; - snprintf(fil_c, 2048, "%s/.urb/put/%s.%s", - pir_u->pax_c, pac_c+1, ext_c); + c3_c fil_c[256]; + snprintf(fil_c, 256, "%s.%s", pac_c + 1, ext_c); - u3_walk_save(fil_c, 0, out, pir_u->pax_c, pad); - u3l_log("pier: scry result in %s\n", fil_c); + u3_unix_save(c3__put, fil_c, pad); + u3l_log("pier: scry result in %s/.urb/put/%s\n", u3_Host.dir_c, fil_c); } } diff --git a/pkg/urbit/vere/walk.c b/pkg/urbit/vere/walk.c deleted file mode 100644 index 1e0eb1f47..000000000 --- a/pkg/urbit/vere/walk.c +++ /dev/null @@ -1,326 +0,0 @@ -/* vere/walk.c -** -*/ -#include "all.h" -#include "vere/vere.h" - - /* |% - ** ++ arch :: fs node - ** $% [& p=@uvI q=*] :: file, hash/data - ** [| p=(map ,@ta arch)] :: directory - ** == :: - ** -- - */ - -#if 0 -static u3_noun -_walk_ok(u3_noun nod) -{ - u3_noun don = u3n_mung(u3k(u2A->toy.arch), u3k(nod)); - - if ( c3n == u3_sing(nod, don) ) { - c3_assert(0); - } - u3z(don); - return nod; -} -#endif - -/* u3_walk_safe(): load file or 0. -*/ -u3_noun -u3_walk_safe(c3_c* pas_c) -{ - struct stat buf_b; - c3_i fid_i = c3_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) ) { - // u3l_log("%s: %s\n", pas_c, strerror(errno)); - return 0; - } - fln_w = buf_b.st_size; - pad_y = c3_malloc(buf_b.st_size); - - red_w = read(fid_i, pad_y, fln_w); - close(fid_i); - - if ( fln_w != red_w ) { - c3_free(pad_y); - return 0; - } - else { - u3_noun pad = u3i_bytes(fln_w, (c3_y *)pad_y); - c3_free(pad_y); - - return pad; - } -} - -/* u3_walk_load(): load file or bail. -*/ -u3_noun -u3_walk_load(c3_c* pas_c) -{ - struct stat buf_b; - c3_i fid_i = c3_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) ) { - u3l_log("%s: %s\n", pas_c, strerror(errno)); - return u3m_bail(c3__fail); - } - fln_w = buf_b.st_size; - pad_y = c3_malloc(buf_b.st_size); - - red_w = read(fid_i, pad_y, fln_w); - close(fid_i); - - if ( fln_w != red_w ) { - c3_free(pad_y); - u3l_log("u3_walk_load failed"); - return u3m_bail(c3__fail); - } - else { - u3_noun pad = u3i_bytes(fln_w, (c3_y *)pad_y); - c3_free(pad_y); - - return pad; - } -} - -/* _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); - strcpy(pax_c, bas_c); - - 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 != c3_mkdir(pax_c, 0755) && EEXIST != errno ) { - u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno)); - u3m_bail(c3__fail); - } - - _walk_mkdirp(pax_c, u3t(pax)); - c3_free(pax_c); -} - -/* u3_walk_save(): save file or bail. -*/ -void -u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax) -{ - c3_i fid_i = c3_open(pas_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); - c3_w fln_w, rit_w; - c3_y* pad_y; - - if ( fid_i < 0 ) { - if ( ENOENT == errno && u3_nul != pax ) { - _walk_mkdirp(bas_c, pax); - return u3_walk_save(pas_c, tim, pad, 0, u3_nul); - } - - u3l_log("%s: %s\n", pas_c, strerror(errno)); - u3m_bail(c3__fail); - } - - fln_w = u3r_met(3, pad); - pad_y = c3_malloc(fln_w); - u3r_bytes(0, fln_w, pad_y, pad); - u3z(pad); - u3z(pax); - - rit_w = write(fid_i, pad_y, fln_w); - close(fid_i); - c3_free(pad_y); - - if ( rit_w != fln_w ) { - u3l_log("%s: %s\n", pas_c, strerror(errno)); - u3m_bail(c3__fail); - } - - if ( 0 != tim ) { - struct timeval tim_tv[2]; - - u3_time_out_tv(&tim_tv[0], u3k(tim)); - u3_time_out_tv(&tim_tv[1], tim); - - utimes(pas_c, tim_tv); - } -} - -/* _walk_in(): inner loop of _walk(), producing map. -*/ -static u3_noun -_walk_in(const c3_c* dir_c, c3_w len_w) -{ - DIR* dir_d = c3_opendir(dir_c); - u3_noun map = u3_nul; - - if ( !dir_d ) { - return u3_nul; - } - else while ( 1 ) { - struct dirent ent_n; - struct dirent* out_n; - - if ( u3_readdir_r(dir_d, &ent_n, &out_n) != 0 ) { - u3l_log("%s: %s\n", dir_c, strerror(errno)); - break; - } - else if ( !out_n ) { - break; - } - else if ( !strcmp(out_n->d_name, ".") || - !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); - c3_c* pat_c = c3_malloc(lef_w + 1); - struct stat buf_b; - - strncpy(pat_c, dir_c, lef_w); - pat_c[len_w] = '/'; - strncpy(pat_c + len_w + 1, fil_c, lef_w); - pat_c[lef_w] = '\0'; - - if ( 0 != stat(pat_c, &buf_b) ) { - c3_free(pat_c); - } else { - u3_noun tim = c3_stat_mtime(&buf_b); - - 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; - { - u3_noun nam = u3i_string(nam_c); - u3_noun ext = u3i_string(ext_c); - u3_noun get = u3kdb_get(u3k(map), u3k(nam)); - u3_noun dat = u3_walk_load(pat_c); - u3_noun hax; - - if ( !strcmp("noun", ext_c) ) { - dat = u3ke_cue(dat); - } - hax = u3do("sham", u3k(dat)); - if ( u3_none == get ) { get = u3_nul; } - - get = u3kdb_put(get, ext, u3nt(c3y, hax, dat)); - map = u3kdb_put(map, nam, u3nc(c3n, get)); - } - c3_free(nam_c); - c3_free(ext_c); - } - else { - u3_noun dir = _walk_in(pat_c, lef_w); - - if ( u3_nul != dir ) { - map = u3kdb_put - (map, u3i_string(fil_c), u3nc(c3n, dir)); - } - else u3z(tim); - } - c3_free(pat_c); - } - } - } - closedir(dir_d); - return map; -} - -/* u3_walk(): traverse `dir_c` to produce an arch, updating `old`. -*/ -u3_noun -u3_walk(const c3_c* dir_c, u3_noun old) -{ - // XX - obviously, cheaper to update old data. - u3z(old); - { - struct stat buf_b; - - if ( 0 != stat(dir_c, &buf_b) ) { - u3l_log("can't stat %s\n", dir_c); - // return u3m_bail(c3__fail); - c3_assert(0); - } - else { - return u3nc(c3n, - _walk_in(dir_c, strlen(dir_c))); - } - } -} - -/* u3_path(): C unix path in computer for file or directory. -*/ -c3_c* -u3_path(c3_o fyl, u3_noun pax) -{ - c3_w len_w; - c3_c *pas_c; - - // measure - // - len_w = strlen(u3_Local); - { - u3_noun wiz = pax; - - while ( u3_nul != wiz ) { - len_w += (1 + u3r_met(3, u3h(wiz))); - wiz = u3t(wiz); - } - } - - // cut - // - pas_c = c3_malloc(len_w + 1); - strncpy(pas_c, u3_Local, len_w); - pas_c[len_w] = '\0'; - { - u3_noun wiz = pax; - c3_c* waq_c = (pas_c + strlen(pas_c)); - - while ( u3_nul != wiz ) { - c3_w tis_w = u3r_met(3, u3h(wiz)); - - if ( (c3y == fyl) && (u3_nul == u3t(wiz)) ) { - *waq_c++ = '.'; - } else *waq_c++ = '/'; - - u3r_bytes(0, tis_w, (c3_y*)waq_c, u3h(wiz)); - waq_c += tis_w; - - wiz = u3t(wiz); - } - *waq_c = 0; - } - u3z(pax); - return pas_c; -} From ca1ed3d7a16e1cb78a7f902ff39b0e60fe818a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 13:21:50 -0600 Subject: [PATCH 19/34] vere: remove 'new' from header comments 'New' is relative; some of these subsystems were 'new' in 2015. --- pkg/urbit/include/vere/vere.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index 5f1ad15e0..32e1cc9b5 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -328,7 +328,7 @@ void (*bot_f)(); // call when chis is up } u3_host; // host == computer == process - /** New pier system. + /** Pier system. **/ /* u3_ovum_news: u3_ovum lifecycle events */ @@ -755,7 +755,7 @@ c3_d u3_time_gap_ms(u3_noun now, u3_noun wen); - /** ward: common structure lifecycle + /** Common structure lifecycle. **/ /* u3_dent_init(): initialize file record. */ @@ -840,7 +840,7 @@ c3_w u3_mcut_host(c3_c* buf_c, c3_w len_w, u3_noun hot); - /** New vere + /** IO drivers. **/ /* u3_auto_init(): initialize all drivers. */ @@ -1034,14 +1034,14 @@ void u3_lord_peek(u3_lord* god_u, u3_pico* pic_u); - /** Filesystem (async) + /** Filesystem (async). **/ /* u3_foil_folder(): load directory, blockingly. create if nonexistent. */ u3_dire* u3_foil_folder(const c3_c* pax_c); // directory object, or 0 - /** Terminal, new style. + /** Terminal. **/ /* u3_term_start_spinner(): prepare spinner state. RETAIN. */ @@ -1139,7 +1139,7 @@ u3_save_io_exit(u3_pier *pir_u); - /** Storage, new school. + /** Storage. **/ /* u3_unix_save(): save file undir .../.urb/[bas_m] or bail. */ @@ -1182,14 +1182,14 @@ u3_auto* u3_cttp_io_init(u3_pier* pir_u); - /** fore, first events + /** fore, first events. **/ /* u3_hind_io_init(): initialize fore */ u3_auto* u3_fore_io_init(u3_pier* pir_u); - /** hind, defaults + /** hind, defaults. **/ /* u3_hind_io_init(): initialize hint */ @@ -1292,7 +1292,7 @@ void u3_pier_info(u3_pier* pir_u); - /* u3_pier_boot(): start the new pier system. + /* u3_pier_boot(): start the pier. */ u3_pier* u3_pier_boot(c3_w wag_w, // config flags @@ -1302,7 +1302,7 @@ u3_noun pax, // path to pier u3_weak fed); // extra private keys - /* u3_pier_stay(): restart the new pier system. + /* u3_pier_stay(): restart the pier. */ u3_pier* u3_pier_stay(c3_w wag_w, u3_noun pax); From 6b5361d7df64de6745c30d4f71f4349f1d91c4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 13:49:51 -0600 Subject: [PATCH 20/34] unix: code review feedback --- pkg/urbit/vere/io/unix.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 26067ea56..345ef6e15 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -81,15 +81,15 @@ u3_unix_cane(const c3_c* pax_c) if ( 0 == pax_c ) { return 0; } - // allow root. - // - if ( 0 == strcmp("/", pax_c) ) { - return 1; - } // allow absolute paths. // if ( '/' == *pax_c ) { pax_c++; + // allow root. + // + if ( 0 == *pax_c ) { + return 1; + } } do { if ( 0 == *pax_c @@ -158,20 +158,23 @@ _unix_string_to_knot(c3_c* pax_c) static c3_c* _unix_knot_to_string(u3_atom pon) { - c3_w met_w = u3r_met(3, pon); - c3_w add_w = 2 * - ( 0 == met_w - || ( '~' == u3r_byte(0, pon) - && '.' == u3r_byte(1, pon) ) - || c3_s1('.') == pon - || c3_s2('.','.') == pon ); - c3_c* ret_c = c3_malloc(met_w + add_w + 1); + c3_c* ret_c; - memcpy(ret_c, "~.", add_w); - u3r_bytes(0, met_w, (c3_y*)ret_c + add_w, pon); - ret_c[met_w + add_w] = 0; - // |(((sane %ta) '/') ((sane %ta) '\\')) -> %.n - // + if ( u3_nul != pon + && c3_s1('.') != pon + && c3_s2('.','.') != pon + && !( '~' == u3r_byte(0, pon) + && '.' == u3r_byte(1, pon) ) ) + { + ret_c = u3r_string(pon); + } + else { + c3_w met_w = u3r_met(3, pon); + + ret_c = malloc(met_w + 3); + memcpy(ret_c, "~.", 2); + u3r_bytes(0, met_w, ret_c + 2, pon); + } c3_assert(!strchr(ret_c, '/')); c3_assert(!strchr(ret_c, '\\')); return ret_c; From 9172b3dfe870c387d3635c926fab951b89fecdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 13:52:44 -0600 Subject: [PATCH 21/34] unix: c3_ --- pkg/urbit/vere/io/unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 345ef6e15..e0e39471a 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -171,7 +171,7 @@ _unix_knot_to_string(u3_atom pon) else { c3_w met_w = u3r_met(3, pon); - ret_c = malloc(met_w + 3); + ret_c = c3_malloc(met_w + 3); memcpy(ret_c, "~.", 2); u3r_bytes(0, met_w, ret_c + 2, pon); } From 2b05fa2ebe13fdec375222b156a0fa5ed06d3fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 13:53:22 -0600 Subject: [PATCH 22/34] unix: use $ for types --- pkg/urbit/vere/io/unix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index e0e39471a..56f463384 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -136,7 +136,7 @@ u3_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) return(0); } -/* _unix_string_to_knot(): convert c unix path component to +knot +/* _unix_string_to_knot(): convert c unix path component to $knot */ static u3_atom _unix_string_to_knot(c3_c* pax_c) @@ -153,7 +153,7 @@ _unix_string_to_knot(c3_c* pax_c) return u3i_string(pax_c); } -/* _unix_knot_to_string(): convert +knot to c unix path component +/* _unix_knot_to_string(): convert $knot to c unix path component */ static c3_c* _unix_knot_to_string(u3_atom pon) @@ -197,7 +197,7 @@ _unix_down(c3_c* pax_c, c3_c* sub_c) return don_c; } -/* _unix_string_to_path(): convert c string to u3_noun +path +/* _unix_string_to_path(): convert c string to u3_noun $path ** ** c string must begin with the pier path plus mountpoint */ From c83d9b9c1e83e9ea878f108a829e3c3acc42a71e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 14:03:34 -0600 Subject: [PATCH 23/34] unix: hard-code %put base directory --- pkg/urbit/include/vere/vere.h | 4 ++-- pkg/urbit/vere/io/term.c | 2 +- pkg/urbit/vere/io/unix.c | 14 ++++---------- pkg/urbit/vere/pier.c | 2 +- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index 32e1cc9b5..f835c60be 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -1141,10 +1141,10 @@ /** Storage. **/ - /* u3_unix_save(): save file undir .../.urb/[bas_m] or bail. + /* u3_unix_save(): save file undir .../.urb/put or bail. */ void - u3_unix_save(c3_m bas_m, c3_c* pax_c, u3_atom pad); + u3_unix_save(c3_c* pax_c, u3_atom pad); /* u3_unix_cane(): true iff (unix) path is canonical. */ diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index a4c16daed..f2eff77a4 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -598,7 +598,7 @@ _term_it_save(u3_noun pax, u3_noun pad) { c3_c* pax_c = _term_it_path(pax); - u3_unix_save(c3__put, pax_c, pad); + u3_unix_save(pax_c, pad); c3_free(pax_c); } diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 56f463384..c9b6e04f7 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -264,7 +264,7 @@ _unix_mkdirp(c3_c* pax_c) } } -/* u3_unix_save(): save file under .../.urb/[bas_m] or bail. +/* u3_unix_save(): save file under .../.urb/put or bail. ** ** XX this is quite bad, and doesn't share much in common with ** the rest of unix.c. at minimum it should instead take pax as @@ -273,18 +273,13 @@ _unix_mkdirp(c3_c* pax_c) ** base directory. */ void -u3_unix_save(c3_m bas_m, c3_c* pax_c, u3_atom pad) +u3_unix_save(c3_c* pax_c, u3_atom pad) { c3_i fid_i; c3_w lod_w, len_w, fln_w, rit_w; c3_y* pad_y; c3_c* ful_c; - c3_assert(3 == u3r_met(3, bas_m)); - c3_assert(c3_s3('b','h','k') != bas_m && - c3_s3('c','h','k') != bas_m && - c3_s3('g','e','t') != bas_m && - c3_s3('l','o','g') != bas_m); if ( '/' == *pax_c) { pax_c++; } @@ -293,11 +288,10 @@ u3_unix_save(c3_m bas_m, c3_c* pax_c, u3_atom pad) u3z(pad); u3m_bail(c3__fail); } lod_w = strlen(u3_Host.dir_c); - len_w = lod_w + sizeof("/.urb/xxx/") + strlen(pax_c); + len_w = lod_w + sizeof("/.urb/put/") + strlen(pax_c); ful_c = c3_malloc(len_w); - rit_w = snprintf(ful_c, len_w, "%s/.urb/xxx/%s", u3_Host.dir_c, pax_c); + rit_w = snprintf(ful_c, len_w, "%s/.urb/put/%s", u3_Host.dir_c, pax_c); c3_assert(len_w == rit_w + 1); - u3r_bytes(0, 3, (c3_y*)ful_c + lod_w + sizeof("/.urb/") - 1, bas_m); _unix_mkdirp(ful_c); fid_i = c3_open(ful_c, O_WRONLY | O_CREAT | O_TRUNC, 0666); diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index 2f7fc5b85..0cdf9abdb 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -529,7 +529,7 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) c3_c fil_c[256]; snprintf(fil_c, 256, "%s.%s", pac_c + 1, ext_c); - u3_unix_save(c3__put, fil_c, pad); + u3_unix_save(fil_c, pad); u3l_log("pier: scry result in %s/.urb/put/%s\n", u3_Host.dir_c, fil_c); } } From 8191955effd0b265629feb8347858dbec5f0bc0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 14:18:14 -0600 Subject: [PATCH 24/34] unix: reorder checks --- pkg/urbit/vere/io/unix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index c9b6e04f7..a66d28d49 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -1037,8 +1037,8 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) c3_w len_w = strlen(out_u->d_name); if ( !strchr(out_u->d_name,'.') - || !_unix_sane_ta(unx_u, out_u->d_name, len_w) - || '~' == out_u->d_name[len_w - 1] ) + || '~' == out_u->d_name[len_w - 1] + || !_unix_sane_ta(unx_u, out_u->d_name, len_w) ) { c3_free(pax_c); continue; From 3f1c526d2e04d139dfdaa1c733fddab75a2e5229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 14:19:27 -0600 Subject: [PATCH 25/34] main: repath scry path --- pkg/urbit/daemon/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index 3454b7110..ffc6e858a 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -129,7 +129,7 @@ _main_getopt(c3_i argc, c3_c** argv) break; } case 'Y': { - u3_Host.ops_u.puk_c = strdup(optarg); + u3_Host.ops_u.puk_c = _main_repath(optarg); break; } case 'Z': { From eaf47d95c5853b8de69976a8a21d503fde1c65d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 14:23:39 -0600 Subject: [PATCH 26/34] unix: test cases --- pkg/urbit/tests/unix_tests.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/urbit/tests/unix_tests.c b/pkg/urbit/tests/unix_tests.c index 963e301a9..ca247f5ef 100644 --- a/pkg/urbit/tests/unix_tests.c +++ b/pkg/urbit/tests/unix_tests.c @@ -15,7 +15,9 @@ _test_safe() { c3_i ret_i = 1; - if ( !u3_unix_cane("a") || + if ( !u3_unix_cane("/") || + !u3_unix_cane("~.") || + !u3_unix_cane("a") || !u3_unix_cane("a/b") || !u3_unix_cane("a/b/c/defg/h/ijklmnop") ) { From 6c5d7133f1b704ad893537025adee3460718fcb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 14:25:22 -0600 Subject: [PATCH 27/34] unix: fix compile warning --- pkg/urbit/vere/io/unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index a66d28d49..b3c5c66df 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -173,7 +173,7 @@ _unix_knot_to_string(u3_atom pon) ret_c = c3_malloc(met_w + 3); memcpy(ret_c, "~.", 2); - u3r_bytes(0, met_w, ret_c + 2, pon); + u3r_bytes(0, met_w, (c3_y*)ret_c + 2, pon); } c3_assert(!strchr(ret_c, '/')); c3_assert(!strchr(ret_c, '\\')); From 0375646a93d0c5a363d3874e96d4fe91d0f534e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 16:34:09 -0600 Subject: [PATCH 28/34] unix: cane before root removal --- pkg/urbit/vere/io/unix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index b3c5c66df..3fe736a96 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -280,13 +280,13 @@ u3_unix_save(c3_c* pax_c, u3_atom pad) c3_y* pad_y; c3_c* ful_c; - if ( '/' == *pax_c) { - pax_c++; - } if ( !u3_unix_cane(pax_c) ) { u3l_log("%s: non-canonical path\n", pax_c); u3z(pad); u3m_bail(c3__fail); } + if ( '/' == *pax_c) { + pax_c++; + } lod_w = strlen(u3_Host.dir_c); len_w = lod_w + sizeof("/.urb/put/") + strlen(pax_c); ful_c = c3_malloc(len_w); From 5591752f9c9c5870c4c1fa66e76b8e16edd52e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 17:02:18 -0600 Subject: [PATCH 29/34] main: support files in cwd --- pkg/urbit/daemon/main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index ffc6e858a..68eec734e 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -64,13 +64,20 @@ _main_repath(c3_c* pax_c) c3_c* dir_c; c3_w len_w; + c3_assert(pax_c); if ( 0 != (rel_c = realpath(pax_c, 0)) ) { return rel_c; } fas_c = strrchr(pax_c, '/'); if ( !fas_c ) { - fprintf(stderr, "invalid path %s\n", pax_c); - return 0; + c3_c* rec_c = c3_malloc(strlen(pax_c) + 3); + c3_c* ret_c; + + strcpy(rec_c, "./"); + strcat(rec_c, pax_c); + ret_c = _main_repath(rec_c); + c3_free(rec_c); + return ret_c; } c3_assert(u3_unix_cane(fas_c + 1)); *fas_c = 0; From 46a1139e7077c9f5c9e657e9b2d94926436da813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 17:26:07 -0600 Subject: [PATCH 30/34] main: repath cleanup --- pkg/urbit/daemon/main.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index 68eec734e..bd3e41634 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -63,6 +63,7 @@ _main_repath(c3_c* pax_c) c3_c* fas_c; c3_c* dir_c; c3_w len_w; + c3_i wit_i; c3_assert(pax_c); if ( 0 != (rel_c = realpath(pax_c, 0)) ) { @@ -70,14 +71,11 @@ _main_repath(c3_c* pax_c) } fas_c = strrchr(pax_c, '/'); if ( !fas_c ) { - c3_c* rec_c = c3_malloc(strlen(pax_c) + 3); - c3_c* ret_c; + c3_c rec_c[2048]; - strcpy(rec_c, "./"); - strcat(rec_c, pax_c); - ret_c = _main_repath(rec_c); - c3_free(rec_c); - return ret_c; + wit_i = snprintf(rec_c, sizeof(rec_c), "./%s", pax_c); + c3_assert(sizeof(rec_c) > wit_i); + return _main_repath(rec_c); } c3_assert(u3_unix_cane(fas_c + 1)); *fas_c = 0; @@ -88,9 +86,9 @@ _main_repath(c3_c* pax_c) } len_w = strlen(dir_c) + strlen(fas_c) + 1; rel_c = c3_malloc(len_w); - strcpy(rel_c, dir_c); + wit_i = snprintf(rel_c, len_w, "%s%s", dir_c, fas_c); + c3_assert(len_w == wit_i + 1); c3_free(dir_c); - strcat(rel_c, fas_c); return rel_c; } From 4a74b9b13f9505007ee6d2b3a1eff03fdac15d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 20:52:42 -0600 Subject: [PATCH 31/34] unix: fix regression in _unix_scan_mount_point We previously checked for '#' at strlen(out_u->d_name) - 1 here. So just go ahead and do (sane %ta) on the whole out_u->d_name. --- pkg/urbit/vere/io/unix.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 3fe736a96..52c05ff03 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -590,10 +590,12 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) } } else { + c3_w lod_w = strlen(out_u->d_name); + if ( '.' != out_u->d_name[len_w] || '\0' == out_u->d_name[len_w + 1] - || '~' == out_u->d_name[strlen(out_u->d_name) - 1] - || !_unix_sane_ta(unx_u, out_u->d_name, len_w) ) + || '~' == out_u->d_name[lod_w - 1] + || !_unix_sane_ta(unx_u, out_u->d_name, lod_w) ) { c3_free(pax_c); continue; From 7b6e89fc1550b1eb1e7e14627a7c4fc27d78dd99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Jan 2022 23:07:13 -0600 Subject: [PATCH 32/34] unix: comment with suggestions for future --- pkg/urbit/vere/io/unix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 52c05ff03..ab90f35e6 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -267,10 +267,10 @@ _unix_mkdirp(c3_c* pax_c) /* u3_unix_save(): save file under .../.urb/put or bail. ** ** XX this is quite bad, and doesn't share much in common with -** the rest of unix.c. at minimum it should instead take pax as -** a noun and build the C path from that. it would also be nice -** if it could take a u3_udir or something corresponding to the -** base directory. +** the rest of unix.c. a refactor would probably share common +** logic with _unix_sync_change, perhaps using openat, making +** unx_u optional, and/or having a flag to not track the file +** for future changes. */ void u3_unix_save(c3_c* pax_c, u3_atom pad) From 118363450106e37eb99d5eadaa17e989e98db19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Tue, 1 Feb 2022 12:02:51 -0600 Subject: [PATCH 33/34] unix: knot mapping that is not a valid @ta '~.' was a pun with the @ta encoding, which could cause people to get confused about how the mapping actually worked. I had previusly wanted the escape sequence to be a valid @ta, since I had wanted to check that path components were (sane %ta) prior to doing $knot conversion. However @joemfb mentioned that it was desirable to have it not be a valid @ta so that if someone messed up the encoding in the future, the paths would be detectably wrong. This necessitates calling _unix_knot_to_string on unsanitized input, which means we can no longer assume that it won't contain non-(sane %ta) characters, which means we can no longer assert that '\\' is not in the string on Linux. Also added a seemingly forgotten null byte to _unix_knot_to_string. --- pkg/urbit/vere/io/unix.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index ab90f35e6..a88192412 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -106,15 +106,15 @@ u3_unix_cane(const c3_c* pax_c) return 1; } -/* _unix_sane_ta(): true iff all len_w characters of pax_c are (sane %ta). +/* _unix_sane_ta(): true iff pat is a valid @ta ** ** %ta is parsed by: ** (star ;~(pose nud low hep dot sig cab)) */ static c3_t -_unix_sane_ta(u3_unix* unx_u, c3_c* pax_c, c3_w len_w) +_unix_sane_ta(u3_unix* unx_u, u3_atom pat) { - return _(u3n_slam_on(u3k(unx_u->sat), u3i_bytes(len_w, (c3_y*)pax_c))); + return _(u3n_slam_on(u3k(unx_u->sat), pat)); } /* u3_readdir_r(): @@ -146,14 +146,18 @@ _unix_string_to_knot(c3_c* pax_c) // // c3_assert(*pax_c); c3_assert(!strchr(pax_c, '/')); + // XX horrible + // +# ifdef _WIN32 c3_assert(!strchr(pax_c, '\\')); - if ( 0 == strncmp("~.", pax_c, 2) ) { - pax_c += 2; +# endif + if ( '!' == *pax_c ) { + pax_c++; } return u3i_string(pax_c); } -/* _unix_knot_to_string(): convert $knot to c unix path component +/* _unix_knot_to_string(): convert $knot to c unix path component. RETAIN. */ static c3_c* _unix_knot_to_string(u3_atom pon) @@ -163,20 +167,22 @@ _unix_knot_to_string(u3_atom pon) if ( u3_nul != pon && c3_s1('.') != pon && c3_s2('.','.') != pon - && !( '~' == u3r_byte(0, pon) - && '.' == u3r_byte(1, pon) ) ) + && '!' != u3r_byte(0, pon) ) { ret_c = u3r_string(pon); } else { c3_w met_w = u3r_met(3, pon); - ret_c = c3_malloc(met_w + 3); - memcpy(ret_c, "~.", 2); - u3r_bytes(0, met_w, (c3_y*)ret_c + 2, pon); + ret_c = c3_malloc(met_w + 2); + *ret_c = '!'; + u3r_bytes(0, met_w, (c3_y*)ret_c + 1, pon); + ret_c[met_w + 1] = 0; } c3_assert(!strchr(ret_c, '/')); +# ifdef _WIN32 c3_assert(!strchr(ret_c, '\\')); +# endif return ret_c; } @@ -590,12 +596,10 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) } } else { - c3_w lod_w = strlen(out_u->d_name); - if ( '.' != out_u->d_name[len_w] || '\0' == out_u->d_name[len_w + 1] - || '~' == out_u->d_name[lod_w - 1] - || !_unix_sane_ta(unx_u, out_u->d_name, lod_w) ) + || '~' == out_u->d_name[strlen(out_u->d_name) - 1] + || !_unix_sane_ta(unx_u, _unix_string_to_knot(out_u->d_name)) ) { c3_free(pax_c); continue; @@ -1036,11 +1040,9 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( !nod_u ) { if ( !S_ISDIR(buf_u.st_mode) ) { - c3_w len_w = strlen(out_u->d_name); - if ( !strchr(out_u->d_name,'.') - || '~' == out_u->d_name[len_w - 1] - || !_unix_sane_ta(unx_u, out_u->d_name, len_w) ) + || '~' == out_u->d_name[strlen(out_u->d_name) - 1] + || !_unix_sane_ta(unx_u, _unix_string_to_knot(out_u->d_name)) ) { c3_free(pax_c); continue; From ed0c66a43cf82ce4fc5640a2880f1fbb78859937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Wed, 9 Feb 2022 14:56:10 -0600 Subject: [PATCH 34/34] vere: comments around fs wrappers and unix.c --- pkg/urbit/include/c/defs.h | 8 ++++++++ pkg/urbit/vere/io/unix.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/pkg/urbit/include/c/defs.h b/pkg/urbit/include/c/defs.h index 470d01227..54f28a1b1 100644 --- a/pkg/urbit/include/c/defs.h +++ b/pkg/urbit/include/c/defs.h @@ -123,6 +123,14 @@ rut;}) /* Asserting unix fs wrappers. + ** + ** these all crash the process if passed a non-canonical + ** path (i.e., one containing '.', '..', or the empty path + ** component), so make sure you don't pass them one. if you + ** find yourself fighting with them, then please delete them + ** and do a sed search-and-replace to remove the `c3_` from + ** their call sites; their goal is to decrease maintenance + ** burden, not increase it. */ // defined in vere/io/unix.c. c3_t u3_unix_cane(const c3_c* pax_c); diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index a88192412..f9e175b5d 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -1,5 +1,36 @@ /* vere/unix.c ** +** this file is responsible for maintaining a bidirectional +** mapping between the contents of a clay desk and a directory +** in a unix filesystem. +** +** TODO this driver is crufty and overdue for a rewrite. +** aspirationally, the rewrite should do sanity checking and +** transformations at the noun level to convert messages from +** arvo into sets of fs operations on trusted inputs, and +** inverse transformations and checks for fs contents to arvo +** messages. +** +** the two relevant transformations to apply are: +** +** 1. bidirectionally map file contents to atoms +** 2. bidirectionally map arvo $path <-> unix relative paths +** +** the first transform is trivial. the second poses some +** challenges: an arvo $path is a list of $knot, and the $knot +** space intersects with invalid unix paths in the three cases +** of: %$ (the empty knot), '.', and '..'. we escape these by +** prepending a '!' to the filename corresponding to the $knot, +** yielding unix files named '!', '!.', and '!..'. +** +** there is also the case of the empty path. we elide empty +** paths from this wrapper, which always uses the last path +** component as the file extension/mime-type. +** +** these transforms are implemented, but they ought to be +** implemented in one place, prior to any fs calls; as-is, they +** are sprinkled throughout the file updating code. +** */ #include "all.h" #include