コード例 #1
0
ファイル: unix.c プロジェクト: cgyarvin/urbit
/* _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;
  }
}
コード例 #2
0
ファイル: unix.c プロジェクト: juped/your-urbit
/* 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);
    free(paf_c);
}
コード例 #3
0
ファイル: unix.c プロジェクト: juped/your-urbit
/* _unix_initial_update_dir(): read directory, but don't watch
*/
static u3_noun
_unix_initial_update_dir(c3_c* pax_c)
{
    u3_noun can = u3_nul;

    DIR* rid_u = opendir(pax_c);
    if ( !rid_u ) {
        uL(fprintf(uH, "error opening initial directory: %s: %s\r\n",
                   pax_c, strerror(errno)));
        return u3_nul;
    }

    while ( 1 ) {
        struct dirent  ent_u;
        struct dirent* out_u;
        c3_w err_w;

        if ( 0 != (err_w = readdir_r(rid_u, &ent_u, &out_u)) ) {
            uL(fprintf(uH, "error loading initial directory %s: %s\r\n",
                       pax_c, strerror(errno)));
            c3_assert(0);
        }
        else if ( !out_u ) {
            break;
        }
        else if ( '.' == out_u->d_name[0] ) {
            continue;
        }
        else {
            c3_c* pox_c = _unix_down(pax_c, out_u->d_name);

            struct stat buf_u;

            if ( 0 != stat(pox_c, &buf_u) ) {
                uL(fprintf(uH, "initial can't stat %s: %s\r\n",
                           pox_c, strerror(errno)));
                free(pox_c);
                continue;
            }
            else {
                if ( S_ISDIR(buf_u.st_mode) ) {
                    can = u3kb_weld(_unix_initial_update_dir(pox_c), can);
                }
                else {
                    can = u3kb_weld(_unix_initial_update_file(pox_c), can);
                }
                free(pox_c);
            }
        }
    }

    if ( closedir(rid_u) < 0 ) {
        uL(fprintf(uH, "error closing initial directory %s: %s\r\n",
                   pax_c, strerror(errno)));
    }

    return can;
}
コード例 #4
0
ファイル: unix.c プロジェクト: cgyarvin/urbit
/* u2_unix_acquire(): acquire a lockfile, killing anything that holds it.
*/
void
u2_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, "%u", &pid_w) ) {
      uL(fprintf(uH, "lockfile %s is corrupt!\n", paf_c));
      kill(getpid(), SIGTERM);
      sleep(1); c3_assert(0);
    }
    else {
      c3_w i_w;

      if ( -1 != kill(pid_w, SIGTERM) ) {
        uL(fprintf(uH, "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 ) {
          uL(fprintf(uH, "process %d seems unkillable!\n", pid_w));
          c3_assert(0);
        }
      }
      uL(fprintf(uH, "unix: stopped old process %u\n", pid_w));
    }
    fclose(loq_u);
    unlink(paf_c);
  }

  loq_u = fopen(paf_c, "w");
  fprintf(loq_u, "%u\n", getpid());

  {
    c3_i fid_i = fileno(loq_u);
#if defined(U2_OS_linux)
    fdatasync(fid_i);
#else
    fcntl(fid_i, F_FULLFSYNC); 
#endif
  }
  fclose(loq_u);
}
コード例 #5
0
ファイル: unix.c プロジェクト: juped/your-urbit
void
u3_unix_ef_initial_into()
{
    c3_c* pax_c = _unix_down(U3_LIB, "arvo");
    u3_noun can = _unix_initial_update_dir(pax_c);
    free(pax_c);

    u3v_plan(u3nq(u3_blip, c3__sync, u3k(u3A->sen), u3_nul),
             u3nq(c3__into, u3_nul, c3y, can));
}
コード例 #6
0
ファイル: unix.c プロジェクト: juped/your-urbit
/* _unix_update_dir(): update directory, producing list of changes
 *
 * when changing this, consider whether to also change
 * _unix_initial_update_dir()
*/
static u3_noun
_unix_update_dir(u3_udir* dir_u)
{
    u3_noun can = u3_nul;

    c3_assert( c3y == dir_u->dir );

    if ( c3y == dir_u->dry ) {
        return u3_nul;
    }

    dir_u->dry = c3y;

    // Check that old nodes are still there

    u3_unod* nod_u = dir_u->kid_u;

    if ( nod_u ) {
        while ( 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);
                    if ( 0 == red_u ) {
                        u3_unod* nex_u = nod_u->nex_u;
                        can = u3kb_weld(_unix_free_node(nod_u), can);
                        nod_u = nex_u;
                    }
                    else {
                        closedir(red_u);
                        nod_u = nod_u->nex_u;
                    }
                }
                else {
                    struct stat buf_u;
                    c3_i  fid_i = open(nod_u->pax_c, O_RDONLY, 0644);

                    if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) {
                        if ( ENOENT != errno ) {
                            uL(fprintf(uH, "_unix_update_dir: error opening file %s: %s\r\n",
                                       nod_u->pax_c, strerror(errno)));
                        }

                        u3_unod* nex_u = nod_u->nex_u;
                        can = u3kb_weld(_unix_free_node(nod_u), can);
                        nod_u = nex_u;
                    }
                    else {
                        if ( close(fid_i) < 0 ) {
                            uL(fprintf(uH, "_unix_update_dir: error closing file %s: %s\r\n",
                                       nod_u->pax_c, strerror(errno)));
                        }

                        nod_u = nod_u->nex_u;
                    }
                }
            }
        }
    }

    // Check for new nodes

    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)));
        c3_assert(0);
    }

    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\r\n",
                       dir_u->pax_c, strerror(err_w)));
            c3_assert(0);
        }
        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);

            struct stat buf_u;

            if ( 0 != stat(pax_c, &buf_u) ) {
                uL(fprintf(uH, "can't stat %s: %s\r\n", pax_c, strerror(errno)));
                free(pax_c);
                continue;
            }
            else {
                u3_unod* nod_u;
                for ( nod_u = dir_u->kid_u; nod_u; nod_u = nod_u->nex_u ) {
                    if ( 0 == strcmp(pax_c, nod_u->pax_c) ) {
                        if ( S_ISDIR(buf_u.st_mode) ) {
                            if ( c3n == nod_u->dir ) {
                                uL(fprintf(uH, "not a directory: %s\r\n", nod_u->pax_c));
                                c3_assert(0);
                            }
                        }
                        else {
                            if ( c3y == nod_u->dir ) {
                                uL(fprintf(uH, "not a file: %s\r\n", nod_u->pax_c));
                                c3_assert(0);
                            }
                        }
                        break;
                    }
                }

                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])
                           ) {
                            free(pax_c);
                            continue;
                        }

                        u3_ufil* fil_u = c3_malloc(sizeof(u3_ufil));
                        _unix_watch_file(fil_u, dir_u, pax_c);
                    }
                    else {
                        u3_udir* dis_u = c3_malloc(sizeof(u3_udir));
                        _unix_watch_dir(dis_u, dir_u, pax_c);
                        can = u3kb_weld(_unix_update_dir(dis_u), can); // XXX unnecessary?
                    }
                }
            }
        }
    }

    if ( closedir(rid_u) < 0 ) {
        uL(fprintf(uH, "error closing directory %s: %s\r\n",
                   dir_u->pax_c, strerror(errno)));
    }

    if ( !dir_u->kid_u ) {
        return u3kb_weld(_unix_free_node((u3_unod*) dir_u), can);
    }

    // get change list

    for ( nod_u = dir_u->kid_u; nod_u; nod_u = nod_u->nex_u ) {
        can = u3kb_weld(_unix_update_node(nod_u), can);
    }

    return can;
}
コード例 #7
0
ファイル: unix.c プロジェクト: juped/your-urbit
/* _unix_scan_mount_point(): scan unix for already-existing mount point
*/
static void
_unix_scan_mount_point(u3_umon* mon_u)
{
    DIR* rid_u = opendir(mon_u->dir_u.pax_c);
    if ( !rid_u ) {
        uL(fprintf(uH, "error opening pier directory: %s: %s\r\n",
                   mon_u->dir_u.pax_c, strerror(errno)));
        return;
    }

    c3_w len_w = strlen(mon_u->nam_c);

    while ( 1 ) {
        struct dirent  ent_u;
        struct dirent* out_u;
        c3_w err_w;

        if ( 0 != (err_w = readdir_r(rid_u, &ent_u, &out_u)) ) {
            uL(fprintf(uH, "erroring loading pier directory %s: %s\r\n",
                       mon_u->dir_u.pax_c, strerror(errno)));
            c3_assert(0);
        }
        else if ( !out_u ) {
            break;
        }
        else if ( '.' == out_u->d_name[0] ) { // unnecessary, but consistency
            continue;
        }
        else if ( 0 != strncmp(mon_u->nam_c, out_u->d_name, len_w) ) {
            continue;
        }
        else {
            c3_c* pax_c = _unix_down(mon_u->dir_u.pax_c, out_u->d_name);

            struct stat buf_u;

            if ( 0 != stat(pax_c, &buf_u) ) {
                uL(fprintf(uH, "can't stat pier directory %s: %s\r\n",
                           mon_u->dir_u.pax_c, strerror(errno)));
                free(pax_c);
                continue;
            }
            if ( S_ISDIR(buf_u.st_mode) ) {
                if ( out_u->d_name[len_w] != '\0' ) {
                    free(pax_c);
                    continue;
                }
                else {
                    u3_udir* dir_u = c3_malloc(sizeof(u3_udir));
                    _unix_watch_dir(dir_u, &mon_u->dir_u, pax_c);
                }
            }
            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])
                   ) {
                    free(pax_c);
                    continue;
                }
                else {
                    u3_ufil* fil_u = c3_malloc(sizeof(u3_ufil));
                    _unix_watch_file(fil_u, &mon_u->dir_u, pax_c);
                }
            }
        }
    }
}
コード例 #8
0
ファイル: unix.c プロジェクト: cgyarvin/urbit
/* _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;
}
コード例 #9
0
ファイル: unix.c プロジェクト: esaul/urbit
/* _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);
            }
          }
        }
      }
    }
  }
}