Ejemplo n.º 1
0
/**
 * Check if two versions have a certain relation.
 *
 * @param a The first version.
 * @param rel The relation.
 * @param b The second version.
 *
 * @retval true If the expression “a rel b” is true.
 * @retval true If rel is #dpkg_relation_none.
 * @retval false Otherwise.
 *
 * @warning If rel is not a valid relation, this function will terminate
 *          the program.
 */
bool
dpkg_version_relate(const struct dpkg_version *a,
                    enum dpkg_relation rel,
                    const struct dpkg_version *b)
{
	int r;

	if (rel == dpkg_relation_none)
		return true;

	r = dpkg_version_compare(a, b);

	switch (rel) {
	case dpkg_relation_eq:
		return r == 0;
	case dpkg_relation_lt:
		return r < 0;
	case dpkg_relation_le:
		return r <= 0;
	case dpkg_relation_gt:
		return r > 0;
	case dpkg_relation_ge:
		return r >= 0;
	default:
		internerr("unknown dpkg_relation %d", rel);
	}
	return false;
}
Ejemplo n.º 2
0
int
cmpversions(const char *const *argv)
{
  struct relationinfo {
    const char *string;
    /* These values are exit status codes, so 0 = true, 1 = false. */
    int if_lesser, if_equal, if_greater;
    int if_none_a, if_none_both, if_none_b;
  };

  static const struct relationinfo relationinfos[]= {
    /*             < = > !a!2!b  */
    { "le",        0,0,1, 0,0,1  },
    { "lt",        0,1,1, 0,1,1  },
    { "eq",        1,0,1, 1,0,1  },
    { "ne",        0,1,0, 0,1,0  },
    { "ge",        1,0,0, 1,0,0  },
    { "gt",        1,1,0, 1,1,0  },

    /* These treat an empty version as later than any version. */
    { "le-nl",     0,0,1, 1,0,0  },
    { "lt-nl",     0,1,1, 1,1,0  },
    { "ge-nl",     1,0,0, 0,0,1  },
    { "gt-nl",     1,1,0, 0,1,1  },

    /* For compatibility with dpkg control file syntax. */
    { "<",         0,0,1, 0,0,1  },
    { "<=",        0,0,1, 0,0,1  },
    { "<<",        0,1,1, 0,1,1  },
    { "=",         1,0,1, 1,0,1  },
    { ">",         1,0,0, 1,0,0  },
    { ">=",        1,0,0, 1,0,0  },
    { ">>",        1,1,0, 1,1,0  },
    { NULL                       }
  };

  const struct relationinfo *rip;
  struct dpkg_version a, b;
  struct dpkg_error err;
  int r;

  if (!argv[0] || !argv[1] || !argv[2] || argv[3])
    badusage(_("--compare-versions takes three arguments:"
             " <version> <relation> <version>"));

  for (rip=relationinfos; rip->string && strcmp(rip->string,argv[1]); rip++);

  if (!rip->string) badusage(_("--compare-versions bad relation"));

  if (*argv[0] && strcmp(argv[0],"<unknown>")) {
    if (parseversion(&a, argv[0], &err) < 0) {
      if (err.type == DPKG_MSG_WARN)
        warning(_("version '%s' has bad syntax: %s"), argv[0], err.str);
      else
        ohshit(_("version '%s' has bad syntax: %s"), argv[0], err.str);
      dpkg_error_destroy(&err);
    }
  } else {
    dpkg_version_blank(&a);
  }
  if (*argv[2] && strcmp(argv[2],"<unknown>")) {
    if (parseversion(&b, argv[2], &err) < 0) {
      if (err.type == DPKG_MSG_WARN)
        warning(_("version '%s' has bad syntax: %s"), argv[2], err.str);
      else
        ohshit(_("version '%s' has bad syntax: %s"), argv[2], err.str);
      dpkg_error_destroy(&err);
    }
  } else {
    dpkg_version_blank(&b);
  }
  if (!dpkg_version_is_informative(&a)) {
    if (dpkg_version_is_informative(&b))
      return rip->if_none_a;
    else
      return rip->if_none_both;
  } else if (!dpkg_version_is_informative(&b)) {
    return rip->if_none_b;
  }
  r = dpkg_version_compare(&a, &b);
  debug(dbg_general,"cmpversions a=`%s' b=`%s' r=%d",
        versiondescribe(&a,vdew_always),
        versiondescribe(&b,vdew_always),
        r);
  if (r > 0)
    return rip->if_greater;
  else if (r < 0)
    return rip->if_lesser;
  else
    return rip->if_equal;
}