int main()

in utils/adjust-times/adjust-times.cpp [169:324]


int main(int argc, char **argv) {
  using namespace llvm;

  cl::opt<int>         Adjust   ("adjust", cl::init(0), cl::desc("Move access and modification times"));
  cl::alias            AdjustA  ("a", cl::aliasopt(Adjust));
  cl::opt<bool>        MTimeA   ("mtime-add-ulp", cl::desc("Move the a/mtime a smallest amount backwards"));
  cl::opt<bool>        MTimeM   ("mtime-minus-ulp", cl::desc("Move the a/mtime a smallest amount Forwards"));
  cl::opt<bool>        NowP     ("now-plus-ulp", cl::desc("Set to current time plus epsilon"));
  cl::opt<bool>        NowM     ("now-minus-ulp", cl::desc("Set to current time minus epsilon"));
  cl::opt<std::string> Filename ("from-file", cl::init(""), cl::desc("Set access and modification times from FILE"), cl::value_desc("file"));
  cl::alias            FilenameA("f", cl::aliasopt(Filename));
  cl::opt<bool>        Verbose  ("verbose", cl::desc("Show what is being done"));
  cl::alias            VerboseA ("v", cl::aliasopt(Verbose));
  cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<Input files>"), cl::OneOrMore);

  cl::ParseCommandLineOptions(argc, argv, "Modify timestamps of existing files\n");

  enum mode {
    ModeSetToNow,
    ModeSetToFile,      // -f, --from-file
    ModeAdjustMtime,    // -a, --adjust
    ModeMtimeMinusULP,  // --mtime-minus-ulp
    ModeMtimePlusULP,   // --mtime-plus-ulp
    ModeNowMinusULP,    // --now-minus-ulp
    ModeNowPlusULP,     // --now-plus-ulp
  } mode = ModeSetToNow;

  struct timespec time_to_set = { 0, UTIME_NOW };
  double adjust_relative_sec = 0;

  if (MTimeM) {
    mode = ModeMtimeMinusULP;
  }
  if (MTimeA) {
    mode = ModeMtimePlusULP;
  }
  if (NowP) {
    mode = ModeNowPlusULP;
  }
  if (NowM) {
    mode = ModeNowMinusULP;
  }
  if (Adjust) {
    double value = Adjust;
    if (value < -1000000 || value > 1000000) {
      errno = ERANGE;
    }
    if (errno != 0) {
      std::cerr << "--adjust " << Adjust << ": " << strerror(errno) << std::endl;
      exit(EX_DATAERR);
    }
    adjust_relative_sec = value;
    mode = ModeAdjustMtime;
  }
  if (!Filename.empty()) {
    if (get_file_mtime(Filename.c_str(), &time_to_set) == -1) {
      std::cerr << "--from-file " << Filename << ": " << strerror(errno) << std::endl;
      exit(EX_DATAERR);
    }
    mode = ModeSetToFile;
  }

  // A list of filenames is required.
  if (InputFilenames.empty()) {
    cl::PrintHelpMessage();
    exit(EX_USAGE);
  }

  // Modify all files' access and modification times.
  for (std::string file : InputFilenames) {
    const char* filename = file.c_str();

    struct timespec previous_timestamp = { 0, UTIME_OMIT };
    if (Verbose) {
      if (get_file_mtime(filename, &previous_timestamp) == -1) {
        fprintf(stderr, "%s: %s\n", filename, strerror(errno));
        exit(EX_NOINPUT);
      }
    }

    switch (mode) {
    case ModeSetToNow:
    case ModeSetToFile:   // -f, --from
      if (file_time_set_fixed(filename, time_to_set) == -1) {
        fprintf(stderr, "%s: %s\n", filename, strerror(errno));
        exit(EX_NOINPUT);
      }
      break;
    case ModeAdjustMtime:  // -a, --adjust
      if (file_time_adjust_relative(filename, adjust_relative_sec) == -1) {
        fprintf(stderr, "%s: %s\n", filename, strerror(errno));
        exit(EX_NOINPUT);
      }
      break;
    case ModeMtimePlusULP:
    case ModeMtimeMinusULP:
      if (file_time_adjust_epsilon(filename, mode == ModeMtimeMinusULP ? -1 : 1) == -1) {
        fprintf(stderr, "%s: %s\n", filename, strerror(errno));
        exit(EX_NOINPUT);
      }
      break;
    case ModeNowPlusULP:
    case ModeNowMinusULP:
      struct timespec now = { 0, UTIME_NOW };
      if (file_time_set_fixed(filename, now) == -1) {
        fprintf(stderr, "%s: %s\n", filename, strerror(errno));
        exit(EX_NOINPUT);
      }
      if (file_time_adjust_epsilon(filename, mode == ModeNowMinusULP ? -1 : 1) == -1) {
        fprintf(stderr, "%s: %s\n", filename, strerror(errno));
        exit(EX_NOINPUT);
      }
      break;
    }

    if (Verbose) {
      struct timespec final_timestamp;
      if (get_file_mtime(filename, &final_timestamp) == -1) {
        fprintf(stderr, "%s: %s\n", filename, strerror(errno));
        exit(EX_NOINPUT);
      }

      fprintf(stderr, "%s: ", filename);
      switch (mode) {
      case ModeSetToNow:
      case ModeSetToFile:
        fprintf(stderr, "reset");
        break;
      case ModeAdjustMtime:
        fprintf(stderr, "adjusted %+.9gs", adjust_relative_sec);
        break;
      case ModeMtimeMinusULP:
        fprintf(stderr, "adjusted backward");
        break;
      case ModeMtimePlusULP:
        fprintf(stderr, "adjusted forward");
        break;
      case ModeNowMinusULP:
        fprintf(stderr, "set to now - epsilon");
        break;
      case ModeNowPlusULP:
        fprintf(stderr, "set to now + epsilon");
        break;
      }

      char buf_prev[64];
      char buf_final[64];
      time_format(buf_prev, sizeof(buf_prev), previous_timestamp);
      time_format(buf_final, sizeof(buf_final), final_timestamp);

      fprintf(stderr, "\n  from %s\n  to   %s\n", buf_prev, buf_final);
    }
  }

  return 0;
}