Merge pull request #5575 from urbit/jo/unix-sane

vere/unix: sane(r) path handling
This commit is contained in:
Jōshin 2022-03-02 10:00:05 -08:00 committed by GitHub
commit 6ed6fdfc6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 599 additions and 631 deletions

View File

@ -350,8 +350,9 @@ 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);
}
long sysconf(int name)

View File

@ -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) ) {

View File

@ -55,6 +55,44 @@ _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;
c3_assert(pax_c);
if ( 0 != (rel_c = realpath(pax_c, 0)) ) {
return rel_c;
}
fas_c = strrchr(pax_c, '/');
if ( !fas_c ) {
c3_c rec_c[2048];
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;
dir_c = realpath(pax_c, 0);
*fas_c = '/';
if ( 0 == dir_c ) {
return 0;
}
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);
c3_assert(len_w == wit_i + 1);
c3_free(dir_c);
return rel_c;
}
/* _main_getopt(): extract option map from command line.
*/
static u3_noun
@ -139,7 +177,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': {
@ -147,11 +185,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': {
@ -163,7 +201,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': {
@ -171,7 +209,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': {
@ -209,7 +247,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': {
@ -231,7 +269,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; }
@ -291,7 +329,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)
@ -705,31 +743,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 ) {

View File

@ -122,4 +122,35 @@
} \
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);
# define c3_open(a, ...) ({ \
c3_assert(u3_unix_cane(a)); \
open(a, __VA_ARGS__);})
# define c3_opendir(a) ({ \
c3_assert(u3_unix_cane(a)); \
opendir(a);})
# define c3_mkdir(a, b) ({ \
c3_assert(u3_unix_cane(a)); \
mkdir(a, b);})
# define c3_rmdir(a) ({ \
c3_assert(u3_unix_cane(a)); \
rmdir(a);})
# define c3_unlink(a) ({ \
c3_assert(u3_unix_cane(a)); \
unlink(a);})
# define c3_fopen(a, b) ({ \
c3_assert(u3_unix_cane(a)); \
fopen(a, b);})
#endif /* ifndef C3_DEFS_H */

View File

@ -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.

View File

@ -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,41 +1034,14 @@
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)
/** 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.
*/
@ -1166,8 +1139,18 @@
u3_save_io_exit(u3_pier *pir_u);
/** Storage, new school.
/** Storage.
**/
/* u3_unix_save(): save file undir .../.urb/put or bail.
*/
void
u3_unix_save(c3_c* pax_c, u3_atom pad);
/* u3_unix_cane(): true iff (unix) path is canonical.
*/
c3_t
u3_unix_cane(const c3_c* pax_c);
/* u3_unix_initial_into_card(): create initial filesystem sync card.
*/
u3_noun
@ -1199,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
*/
@ -1309,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
@ -1319,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);

View File

@ -239,17 +239,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 {
@ -333,20 +333,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);
}
}
@ -359,10 +359,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.
@ -431,18 +431,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();
@ -838,7 +838,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));
}
@ -847,15 +847,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;
}
@ -863,11 +863,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);

View File

@ -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 ) {

View File

@ -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;

View File

@ -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, "[ ");

View File

@ -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);

View File

@ -0,0 +1,65 @@
#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_cane("/") ||
!u3_unix_cane("~.") ||
!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_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_cane(".a") ||
!u3_unix_cane("/.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;
}

View File

@ -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);
}

View File

@ -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_cane(pax_c));
if ( (ret_w = mdb_env_create(&env_u)) ) {
mdb_logerror(stderr, ret_w, "lmdb: init fail");
return 0;

View File

@ -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
//
{
@ -721,11 +815,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);
}

View File

@ -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_cane(pax_c));
/* open directory, synchronously
*/
{

View File

@ -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);
}

View File

@ -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(pax_c, pad);
c3_free(pax_c);
c3_free(bas_c);
}
/* _term_ovum_plan(): plan term ovums, configuring spinner.

View File

@ -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 <ftw.h>
@ -58,6 +89,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 {
@ -72,6 +104,50 @@ struct _u3_ufil;
void
u3_unix_ef_look(u3_unix* unx_u, u3_noun mon, u3_noun all);
/* u3_unix_cane(): true iff (unix) path is canonical.
*/
c3_t
u3_unix_cane(const c3_c* pax_c)
{
if ( 0 == pax_c ) {
return 0;
}
// allow absolute paths.
//
if ( '/' == *pax_c ) {
pax_c++;
// allow root.
//
if ( 0 == *pax_c ) {
return 1;
}
}
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;
}
/* _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, u3_atom pat)
{
return _(u3n_slam_on(u3k(unx_u->sat), pat));
}
/* u3_readdir_r():
*/
c3_w
@ -91,6 +167,56 @@ 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);
// XX this can happen if we encounter a file without an extension.
//
// c3_assert(*pax_c);
c3_assert(!strchr(pax_c, '/'));
// XX horrible
//
# ifdef _WIN32
c3_assert(!strchr(pax_c, '\\'));
# endif
if ( '!' == *pax_c ) {
pax_c++;
}
return u3i_string(pax_c);
}
/* _unix_knot_to_string(): convert $knot to c unix path component. RETAIN.
*/
static c3_c*
_unix_knot_to_string(u3_atom pon)
{
c3_c* ret_c;
if ( u3_nul != pon
&& c3_s1('.') != pon
&& c3_s2('.','.') != 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 + 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;
}
/* _unix_down(): descend path.
*/
static c3_c*
@ -108,29 +234,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
*
* c string must begin with the pier path plus mountpoint
/* _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
@ -144,7 +275,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 {
@ -152,6 +283,77 @@ _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/put or bail.
**
** XX this is quite bad, and doesn't share much in common with
** 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)
{
c3_i fid_i;
c3_w lod_w, len_w, fln_w, rit_w;
c3_y* pad_y;
c3_c* ful_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);
rit_w = snprintf(ful_c, len_w, "%s/.urb/put/%s", u3_Host.dir_c, pax_c);
c3_assert(len_w == rit_w + 1);
_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
@ -165,7 +367,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);
@ -181,7 +383,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);
}
@ -213,7 +415,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);
}
@ -224,7 +426,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;
@ -267,7 +469,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;
@ -339,7 +541,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;
@ -374,7 +576,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));
@ -428,9 +630,8 @@ _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(unx_u, _unix_string_to_knot(out_u->d_name)) )
{
c3_free(pax_c);
continue;
}
@ -452,7 +653,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);
}
@ -482,8 +683,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)
@ -526,12 +727,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)
@ -559,7 +760,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;
@ -651,7 +852,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);
@ -671,12 +872,13 @@ _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)
@ -690,7 +892,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;
@ -745,9 +947,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)
@ -773,7 +975,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);
@ -786,7 +988,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 ) {
@ -813,7 +1015,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));
@ -871,9 +1073,8 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_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])
) {
|| !_unix_sane_ta(unx_u, _unix_string_to_knot(out_u->d_name)) )
{
c3_free(pax_c);
continue;
}
@ -942,7 +1143,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));
}
@ -956,7 +1158,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;
@ -1013,7 +1215,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));
@ -1089,8 +1291,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);
@ -1174,7 +1376,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;
@ -1207,7 +1409,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,
@ -1263,98 +1465,24 @@ 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 = 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);
unlink(paf_c);
}
if ( NULL == (loq_u = 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");
unlink(paf_c);
c3_free(paf_c);
}
/* u3_unix_ef_look(): update the root of a specific mount point.
*/
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);
}
@ -1431,10 +1559,7 @@ _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);
u3z(unx_u->sat);
c3_free(unx_u->pax_c);
c3_free(unx_u);
}
@ -1449,10 +1574,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;
// XX move to disk.c?
//
u3_unix_acquire(unx_u->pax_c);
unx_u->sat = u3do("sane", c3__ta);
u3_auto* car_u = &unx_u->car_u;
car_u->nam_m = c3__unix;

View File

@ -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);

View File

@ -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(fil_c, pad);
u3l_log("pier: scry result in %s/.urb/put/%s\n", u3_Host.dir_c, fil_c);
}
}

View File

@ -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 = 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 = 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 != 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 = 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 = 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;
}

View File

@ -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);

View File

@ -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);