shrub/v/unix.c

683 lines
14 KiB
C
Raw Normal View History

2015-06-05 05:47:27 +03:00
// XXX where does mon_u in u3_unix get initialized?
// XXX _unix_string_to_path
// XXX aww, man, i do need parentage because of the dryness thing
// XXX _unix_dir_watch
// XXX _unix_file_watch
2013-09-29 00:21:18 +04:00
/* v/unix.c
**
** This file is in the public domain.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <setjmp.h>
#include <gmp.h>
#include <dirent.h>
#include <stdint.h>
#include <uv.h>
#include <termios.h>
#include <term.h>
#include <errno.h>
2015-02-27 09:35:41 +03:00
#include <libgen.h>
2013-09-29 00:21:18 +04:00
#include "all.h"
#include "v/vere.h"
2015-05-14 00:18:43 +03:00
/* undef this to turn off syncing out to unix */
#define ERGO_SYNC
2013-09-29 00:21:18 +04:00
/* _unix_down(): descend path.
*/
static c3_c*
_unix_down(c3_c* pax_c, c3_c* sub_c)
{
c3_w pax_w = strlen(pax_c);
c3_w sub_w = strlen(sub_c);
2014-04-02 04:47:01 +04:00
c3_c* don_c = c3_malloc(pax_w + strlen(sub_c) + 2);
2013-09-29 00:21:18 +04:00
strncpy(don_c, pax_c, pax_w + 1);
2013-09-29 00:21:18 +04:00
don_c[pax_w] = '/';
strncpy(don_c + pax_w + 1, sub_c, sub_w + 1);
don_c[pax_w + sub_w + 1] = '\0';
2013-09-29 00:21:18 +04:00
return don_c;
}
/* _unix_mkdir(): mkdir, asserting.
2013-09-29 00:21:18 +04:00
*/
static void
_unix_mkdir(c3_c* pax_c)
2013-09-29 00:21:18 +04:00
{
if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno) {
2015-03-05 03:36:29 +03:00
uL(fprintf(uH, "error mkdiring %s: %s\n", pax_c, strerror(errno)));
2013-09-29 00:21:18 +04:00
c3_assert(0);
}
}
/* _unix_opendir(): opendir, recreating if nonexistent.
2013-09-29 00:21:18 +04:00
*/
static DIR*
_unix_opendir(c3_c* pax_c)
2013-09-29 00:21:18 +04:00
{
DIR* rid_u = opendir(pax_c);
if ( !rid_u ) {
// uL(fprintf(uH, "%s: %s\n", pax_c, strerror(errno)));
_unix_mkdir(pax_c);
rid_u = opendir(pax_c);
if ( !rid_u ) {
uL(fprintf(uH, "%s: %s\n", pax_c, strerror(errno)));
c3_assert(0);
}
2013-09-29 00:21:18 +04:00
}
return rid_u;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_get_mount_point(): retrieve or create mount point
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
static u3_umon*
_unix_get_mount_point(u3_noun mon)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
if ( c3n == u3ud(mon) ) {
c3_assert(!"mount point must be an atom");
u3z(mon);
return NULL;
}
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
c3_c* nam_c = u3r_string(mon);
u3_umon* mon_u;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
for ( mon_u = u3_Host.unx_u.mon_u;
mon_u && 0 != strcmp(nam_c, mon_u->nam_c);
mon_u = mon_u->nex_u )
{
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
if ( 0 == u3_mon ) {
mon_u = malloc(sizeof(u3_umon));
mon_u->nam_c = nam_c;
mon_u->dir_u = malloc(sizeof(u3_udir));
mon_u->dir_u.dir = c3y;
mon_u->dir_u.dry = c3n;
mon_u->dir_u.pax_c = _unix_down(u3_Host.dir_c, nam_c);
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
/*
c3_w dir_w = strlen(u3_Host.dir_c)
c3_w nam_w = strlen(nam_c);
mon_u->dir_u.pax_c = malloc(sizeof(c3_c) * (dir_w + 1 + nam_w));
strncpy(mon_u->dir_u.pax_c, u3_Host.dir_c, dir_w);
mon_u->dir_u.pax_c[dir_w] = '/';
strncpy(mon_u->dir_u.pax_c+dir_w+1, nam_c, nam_w);
*/
mon_u->dir_u.nex_u = NULL;
mon_u->dir_u.kid_u = NULL;
mon_u->nex_u = u3_Host.unx_u.mon_u;
u3_Host.unx_u.mon_u = mon_u;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
free(nam_c);
u3z(mon);
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
return mon_u;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_free_node(): free node, deleting everything within
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
void
_unix_free_node(u3_unod* nod_u)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
if ( c3y == nod_u->dir_u ) {
uv_close((uv_handle_t*)&dir_u->was_u, _unix_free_dir);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
else {
uv_close((uv_handle_t*)&dir_u->was_u, _unix_free_file);
2013-09-29 00:21:18 +04:00
}
}
2015-06-05 05:47:27 +03:00
/* _unix_free_file(): free file, unlinking it
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
void
_unix_free_file(u3_ufil* fil_u)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
if ( 0 != unlink(fil_u->pax_c) && ENOENT != errno ) {
uL(fprintf(uH, "error unlinking %s: %s\n", fil_u->pax_c, strerror(errno)));
c3_assert(0);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
free(nod_u->pax_c);
free(nod_u);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_free_dir(): free directory, deleting everything within
2013-09-29 00:21:18 +04:00
*/
static void
2015-06-05 05:47:27 +03:00
_unix_free_dir(uv_handle_t* was_u)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
u3_udir* dir_u = (void*) was_u;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
u3_unod nod_u = dir_u->kid_u;
while ( nod_u ) {
u3_udir* nex_u = nod_u->nex_u;
_unix_free_node(nod_u);
nod_u = nex_u;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
if ( 0 != rmdir(dir_u->pax_c) && ENOENT != errno ) {
uL(fprintf(uH, "error rmdiring %s: %s\n", dir_u->pax_c, strerror(errno)));
2014-08-23 01:33:27 +04:00
c3_assert(0);
}
2015-06-05 05:47:27 +03:00
free(nod_u->pax_c);
free(nod_u);
}
/* _unix_free_mount_point(): free mount point
*/
void
_unix_free_mount_point(u3_umon* mon_u)
{
u3_unod nod_u;
for ( nod_u = mon_u->dir_u.kid_u; kid_u; kid_u = kid_u->nex_u ) {
_unix_free_node(kid_u);
2014-08-23 01:33:27 +04:00
}
2015-06-05 05:47:27 +03:00
free(mon_u->dir_u.pax_c);
free(mon_u->nam_c);
free(mon_u);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_delete_mount_point(): remove mount point from list and free
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
void
_unix_delete_mount_point(u3_noun mon)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
if ( c3n == u3ud(mon) ) {
c3_assert(!"mount point must be an atom");
u3z(mon);
return;
2014-08-21 02:09:51 +04:00
}
2015-06-05 05:47:27 +03:00
c3_c* nam_c = u3r_string(mon);
u3_umon* mon_u;
u3_umon* tem_u;
mon_u = u3_host.unx_u.mon_u;
if ( !mon_u ) {
uL(fprintf(uH, "mount point already gone: %s\r\n", nam_c));
goto _delete_mount_point_out;
}
if ( 0 == strcmp(nam_c, mon_u->nam_c) ) {
u3_Host.unx_u.mon_u = mon_u->nex_u;
_unix_free_mount_point(mon_u);
goto _delete_mount_point_out;
2014-08-21 02:09:51 +04:00
}
2015-06-05 05:47:27 +03:00
for ( ;
mon_u->nex_u && 0 != strcmp(nam_c, mon_u->nex_u->nam_c);
mon_u = mon_u->nex_u )
{
}
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
if ( !mon_u->nex_u ) {
uL(fprintf(uH, "mount point already gone: %s\r\n", nam_c));
goto _delete_mount_point_out;
}
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
tem_u = mon_u->nex_u;
mon_u->nex_u = mon_u->nex_u->nex_u;
_unix_free_mount_point(tem_u);
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
_delete_mount_point_out:
free(nam_c);
u3z(mon);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_node_update(): update node, producing list of changes
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
static u3_noun
_unix_node_update(u3_unod* nod_u)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
if ( c3y == dir_u->dir ) {
return _unix_dir_update((void*)nod_u);
}
else {
return _unix_file_update((void*)nod_u);
}
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_file_update(): 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 md5 checksum. if same as sum_w, move on. otherwise, overwrite
* sum_w with new md5sum and add path plus data to %into event.
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
static u3_noun
_unix_file_update(u3_ufil* fil_u)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
c3_assert( c3n == fil_u->dir );
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
if ( c3y == fil_u->dry ) {
return u3_nul;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
fil_u->dry = c3y;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
struct stat buf_u;
c3_i fid_i = open(fil_u->pax_c, O_RDONLY, 0644);
c3_w len_w;
c3_y* dat_y;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) {
if ( ENOENT == erno ) {
return u3nc(u3nc(pax, u3_nul), u3_nul)
}
else {
uL(fprintf(uH, "error opening file %s: %s\r\n",
fil_u->pax_c, strerror(errno)));
return u3_nul;
}
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
len_w = buf_u.st_size;
dat_y = c3_malloc(len_w);
red_w = read(fid_i, dat_y, len_w);
c3_i col_i = close(fid_i);
if ( col_i < 0 ) {
uL(fprintf(uH, "error closing file %s: %s\r\n",
fil_u->pax_c, strerror(errno)));
2013-09-29 00:21:18 +04:00
}
2014-03-03 02:31:03 +04:00
2015-06-05 05:47:27 +03:00
if ( len_w != red_w ) {
free(dat_y);
c3_assert(0);
return u3_nul;
}
else {
// XXX check md5
u3_noun pax = _unix_string_to_path(fil_u->pax_c);
u3_noun mim = u3nt(c3__text, u3i_string("plain"), u3_nul);
u3_noun dat = u3nt(mim, len_w, u3i_bytes(len_w, dat_y));
return u3nc(u3nt(pax, u3_nul, dat), u3_nul)
}
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_dir_update(): update directory, producing list of changes
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
static u3_noun
_unix_dir_update(u3_udir* dir_u)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
c3_assert( c3y == dir_u->dir );
2014-11-05 04:18:47 +03:00
if ( c3y == dir_u->dry ) {
2015-06-05 05:47:27 +03:00
return u3_nul;
}
2015-06-05 05:47:27 +03:00
u3_nod* nod_u;
for ( nod_u = dir_u->kid_u; nod_u; ) {
if ( c3y == nod_u->dry ) {
nod_u = nod_u->nex_u;
}
else {
if ( c3y == nod_u->dir ) {
DIR* red_u = opendir(nod_u->pax_c);
2013-09-29 00:21:18 +04:00
if ( 0 == red_u ) {
2015-06-05 05:47:27 +03:00
u3_udir* nex_u = nod_u->nex_u;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
_unix_free_node(nod_u); // XXX actually need to delete from list
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
nod_u = nex_u;
2013-09-29 00:21:18 +04:00
}
else {
2015-06-05 05:47:27 +03:00
closedir(rid_u);
nod_u = nod_u->nex_u;
2013-09-29 00:21:18 +04:00
}
}
2015-06-05 05:47:27 +03:00
else {
}
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
}
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
// Check for new files
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
DIR* rid_u = opendir(dir_u->pax_c);
if ( !rid_u ) {
uL(fprintf(uH, "error opening directory %s: %s\r\n",
dir_u->pax_c, strerror(errno)));
}
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
while ( 1 ) {
struct dirent ent_u;
struct dirent* out_u;
c3_w err_w
if ( (err_w = readdir_r(rid_u, &ent_u, &out_u)) != 0 ) {
uL(fprintf(uH, "error loading directory %s: %s\n",
dir_u->pax_c, strerror(err_w)));
c3_assert(0);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
else if ( !out_u ) {
break;
}
else if ( '.' == out_u->d_name[0] ) {
continue;
}
else {
c3_c* pax_c = _unix_down(dir_u->pax_c, out_u->d_name);
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
struct stat buf_u;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
if ( 0 != stat(pax_c, &buf_u) ) {
free(pax_c);
2013-09-29 00:21:18 +04:00
continue;
}
else {
2015-06-05 05:47:27 +03:00
u3_unod* nod_u;
for ( nod_u = dir_u->kid_u; nod_u; nod_u = nod_u->nex_u ) {
if ( !strcmp(pax_c, nod_u->pax_c) ) {
if ( S_ISDIR(buf_u.st_mode) ) {
c3_assert(nod_u->dir);
}
else {
c3_assert(!nod_u->dir);
}
break;
}
}
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
if ( !nod_u ) {
if ( !S_ISDIR(buf_u.st_mode) ) {
if ( !strchr(out_u->d_name,'.')
|| strchr(out_u->d_name,'.') != strrchr(out_u->d_name,'.')
|| '~' == out_u->d_name[strlen(out_u->d_name) - 1]
2014-03-25 21:39:53 +04:00
) {
2015-05-06 02:42:00 +03:00
free(pax_c);
2014-03-19 04:04:44 +04:00
continue;
}
2015-06-05 05:47:27 +03:00
u3_ufil* fil_u = c3_malloc(sizeof(u3_ufil));
_unix_file_watch(fil_u, dir_u, pax_c);
fil_u->nex = dir_u->kid_u;
dir_u->kid_u = fil_u;
2013-09-29 00:21:18 +04:00
}
else {
2015-06-05 05:47:27 +03:00
if ( strchr(out_u->d_name,'.') ) {
free(pax_c);
2015-06-05 05:47:27 +03:00
continue;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
u3_udir* dis_u = c3_malloc(sizeof(u3_udir));
_unix_dir_watch(dis_u, dir_u, pax_c);
_unix_dir_update(dis_u);
dis_u->nex_u = dir_u->kid_u;
dir_u->kid_u = dis_u;
2013-09-29 00:21:18 +04:00
}
}
}
}
}
2015-06-05 05:47:27 +03:00
c3_w col_i = closedir(rid_u);
if ( col_i < 0 ) {
uL(fprintf(uH, "error closing directory %s: %s\r\n",
dir_u->pax_c, strerror(errno)));
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
// get change list
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
u3_noun can;
u3_unod nod_u;
for ( nod_u = dir_u->kid_u; nod_u; nod_u = nod_u->nex_u ) {
can = u3kb_weld(_unix_node_update(nod_u),can);
2013-09-29 00:21:18 +04:00
}
2015-02-27 09:35:41 +03:00
2015-06-05 05:47:27 +03:00
return can;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_mount_update(): update mount point
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
void
_unix_mount_update(u3_umon* mon_u)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
if ( c3n == mon_u->dir_u.dry ) {
u3_noun can = _unix_dir_update(dir_u);
u3v_plan(u3nq(u3_blip, c3__sync, u3k(u3A->sen), u3_nul),
u3nt(c3__into, u3i_string(mon_u->nam_c), can));
}
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_sync_ergo(): sync changes to unix
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
void
_unix_sync_ergo(u3_umon mon_u, u3_noun can)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
c3_assert(!"not implemented");
u3z(can);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* _unix_sign_cb: signal callback.
2014-05-17 00:44:40 +04:00
*/
2015-06-05 05:47:27 +03:00
static void
_unix_sign_cb(uv_signal_t* sil_u, c3_i num_i)
2014-05-17 00:44:40 +04:00
{
2015-06-05 05:47:27 +03:00
u3_lo_open();
{
switch ( num_i ) {
default: fprintf(stderr, "\r\nmysterious signal %d\r\n", num_i); break;
2014-05-17 00:44:40 +04:00
2015-06-05 05:47:27 +03:00
case SIGTERM:
fprintf(stderr, "\r\ncaught signal %d\r\n", num_i);
u3_Host.liv = c3n;
break;
case SIGINT:
fprintf(stderr, "\r\ninterrupt\r\n");
u3_term_ef_ctlc();
break;
case SIGWINCH: u3_term_ef_winc(); break;
}
2014-05-17 00:44:40 +04:00
}
2015-06-05 05:47:27 +03:00
u3_lo_shut(c3y);
}
2014-05-17 00:44:40 +04:00
2015-06-05 05:47:27 +03:00
/* _unix_ef_sync(): check for files to sync.
*/
2013-09-29 00:21:18 +04:00
static void
2015-06-05 05:47:27 +03:00
_unix_ef_sync(uv_check_t* han_u)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
u3_lo_open();
u3_lo_shut(c3y);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* u3_unix_ef_ergo(): update filesystem from urbit
2013-09-29 00:21:18 +04:00
*/
2015-06-05 05:47:27 +03:00
void
u3_unix_ef_ergo(u3_noun mon
u3_noun can)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
u3_uhot* hot_u;
2013-11-09 03:37:38 +04:00
2015-06-05 05:47:27 +03:00
mon_u = _unix_get_mount_point(mon);
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
_unix_sync_ergo(mon_u, can);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* u3_unix_io_init(): initialize unix sync.
2015-05-14 00:18:43 +03:00
*/
2015-06-05 05:47:27 +03:00
void
u3_unix_io_init(void)
2015-05-14 00:18:43 +03:00
{
u3_unix* unx_u = &u3_Host.unx_u;
{
2015-06-05 05:47:27 +03:00
u3_usig* sig_u;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
sig_u = c3_malloc(sizeof(u3_usig));
uv_signal_init(u3L, &sig_u->sil_u);
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
sig_u->num_i = SIGTERM;
sig_u->nex_u = unx_u->sig_u;
unx_u->sig_u = sig_u;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
{
u3_usig* sig_u;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
sig_u = c3_malloc(sizeof(u3_usig));
uv_signal_init(u3L, &sig_u->sil_u);
2015-05-06 02:42:00 +03:00
2015-06-05 05:47:27 +03:00
sig_u->num_i = SIGINT;
sig_u->nex_u = unx_u->sig_u;
unx_u->sig_u = sig_u;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
{
u3_usig* sig_u;
2015-05-06 02:42:00 +03:00
2015-06-05 05:47:27 +03:00
sig_u = c3_malloc(sizeof(u3_usig));
uv_signal_init(u3L, &sig_u->sil_u);
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
sig_u->num_i = SIGWINCH;
sig_u->nex_u = unx_u->sig_u;
unx_u->sig_u = sig_u;
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
uv_check_init(u3_Host.lup_u, &u3_Host.unx_u.syn_u);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* u3_unix_acquire(): acquire a lockfile, killing anything that holds it.
2013-09-29 00:21:18 +04:00
*/
void
2015-06-05 05:47:27 +03:00
u3_unix_acquire(c3_c* pax_c)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
c3_c* paf_c = _unix_down(pax_c, ".vere.lock");
c3_w pid_w;
FILE* loq_u;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
if ( NULL != (loq_u = fopen(paf_c, "r")) ) {
if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) {
uL(fprintf(uH, "lockfile %s is corrupt!\n", paf_c));
kill(getpid(), SIGTERM);
sleep(1); c3_assert(0);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
else {
c3_w i_w;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
if ( -1 != kill(pid_w, SIGTERM) ) {
uL(fprintf(uH, "unix: stopping process %d, live in %s...\n",
pid_w, pax_c));
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
for ( i_w = 0; i_w < 16; i_w++ ) {
sleep(1);
if ( -1 == kill(pid_w, SIGTERM) ) {
break;
}
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
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 ) {
uL(fprintf(uH, "process %d seems unkillable!\n", pid_w));
c3_assert(0);
}
uL(fprintf(uH, "unix: stopped old process %u\n", pid_w));
2013-09-29 00:21:18 +04:00
}
}
2015-06-05 05:47:27 +03:00
fclose(loq_u);
unlink(paf_c);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
loq_u = fopen(paf_c, "w");
fprintf(loq_u, "%u\n", getpid());
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
c3_i fid_i = fileno(loq_u);
#if defined(U3_OS_linux)
fdatasync(fid_i);
#elif defined(U3_OS_osx)
fcntl(fid_i, F_FULLFSYNC);
#elif defined(U3_OS_bsd)
fsync(fid_i);
#else
# error "port: datasync"
#endif
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
fclose(loq_u);
free(paf_c);
2013-09-29 00:21:18 +04:00
}
2015-06-05 05:47:27 +03:00
/* u3_unix_release(): release a lockfile.
2013-09-29 00:21:18 +04:00
*/
void
2015-06-05 05:47:27 +03:00
u3_unix_release(c3_c* pax_c)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
c3_c* paf_c = _unix_down(pax_c, ".vere.lock");
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
unlink(paf_c);
free(paf_c);
2013-09-29 00:21:18 +04:00
}
2014-09-11 04:01:32 +04:00
/* u3_unix_ef_move()
2013-09-29 00:21:18 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_unix_ef_move(void)
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
u3_unix* unx_u = &u3_Host.unx_u;
u3_usig* sig_u;
2013-09-29 00:21:18 +04:00
for ( sig_u = unx_u->sig_u; sig_u; sig_u = sig_u->nex_u ) {
uv_signal_start(&sig_u->sil_u, _unix_sign_cb, sig_u->num_i);
2013-09-29 00:21:18 +04:00
}
}
2015-06-05 05:47:27 +03:00
/* u3_unix_ef_look(): update the root.
2013-09-29 00:21:18 +04:00
*/
void
2015-06-05 05:47:27 +03:00
u3_unix_ef_look(void)
2013-09-29 00:21:18 +04:00
{
2015-06-05 05:47:27 +03:00
u3_umon* mon_u;
2013-09-29 00:21:18 +04:00
2015-06-05 05:47:27 +03:00
for ( mon_u = u3_Host.unx_u->mon_u; mon_u; mon_u = mon_u->nex_u ) {
_unix_mount_update(mon_u);
2013-09-29 00:21:18 +04:00
}
2014-01-17 12:12:05 +04:00
}
2014-09-11 04:01:32 +04:00
/* u3_unix_io_talk(): start listening for fs events.
2014-01-17 12:12:05 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_unix_io_talk()
2014-01-17 12:12:05 +04:00
{
2014-11-16 04:10:15 +03:00
u3_unix_acquire(u3_Host.dir_c);
2014-09-11 04:01:32 +04:00
u3_unix_ef_move();
uv_check_start(&u3_Host.unx_u.syn_u, _unix_ef_sync);
2013-09-29 00:21:18 +04:00
}
2014-09-11 04:01:32 +04:00
/* u3_unix_io_exit(): terminate unix I/O.
2013-09-29 00:21:18 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_unix_io_exit(void)
2013-09-29 00:21:18 +04:00
{
2014-09-11 04:01:32 +04:00
uv_check_stop(&u3_Host.unx_u.syn_u);
2014-11-16 04:10:15 +03:00
u3_unix_release(u3_Host.dir_c);
2013-09-29 00:21:18 +04:00
}
2014-09-11 04:01:32 +04:00
/* u3_unix_io_poll(): update unix IO state.
2013-09-29 00:21:18 +04:00
*/
void
2014-09-11 04:01:32 +04:00
u3_unix_io_poll(void)
2013-09-29 00:21:18 +04:00
{
}
2015-06-05 05:47:27 +03:00