/* _unix_hot_gain(): gain ship. */ static void _unix_hot_gain(u2_noun who, u2_bean mek) { u2_noun hox = u2_dc("scot", 'p', who); c3_c* hox_c = u2_cr_string(hox); c3_c* pax_c = _unix_down(u2_Host.ops_u.hom_c, hox_c + 1); DIR* rid_u = opendir(pax_c); if ( !rid_u ) { if ( u2_yes == mek ) { _unix_mkdir(pax_c); } else return; } else closedir(rid_u); // uL(fprintf(uH, "GAIN %s\n", pax_c)); free(hox_c); u2z(hox); u2_unix_acquire(pax_c); { u2_uhot* hot_u = malloc(sizeof(u2_uhot)); _unix_dir_watch(&hot_u->dir_u, 0, pax_c); u2_cr_mp(hot_u->who_mp, who); hot_u->nex_u = u2_Host.unx_u.hot_u; u2_Host.unx_u.hot_u = hot_u; } }
/* _unix_home(): find home directory from identity. */ static u2_uhot* _unix_home(u2_noun who) { u2_unix* unx_u = &u2_Host.unx_u; u2_uhot* hot_u; mpz_t who_mp; u2_cr_mp(who_mp, who); for ( hot_u = unx_u->hot_u; hot_u && (0 != mpz_cmp(who_mp, hot_u->who_mp)); hot_u = hot_u->nex_u ) { // uL(fprintf(uH, "uh: %p, %s\n", hot_u, hot_u->dir_u.pax_c)); } mpz_clear(who_mp); return hot_u; }
/* _unix_desk_sync_tofu(): sync out file install. */ static void _unix_desk_sync_tofu(u2_udir* dir_u, u2_noun pre, u2_noun ext, u2_noun mis) { c3_c* pox_c = _unix_file_form(dir_u, u2k(pre), u2_no, u2k(ext)); c3_c* pux_c = _unix_file_form(dir_u, u2k(pre), u2_yes, u2k(ext)); u2_ufil** fil_u; // uL(fprintf(uH, "tofu pox_c %s op %s\n", pox_c, u2_cr_string(u2h(mis)))); fil_u = &(dir_u->fil_u); while ( 1 ) { // XX crude! if ( !*fil_u || !strcmp((*fil_u)->pax_c, pox_c) || !strcmp((*fil_u)->pax_c, pux_c) ) { break; } else fil_u = &((*fil_u)->nex_u); } if ( *fil_u && (c3__del == u2h(mis)) ) { u2_ufil* ded_u = *fil_u; *fil_u = ded_u->nex_u; _unix_unlink(ded_u->pax_c); _unix_file_free(ded_u); free(ded_u); free(pox_c); free(pux_c); } else { u2_noun god, oat; c3_c* pax_c; if ( *fil_u ) { u2_noun old = _unix_file_load(*fil_u); c3_assert(c3__mut == u2h(mis)); god = _unix_desk_sync_udon(u2k(u2t(mis)), old); _unix_unlink((*fil_u)->pax_c); free((*fil_u)->pax_c); } else { c3_assert(c3__ins == u2h(mis)); god = u2k(u2t(mis)); } if ( u2_yes == u2du(god) ) { oat = u2_cke_jam(god); pax_c = pux_c; free(pox_c); } else { oat = god; pax_c = pox_c; free(pux_c); } if ( *fil_u ) { (*fil_u)->dot_c = (pax_c + ((*fil_u)->dot_c - (*fil_u)->pax_c)); (*fil_u)->pax_c = pax_c; mpz_clear((*fil_u)->mod_mp); u2_cr_mp((*fil_u)->mod_mp, u2A->now); } else { mpz_t mod_mp; u2_cr_mp(mod_mp, u2A->now); *fil_u = malloc(sizeof(u2_ufil)); _unix_file_watch(*fil_u, dir_u, pax_c, mod_mp); mpz_clear(mod_mp); } _unix_save((*fil_u)->pax_c, oat); } u2z(pre); u2z(ext); u2z(mis); }
/* _unix_dir_update(): update directory, true if changed. */ static u2_bean _unix_dir_update(u2_udir* dir_u, DIR* rid_u) { u2_bean cha = u2_no; // uL(fprintf(uH, "dir_update ON %s\n", dir_u->pax_c)); /* use dry bits as markers */ { u2_udir* dis_u; u2_ufil* fil_u; for ( dis_u = dir_u->dis_u; dis_u; dis_u = dis_u->nex_u ) { dis_u->dry = u2_yes; } for ( fil_u = dir_u->fil_u; fil_u; fil_u = fil_u->nex_u ) { fil_u->dry = u2_yes; } } /* iterate through directory, opening and updating */ while ( 1 ) { struct dirent ent_u; struct dirent* out_u; if ( readdir_r(rid_u, &ent_u, &out_u) != 0 ) { uL(fprintf(uH, "%s: %s\n", dir_u->pax_c, strerror(errno))); c3_assert(0); } else if ( !out_u ) { break; } else if ( ('.' == out_u->d_name[0]) ) { // XX screws up some paths continue; } else { c3_c* pax_c = _unix_down(dir_u->pax_c, out_u->d_name); struct stat buf_u; // uL(fprintf(uH, " in %s\n", pax_c)); if ( 0 != stat(pax_c, &buf_u) ) { free(pax_c); continue; } else { if ( !S_ISDIR(buf_u.st_mode) ) { mpz_t mod_mp; u2_ufil* fil_u; { u2_noun mod = c3_stat_mtime(&buf_u); u2_cr_mp(mod_mp, mod); u2z(mod); } for ( fil_u = dir_u->fil_u; fil_u; fil_u = fil_u->nex_u ) { if ( !strcmp(pax_c, fil_u->pax_c) ) { fil_u->dry = u2_no; cha = u2_or(cha, _unix_file_update(fil_u, mod_mp)); break; } } if ( !fil_u ) { fil_u = malloc(sizeof(u2_ufil)); // uL(fprintf(uH, "found file %s\n", pax_c)); _unix_file_watch(fil_u, dir_u, pax_c, mod_mp); fil_u->nex_u = dir_u->fil_u; dir_u->fil_u = fil_u; cha = u2_yes; } mpz_clear(mod_mp); } else { DIR* red_u = _unix_opendir(pax_c); u2_udir* dis_u; for ( dis_u = dir_u->dis_u; dis_u; dis_u = dis_u->nex_u ) { if ( !strcmp(pax_c, dis_u->pax_c) ) { dis_u->dry = u2_no; cha = u2_or(cha, _unix_dir_update(dis_u, red_u)); break; } } if ( !dis_u ) { dis_u = malloc(sizeof(u2_udir)); // uL(fprintf(uH, "found directory %s\n", pax_c)); _unix_dir_watch(dis_u, dir_u, pax_c); _unix_dir_update(dis_u, red_u); dis_u->nex_u = dir_u->dis_u; dir_u->dis_u = dis_u; cha = u2_yes; } } } } } /* use dry bits as markers */ { u2_udir** dis_u; u2_ufil** fil_u; for ( dis_u = &(dir_u->dis_u); *dis_u; ) { if ( u2_no == (*dis_u)->dry ) { (*dis_u)->dry = u2_yes; dis_u = &(*dis_u)->nex_u; } else { u2_udir* ded_u = *dis_u; u2_udir* nex_u = ded_u->nex_u; // uL(fprintf(uH, "removed directory %s\n", ded_u->pax_c)); _unix_dir_free(ded_u); free(ded_u); *dis_u = nex_u; cha = u2_yes; } } for ( fil_u = &(dir_u->fil_u); *fil_u; ) { if ( u2_no == (*fil_u)->dry ) { fil_u = &(*fil_u)->nex_u; } else { u2_ufil* ded_u = *fil_u; u2_ufil* nex_u = ded_u->nex_u; // uL(fprintf(uH, "removed file %s\n", ded_u->pax_c)); _unix_file_free(ded_u); free(ded_u); *fil_u = nex_u; cha = u2_yes; } } } closedir(rid_u); // uL(fprintf(uH, "dir_update OFF %s\n", dir_u->pax_c)); return cha; }
/* u2_unix_ef_look(): update the root. */ void u2_unix_ef_look(void) { u2_unix* unx_u = &u2_Host.unx_u; u2_noun won; u2_uhot* hot_u; // find owners without directories { for ( won = u2A->own; u2_nul != won; won = u2t(won) ) { u2_noun who = u2h(won); mpz_t who_mp; u2_cr_mp(who_mp, who); for ( hot_u = unx_u->hot_u; hot_u && (0 != mpz_cmp(who_mp, hot_u->who_mp)); hot_u = hot_u->nex_u ); mpz_clear(who_mp); if ( 0 == hot_u ) { _unix_hot_gain(u2k(who), u2_no); } } } // find directories without owners { u2_uhot** het_u = &(unx_u->hot_u); while ( 0 != (hot_u=*het_u) ) { for ( won = u2A->own; u2_nul != won; won = u2t(won) ) { u2_noun who = u2h(won); mpz_t who_mp; u2_cr_mp(who_mp, who); if ( 0 == mpz_cmp(who_mp, hot_u->who_mp) ) { break; } mpz_clear(who_mp); } if ( u2_nul == won ) { *het_u = hot_u->nex_u; // uL(fprintf(uH, "sync: lose %s\n", hot_u->dir_u.pax_c)); _unix_hot_lose(hot_u); free(hot_u); continue; } else { het_u = &(hot_u->nex_u); } } } // update all ships { u2_uhot* hot_u; for ( hot_u = unx_u->hot_u; hot_u; hot_u = hot_u->nex_u ) { _unix_ship_update(hot_u); } } }
/* _unix_dir_update(): update directory. */ static void _unix_dir_update(u2_udir* dir_u, DIR* rid_u) { if ( u2_yes == dir_u->dry ) { return; } else { // Update all wet subdirectories. // u2_udir** dis_u; u2_ufil** fil_u; for ( dis_u = &(dir_u->dis_u); *dis_u; ) { if ( u2_yes == (*dis_u)->dry ) { dis_u = &(*dis_u)->nex_u; } else { DIR* red_u = opendir((*dis_u)->pax_c); if ( 0 == red_u ) { u2_udir* ded_u = *dis_u; u2_udir* nex_u = ded_u->nex_u; // uL(fprintf(uH, "removed directory %s\n", ded_u->pax_c)); _unix_dir_free(ded_u); *dis_u = nex_u; } else { _unix_dir_update(*dis_u, red_u); closedir(red_u); dis_u = &(*dis_u)->nex_u; } } } // Check all wet files to see if they need deleting. // for ( fil_u = &(dir_u->fil_u); *fil_u; ) { if ( u2_yes == (*fil_u)->dry ) { fil_u = &(*fil_u)->nex_u; } else { struct stat buf_u; if ( -1 == stat((*fil_u)->pax_c, &buf_u) || !(S_IFREG & buf_u.st_mode) ) { u2_ufil* ded_u = *fil_u; u2_ufil* nex_u = ded_u->nex_u; // uL(fprintf(uH, "removed file %s\n", ded_u->pax_c)); _unix_file_free(ded_u); *fil_u = nex_u; } else { fil_u = &(*fil_u)->nex_u; } } } // Scan for new files/directories. XX - this is O(n^2) brute // force, and could be done by smarter event processing. // while ( 1 ) { struct dirent ent_u; struct dirent* out_u; if ( readdir_r(rid_u, &ent_u, &out_u) != 0 ) { // uL(fprintf(uH, "%s: %s\n", dir_u->pax_c, strerror(errno))); c3_assert(0); } else if ( !out_u ) { break; } else if ( ('.' == out_u->d_name[0]) ) { // XX screws up some paths continue; } else { c3_c* pax_c = _unix_down(dir_u->pax_c, out_u->d_name); struct stat buf_u; // uL(fprintf(uH, " in %s\n", pax_c)); if ( 0 != stat(pax_c, &buf_u) ) { free(pax_c); continue; } else { if ( !S_ISDIR(buf_u.st_mode) ) { mpz_t mod_mp; u2_ufil* fil_u; if ( ( NULL == strrchr(out_u->d_name, '.')) || ( '~' == out_u->d_name[strlen(out_u->d_name) - 1] ) ) { continue; } { u2_noun mod = c3_stat_mtime(&buf_u); u2_cr_mp(mod_mp, mod); u2z(mod); } for ( fil_u = dir_u->fil_u; fil_u; fil_u = fil_u->nex_u ) { if ( !strcmp(pax_c, fil_u->pax_c) ) { break; } } if ( !fil_u ) { fil_u = c3_malloc(sizeof(u2_ufil)); // uL(fprintf(uH, "found file %s\n", pax_c)); _unix_file_watch(fil_u, dir_u, pax_c, mod_mp); fil_u->nex_u = dir_u->fil_u; dir_u->fil_u = fil_u; } mpz_clear(mod_mp); } else { u2_udir* dis_u; for ( dis_u = dir_u->dis_u; dis_u; dis_u = dis_u->nex_u ) { if ( !strcmp(pax_c, dis_u->pax_c) ) { break; } } if ( !dis_u ) { DIR* red_u = _unix_opendir(pax_c); dis_u = c3_malloc(sizeof(u2_udir)); // uL(fprintf(uH, "found directory %s\n", pax_c)); _unix_dir_watch(dis_u, dir_u, pax_c); _unix_dir_update(dis_u, red_u); dis_u->nex_u = dir_u->dis_u; dir_u->dis_u = dis_u; closedir(red_u); } else { free(pax_c); } } } } } } }
/* u2_unix_ef_look(): update the root. */ void u2_unix_ef_look(void) { u2_unix* unx_u = &u2_Host.unx_u; u2_noun won; u2_uhot* hot_u; if ( u2_nul != u2A->roe ) { // We can't generate a working %into event here because there // are other events, possibly containing %into, that are queued; // they will change the state of %clay and cause a patch that // doesn't work. // return; } // find owners without directories { for ( won = u2A->own; u2_nul != won; won = u2t(won) ) { u2_noun who = u2h(won); mpz_t who_mp; u2_cr_mp(who_mp, who); for ( hot_u = unx_u->hot_u; hot_u && (0 != mpz_cmp(who_mp, hot_u->who_mp)); hot_u = hot_u->nex_u ); mpz_clear(who_mp); if ( 0 == hot_u ) { _unix_hot_gain(u2k(who), u2_no); } } } // find directories without owners { u2_uhot** het_u = &(unx_u->hot_u); while ( 0 != (hot_u=*het_u) ) { for ( won = u2A->own; u2_nul != won; won = u2t(won) ) { u2_noun who = u2h(won); mpz_t who_mp; c3_w cmp_w; u2_cr_mp(who_mp, who); cmp_w = mpz_cmp(who_mp, hot_u->who_mp); mpz_clear(who_mp); if ( 0 == cmp_w ) { break; } } if ( u2_nul == won ) { *het_u = hot_u->nex_u; // uL(fprintf(uH, "sync: lose %s\n", hot_u->dir_u.pax_c)); _unix_hot_lose(hot_u); free(hot_u); continue; } else { het_u = &(hot_u->nex_u); } } } // update all ships { u2_uhot* hot_u; for ( hot_u = unx_u->hot_u; hot_u; hot_u = hot_u->nex_u ) { _unix_ship_update(hot_u); } } }
/* _unix_desk_sync_tofu(): sync out file install. */ static void _unix_desk_sync_tofu(u2_udir* dir_u, u2_noun pre, u2_noun ext, u2_noun mis) { c3_c* pox_c = _unix_file_form(dir_u, u2k(pre), u2_no, u2k(ext)); c3_c* pux_c = _unix_file_form(dir_u, u2k(pre), u2_yes, u2k(ext)); u2_ufil** fil_u; // uL(fprintf(uH, "tofu pox_c %s op %s\n", pox_c, u2_cr_string(u2h(mis)))); #ifdef SYNCLOG c3_w slot = u2_Host.unx_u.lot_w++ % 1024; free(u2_Host.unx_u.sylo[slot].pax_c); u2_Host.unx_u.sylo[slot].pax_c = 0; #endif fil_u = &(dir_u->fil_u); while ( 1 ) { // XX crude! if ( !*fil_u || !strcmp((*fil_u)->pax_c, pox_c) || !strcmp((*fil_u)->pax_c, pux_c) ) { break; } else fil_u = &((*fil_u)->nex_u); } if ( *fil_u && (c3__del == u2h(mis)) ) { u2_ufil* ded_u = *fil_u; #ifdef SYNCLOG u2_Host.unx_u.sylo[slot].unx = u2_no; u2_Host.unx_u.sylo[slot].wer_m = c3_s4('t','o','f','u'); u2_Host.unx_u.sylo[slot].wot_m = c3__del; u2_Host.unx_u.sylo[slot].pax_c = strdup(ded_u->pax_c); #endif *fil_u = ded_u->nex_u; _unix_unlink(ded_u->pax_c); _unix_file_free(ded_u); free(pox_c); free(pux_c); } else { u2_noun god, oat; c3_c* pax_c; if ( *fil_u ) { u2_noun old = _unix_file_load(*fil_u); c3_assert(c3__mut == u2h(mis)); god = _unix_desk_sync_udon(u2k(u2t(mis)), old); _unix_unlink((*fil_u)->pax_c); free((*fil_u)->pax_c); } else { c3_assert(c3__ins == u2h(mis)); god = u2k(u2t(mis)); } if ( u2_yes == u2du(god) ) { oat = u2_cke_jam(god); pax_c = pux_c; free(pox_c); } else { oat = god; pax_c = pox_c; free(pux_c); } #ifdef SYNCLOG u2_Host.unx_u.sylo[slot].unx = u2_no; u2_Host.unx_u.sylo[slot].wer_m = c3_s4('t','o','f','u'); u2_Host.unx_u.sylo[slot].wot_m = u2h(mis); u2_Host.unx_u.sylo[slot].pax_c = strdup(pax_c); #endif _unix_save(pax_c, oat); if ( *fil_u ) { (*fil_u)->dot_c = (pax_c + ((*fil_u)->dot_c - (*fil_u)->pax_c)); (*fil_u)->pax_c = pax_c; mpz_clear((*fil_u)->mod_mp); u2_cr_mp((*fil_u)->mod_mp, u2A->now); } else { mpz_t mod_mp; u2_cr_mp(mod_mp, u2A->now); *fil_u = c3_malloc(sizeof(u2_ufil)); _unix_file_watch(*fil_u, dir_u, pax_c, mod_mp); mpz_clear(mod_mp); } } u2z(pre); u2z(ext); u2z(mis); }