Beispiel #1
0
static bool
check_rename(struct file *src, struct file *dst)
{
	file_stat(src);

	/* If the source file is not present and we are not going to do
	 * the rename anyway there's no point in checking any further. */
	if (src->stat_state == FILE_STAT_NOFILE)
		return false;

	file_stat(dst);

	/*
	 * Unfortunately we have to check for write access in both places,
	 * just having +w is not enough, since people do mount things RO,
	 * and we need to fail before we start mucking around with things.
	 * So we open a file with the same name as the diversions but with
	 * an extension that (hopefully) won't overwrite anything. If it
	 * succeeds, we assume a writable filesystem.
	 */

	check_writable_dir(src);
	check_writable_dir(dst);

	if (src->stat_state == FILE_STAT_VALID &&
	    dst->stat_state == FILE_STAT_VALID &&
	    !(src->stat.st_dev == dst->stat.st_dev &&
	      src->stat.st_ino == dst->stat.st_ino))
		ohshit(_("rename involves overwriting '%s' with\n"
		         "  different file '%s', not allowed"),
		        dst->name, src->name);

	return true;
}
Beispiel #2
0
int c_mkdir_safe( const char * dirname )
{
   int retval = -1 ;

   /* return directly -1 if directory exists and is writable */
   if ( check_writable_dir(dirname) == 0) return -1;

#if defined(_WIN32)
   retval = _mkdir( dirname ) ;
#else
   mode_t mode = 0777 ;
   retval = mkdir( dirname , mode ) ;
#endif
   if ( retval == -1  && errno != EEXIST ) {
     fprintf( stderr , "\nmkdir fail: [%d] %s\n" , errno , strerror( errno ) ) ;
     retval = 1 ;
     }
   /* double check that the directory is a directory and has the good permissions */
   if ( check_writable_dir(dirname) < 0) retval = 1;  
   return retval ;
}
Beispiel #3
0
Datei: run.c Projekt: NUOG/ejudge
static int
check_config(void)
{
  int     i, n1 = 0, n2, j, k;
  int     total = 0;

  struct section_problem_data *prb = 0;
  struct section_tester_data *tst = 0;
  unsigned char *var_test_dir;
  unsigned char *var_corr_dir;
  unsigned char *var_info_dir;
  unsigned char *var_tgz_dir;
  problem_xml_t px;
  const struct section_global_data *global = serve_state.global;

  if (skip_arch_count > 0) {
    for (i = 0; i < serve_state.max_abstr_tester; ++i) {
      tst = serve_state.abstr_testers[i];
      if (!tst) continue;
      tst->skip_testing = -1;
      for (j = 0; j < skip_arch_count; ++j) {
        if (!strcmp(skip_archs[j], tst->arch)) {
          break;
        }
      }
      if (j < skip_arch_count) {
        tst->skip_testing = 1;
      }
    }
  }

  /* check spooler dirs */
  if (check_writable_spool(global->run_queue_dir, SPOOL_OUT) < 0) return -1;
  if (check_writable_dir(global->run_exe_dir) < 0) return -1;

  /* check working dirs */
  if (make_writable(global->run_work_dir) < 0) return -1;
  if (check_writable_dir(global->run_work_dir) < 0) return -1;

  for (i = 1; i <= serve_state.max_prob; i++) {
    prb = serve_state.probs[i];
    if (!prb) continue;
    if (prb->disable_testing) continue;
    if (prb->manual_checking) continue;

    /* ignore output-only problems with XML and answer variants */
    px = 0;
    if (prb->variant_num > 0 && prb->xml.a) {
      px = prb->xml.a[0];
    } else {
      px = prb->xml.p;
    }
    if (px && px->answers) {
      prb->disable_testing = 1;
      continue;
    }

    // check if there exists a tester for this problem
    for (j = 1; j <= serve_state.max_tester; j++) {
      if (!serve_state.testers[j]) continue;
      if (serve_state.testers[j]->any) break;
      if (serve_state.testers[j]->problem == i) break;
    }
    if (j > serve_state.max_tester) {
      // no checker for the problem :-(
      info("no checker found for problem %d", i);
      continue;
    }

    if (prb->type > 0 && prb->type != PROB_TYPE_TESTS) {
      // output-only problems have no input file
      if (prb->variant_num <= 0) {
        if (prb->use_corr) {
          if (!prb->corr_dir[0]) {
            err("directory with answers is not defined");
            return -1;
          }
          if (global->advanced_layout > 0) {
            var_corr_dir = (unsigned char*) alloca(sizeof(path_t));
            get_advanced_layout_path(var_corr_dir, sizeof(path_t), global,
                                     prb, DFLT_P_CORR_DIR, -1);
          } else {
            var_corr_dir = prb->corr_dir;
          }
          if (check_readable_dir(var_corr_dir) < 0) return -1;
          if ((n2 = count_files(var_corr_dir,prb->corr_sfx,prb->corr_pat)) < 0)
            return -1;
          n1 = n2;
          info("found %d answers for problem %s", n2, prb->short_name);
          if (n2 != 1) {
            err("output-only problem must define only one answer file");
            return -1;
          }
        }
        if (prb->use_info) {
          if (!prb->info_dir[0]) {
            err("directory with test information is not defined");
            return -1;
          }
          if (global->advanced_layout > 0) {
            var_info_dir = (unsigned char*) alloca(sizeof(path_t));
            get_advanced_layout_path(var_info_dir, sizeof(path_t), global,
                                     prb, DFLT_P_INFO_DIR, -1);
          } else {
            var_info_dir = prb->info_dir;
          }
          if (check_readable_dir(var_info_dir) < 0) return -1;
          if ((n2 = count_files(var_info_dir,prb->info_sfx,prb->info_pat)) < 0)
            return -1;
          info("found %d info files for problem %s", n2, prb->short_name);
          if (n2 != 1) {
            err("output-only problem must define only one info file");
            return -1;
          }
        }
        if (prb->use_tgz) {
          if (!prb->tgz_dir[0]) {
            err("directory with tgz information is not defined");
            return -1;
          }
          if (global->advanced_layout > 0) {
            var_tgz_dir = (unsigned char*) alloca(sizeof(path_t));
            get_advanced_layout_path(var_tgz_dir, sizeof(path_t), global,
                                     prb, DFLT_P_TGZ_DIR, -1);
          } else {
            var_tgz_dir = prb->tgz_dir;
          }
          if (check_readable_dir(var_tgz_dir) < 0) return -1;
          if ((n2 = count_files(var_tgz_dir, prb->tgz_sfx, 0)) < 0) return -1;
          info("found %d tgz files for problem %s", n2, prb->short_name);
          if (n2 != 1) {
            err("output-only problem must define only one tgz file");
            return -1;
          }
        }
      } else {
        var_test_dir = (unsigned char *) alloca(sizeof(path_t));
        var_corr_dir = (unsigned char *) alloca(sizeof(path_t));
        var_info_dir = (unsigned char *) alloca(sizeof(path_t));
        var_tgz_dir = (unsigned char *) alloca(sizeof(path_t));

        for (k = 1; k <= prb->variant_num; k++) {
          if (global->advanced_layout > 0) {
            get_advanced_layout_path(var_test_dir, sizeof(path_t), global,
                                     prb, DFLT_P_TEST_DIR, k);
            get_advanced_layout_path(var_corr_dir, sizeof(path_t), global,
                                     prb, DFLT_P_CORR_DIR, k);
            get_advanced_layout_path(var_info_dir, sizeof(path_t), global,
                                     prb, DFLT_P_INFO_DIR, k);
            get_advanced_layout_path(var_tgz_dir, sizeof(path_t), global,
                                     prb, DFLT_P_TGZ_DIR, k);
          } else {
            snprintf(var_test_dir, sizeof(path_t), "%s-%d", prb->test_dir, k);
            snprintf(var_corr_dir, sizeof(path_t), "%s-%d", prb->corr_dir, k);
            snprintf(var_info_dir, sizeof(path_t), "%s-%d", prb->info_dir, k);
            snprintf(var_tgz_dir, sizeof(path_t), "%s-%d", prb->tgz_dir, k);
          }
          if (prb->use_corr) {
            if (!prb->corr_dir[0]) {
              err("directory with answers is not defined");
              return -1;
            }
            if (check_readable_dir(var_corr_dir) < 0) return -1;
            if ((j = count_files(var_corr_dir,prb->corr_sfx,prb->corr_pat)) < 0)
              return -1;
            if (j != 1) {
              err("output-only problem must define only one answer file");
              return -1;
            }
          }
          if (prb->use_info) {
            if (!prb->info_dir[0]) {
              err("directory with test infos is not defined");
              return -1;
            }
            if (check_readable_dir(var_info_dir) < 0) return -1;
            if ((j = count_files(var_info_dir,prb->info_sfx,prb->info_pat)) < 0)
              return -1;
            if (j != 1) {
              err("output-only problem must define only one info file");
              return -1;
            }
          }
          if (prb->use_tgz) {
            if (!prb->tgz_dir[0]) {
              err("directory with tgz is not defined");
              return -1;
            }
            if (check_readable_dir(var_tgz_dir) < 0) return -1;
            if ((j = count_files(var_tgz_dir, prb->tgz_sfx, 0)) < 0) return -1;
            if (j != 1) {
              err("output-only problem must define only one info file");
              return -1;
            }
          }
        }
        n1 = n2 = 1;
      }
    } else if (!prb->type) {
      /* check existence of tests */
      if (prb->variant_num <= 0) {
        if (global->advanced_layout > 0) {
          var_test_dir = (unsigned char *) alloca(sizeof(path_t));
          get_advanced_layout_path(var_test_dir, sizeof(path_t), global,
                                   prb, DFLT_P_TEST_DIR, -1);
        } else {
          var_test_dir = prb->test_dir;
        }
        if (check_readable_dir(var_test_dir) < 0) return -1;
        if ((n1 = count_files(var_test_dir, prb->test_sfx, prb->test_pat)) < 0)
          return -1;
        if (!n1) {
          err("'%s' does not contain any tests", var_test_dir);
          return -1;
        }
        /*
        if (prb->type_val > 0 && n1 != 1) {
          err("`%s' must have only one test (as output-only problem)",
              prb->short_name);
          return -1;
        }
        */
        info("found %d tests for problem %s", n1, prb->short_name);
        if (n1 < prb->tests_to_accept) {
          err("%d tests required for problem acceptance!",prb->tests_to_accept);
          return -1;
        }
        if (prb->use_corr) {
          if (!prb->corr_dir[0]) {
            err("directory with answers is not defined");
            return -1;
          }
          if (global->advanced_layout > 0) {
            var_corr_dir = (unsigned char *) alloca(sizeof(path_t));
            get_advanced_layout_path(var_corr_dir, sizeof(path_t), global,
                                     prb, DFLT_P_CORR_DIR, -1);
          } else {
            var_corr_dir = prb->corr_dir;
          }
          if (check_readable_dir(var_corr_dir) < 0) return -1;
          if ((n2 = count_files(var_corr_dir,prb->corr_sfx,prb->corr_pat)) < 0)
            return -1;
          info("found %d answers for problem %s", n2, prb->short_name);
          if (n1 != n2) {
            err("number of test does not match number of answers");
            return -1;
          }
        }
        if (prb->use_info) {
          if (!prb->info_dir[0]) {
            err("directory with test information is not defined");
            return -1;
          }
          if (global->advanced_layout > 0) {
            var_info_dir = (unsigned char *) alloca(sizeof(path_t));
            get_advanced_layout_path(var_info_dir, sizeof(path_t), global,
                                     prb, DFLT_P_INFO_DIR, -1);
          } else {
            var_info_dir = prb->info_dir;
          }
          if (check_readable_dir(var_info_dir) < 0) return -1;
          if ((n2 = count_files(var_info_dir,prb->info_sfx,prb->info_pat)) < 0)
            return -1;
          info("found %d info files for problem %s", n2, prb->short_name);
          if (n1 != n2) {
            err("number of test does not match number of info files");
            return -1;
          }
        }
        if (prb->use_tgz) {
          if (!prb->tgz_dir[0]) {
            err("directory with tgz information is not defined");
            return -1;
          }
          if (global->advanced_layout > 0) {
            var_tgz_dir = (unsigned char *) alloca(sizeof(path_t));
            get_advanced_layout_path(var_tgz_dir, sizeof(path_t), global,
                                     prb, DFLT_P_TGZ_DIR, -1);
          } else {
            var_tgz_dir = prb->tgz_dir;
          }
          if (check_readable_dir(var_tgz_dir) < 0) return -1;
          if ((n2 = count_files(var_tgz_dir, prb->tgz_sfx, 0)) < 0) return -1;
          info("found %d tgz files for problem %s", n2, prb->short_name);
          if (n1 != n2) {
            err("number of test does not match number of tgz files");
            return -1;
          }
        }
      } else {
        n1 = n2 = -1;
        var_test_dir = (unsigned char *) alloca(sizeof(path_t));
        var_corr_dir = (unsigned char *) alloca(sizeof(path_t));
        var_info_dir = (unsigned char *) alloca(sizeof(path_t));
        var_tgz_dir = (unsigned char *) alloca(sizeof(path_t));

        for (k = 1; k <= prb->variant_num; k++) {
          if (global->advanced_layout > 0) {
            get_advanced_layout_path(var_test_dir, sizeof(path_t), global,
                                     prb, DFLT_P_TEST_DIR, k);
            get_advanced_layout_path(var_corr_dir, sizeof(path_t), global,
                                     prb, DFLT_P_CORR_DIR, k);
            get_advanced_layout_path(var_info_dir, sizeof(path_t), global,
                                     prb, DFLT_P_INFO_DIR, k);
            get_advanced_layout_path(var_tgz_dir, sizeof(path_t), global,
                                     prb, DFLT_P_TGZ_DIR, k);
          } else {
            snprintf(var_test_dir, sizeof(path_t), "%s-%d", prb->test_dir, k);
            snprintf(var_corr_dir, sizeof(path_t), "%s-%d", prb->corr_dir, k);
            snprintf(var_info_dir, sizeof(path_t), "%s-%d", prb->info_dir, k);
            snprintf(var_tgz_dir, sizeof(path_t), "%s-%d", prb->tgz_dir, k);
          }
          if (check_readable_dir(var_test_dir) < 0) return -1;
          if ((j = count_files(var_test_dir, prb->test_sfx, prb->test_pat)) < 0)
            return -1;
          if (!j) {
            err("'%s' does not contain any tests", var_test_dir);
            return -1;
          }
          /*
          if (prb->type_val > 0 && n1 != 1) {
            err("`%s', variant %d must have only one test (as output-only problem)",
                prb->short_name, j);
            return -1;
          }
          */
          if (n1 < 0) n1 = j;
          if (n1 != j) {
            err("number of tests %d for variant %d does not equal %d",
                j, k, n1);
            return -1;
          }
          info("found %d tests for problem %s, variant %d",
               n1, prb->short_name, k);
          if (n1 < prb->tests_to_accept) {
            err("%d tests required for problem acceptance!",
                prb->tests_to_accept);
            return -1;
          }
          if (prb->use_corr) {
            if (!prb->corr_dir[0]) {
              err("directory with answers is not defined");
              return -1;
            }
            if (check_readable_dir(var_corr_dir) < 0) return -1;
            if ((j = count_files(var_corr_dir,prb->corr_sfx,prb->corr_pat)) < 0)
              return -1;
            info("found %d answers for problem %s, variant %d",
                 j, prb->short_name, k);
            if (n1 != j) {
              err("number of tests %d does not match number of answers %d",
                  n1, j);
              return -1;
            }
          }
          if (prb->use_info) {
            if (!prb->info_dir[0]) {
              err("directory with test infos is not defined");
              return -1;
            }
            if (check_readable_dir(var_info_dir) < 0) return -1;
            if ((j = count_files(var_info_dir,prb->info_sfx,prb->info_pat)) < 0)
              return -1;
            info("found %d test infos for problem %s, variant %d",
                 j, prb->short_name, k);
            if (n1 != j) {
              err("number of tests %d does not match number of test infos %d",
                  n1, j);
              return -1;
            }
          }
          if (prb->use_tgz) {
            if (!prb->tgz_dir[0]) {
              err("directory with tgz is not defined");
              return -1;
            }
            if (check_readable_dir(var_tgz_dir) < 0) return -1;
            if ((j = count_files(var_tgz_dir, prb->tgz_sfx, 0)) < 0) return -1;
            info("found %d tgzs for problem %s, variant %d",
                 j, prb->short_name, k);
            if (n1 != j) {
              err("number of tests %d does not match number of tgz %d",
                  n1, j);
              return -1;
            }
          }
          n2 = n1;
        }
      }
    }

    if (n1 >= tests_a - 1) {
      if (!tests_a) tests_a = 128;
      while (n1 >= tests_a - 1)
        tests_a *= 2;
      xfree(tests);
      XCALLOC(tests, tests_a);
    }

    ASSERT(prb->test_score >= 0);
    if (global->score_system == SCORE_MOSCOW) {
      if (prb->full_score <= 0) {
        err("problem %s: problem full_score is not set", prb->short_name);
        return -1;
      }
      prb->ntests = n1;
      if (!prb->scoring_checker) {
        if (!(prb->x_score_tests = prepare_parse_score_tests(prb->score_tests,
                                                             prb->full_score))){
          err("problem %s: parsing of score_tests failed", prb->short_name);
          return -1;
        }
        prb->x_score_tests[prb->full_score - 1] = n1 + 1;
        if (prb->full_score > 1
            && prb->x_score_tests[prb->full_score - 2] > n1 + 1) {
          err("problem %s: score_tests[%d] > score_tests[%d]",
              prb->short_name,
              prb->full_score - 2, prb->full_score - 1);
          return -1;
        }
      }
    } else if (prb->test_score >= 0 && global->score_system != SCORE_ACM) {
      int score_summ = 0;

      prb->ntests = n1;
      XCALLOC(prb->tscores, prb->ntests + 1);

      for (j = 1; j <= prb->ntests; j++)
        prb->tscores[j] = prb->test_score;

      // test_score_list overrides test_score
      if (prb->test_score_list && prb->test_score_list[0]) {
        char const *s = prb->test_score_list;
        int tn = 1;
        int was_indices = 0;
        int n;
        int index, score;

        while (1) {
          while (*s > 0 && *s <= ' ') s++;
          if (!*s) break;

          if (*s == '[') {
            if (sscanf(s, "[ %d ] %d%n", &index, &score, &n) != 2) {
              err("cannot parse test_score_list for problem %s",
                  prb->short_name);
              return -1;
            }
            if (index < 1 || index > prb->ntests) {
              err("problem %s: test_score_list: index out of range",
                  prb->short_name);
              return -1;
            }
            if (score < 0) {
              err("problem %s: test_score_list: invalid score",
                  prb->short_name);
              return -1;
            }
            tn = index;
            was_indices = 1;
            prb->tscores[tn++] = score;
            s += n;
          } else {
            if (sscanf(s, "%d%n", &score, &n) != 1) {
              err("cannot parse test_score_list for problem %s",
                  prb->short_name);
              return -1;
            }
            if (score < 0) {
              err("problem %s: test_score_list: invalid score",
                  prb->short_name);
              return -1;
            }
            if (tn > prb->ntests) {
              err("problem %s: too many scores specified", prb->short_name);
              return -1;
            }
            prb->tscores[tn++] = score;
            s += n;
          }
        }

        if (!was_indices && tn <= prb->ntests) {
          info("test_score_list for problem %s defines only %d tests",
               prb->short_name, tn - 1);
        }
      }

      for (j = 1; j <= prb->ntests; j++) score_summ += prb->tscores[j];
      if (score_summ > prb->full_score && !prb->valuer_cmd[0]) {
        err("total score (%d) > full score (%d) for problem %s",
            score_summ, prb->full_score, prb->short_name);
        return -1;
      }
    }
  }

  for (i = 1; i <= serve_state.max_tester; i++) {
    if (!serve_state.testers[i]) continue;
    if (serve_state.testers[i]->any) continue;
    prb = serve_state.probs[serve_state.testers[i]->problem];
    total++;

    /* check working dirs */
    if (make_writable(serve_state.testers[i]->check_dir) < 0) return -1;
    if (check_writable_dir(serve_state.testers[i]->check_dir) < 0) return -1;
    if (serve_state.testers[i]->prepare_cmd[0]
        && check_executable(serve_state.testers[i]->prepare_cmd) < 0) return -1;
    if (serve_state.testers[i]->start_cmd[0]
        && check_executable(serve_state.testers[i]->start_cmd) < 0) return -1;
  }

  info("checking default testers...");
  if ((i = process_default_testers()) < 0) return -1;
  info("checking default testers done");
  total += i;

  if (!total) info("no testers");

#if CONF_HAS_LIBINTL - 0 == 1
  // bind message catalogs, if specified
  if (global->enable_l10n && global->l10n_dir[0]) {
    bindtextdomain("ejudge", global->l10n_dir);
    textdomain("ejudge");
  }
#endif

  return 0;
}
Beispiel #4
0
Datei: run.c Projekt: NUOG/ejudge
static int
process_default_testers(void)
{
  int total = 0;
  int i, j, k;
  unsigned char *prob_flags = 0;
  struct section_tester_data *tp, *tq;
  struct section_problem_data *ts;

  struct section_tester_data tn; //temporary entry

  prob_flags = (unsigned char *) alloca(serve_state.max_prob + 1);

  /* scan all the 'any' testers */
  for (i = 1; i <= serve_state.max_tester; i++) {
    tp = serve_state.testers[i];
    if (!tp || !tp->any) continue;

    // check architecture uniqueness
    for (j = 1; j <= serve_state.max_tester; j++) {
      tq = serve_state.testers[j];
      if (i == j || !tq || !tq->any) continue;
      if (strcmp(serve_state.testers[j]->arch, tp->arch) != 0) continue;
      err("default testers %d and %d has the same architecture '%s'",
          i, j, tp->arch);
      return -1;
    }

    // mark the problems with explicit testers for this architecture
    memset(prob_flags, 0, serve_state.max_prob + 1);
    for (j = 1; j <= serve_state.max_tester; j++) {
      tq = serve_state.testers[j];
      if (!tq || tq->any) continue;
      if (strcmp(tp->arch, tq->arch) != 0) continue;

      // tq is specific tester with the same architecture
      ASSERT(tq->problem > 0 && tq->problem <= serve_state.max_prob);
      ASSERT(serve_state.probs[tq->problem]);
      prob_flags[tq->problem] = 1;
    }

    // scan all problems, which have no default tester
    for (k = 1; k <= serve_state.max_prob; k++) {
      ts = serve_state.probs[k];
      if (!ts || prob_flags[k]) continue;
      if (ts->disable_testing) continue;
      if (ts->manual_checking) continue;

      // so at this point: tp - pointer to the default tester,
      // k is the problem number
      // ts - pointer to the problem which should be handled by the
      // default tester
      if (prepare_tester_refinement(&serve_state, &tn, i, k) < 0) return -1;
      if (create_tester_dirs(&tn) < 0) return -1;

      /* check working dirs */
      if (make_writable(tn.check_dir) < 0) return -1;
      if (check_writable_dir(tn.check_dir) < 0) return -1;
      if (tn.prepare_cmd[0] && check_executable(tn.prepare_cmd) < 0) return -1;
      if (tn.start_cmd[0] && check_executable(tn.start_cmd) < 0) return -1;
      total++;

      sarray_free(tn.start_env);
      sarray_free(tn.super);
    }
  }

  return total;
}