Пример #1
0
static void
test_ctype(void)
{
	int c;

	for (c = -1; c < 256; c++) {
		/* Test blank. */
		if (c == '\t' || c == ' ')
			test_pass(c_isblank(c));
		else
			test_fail(c_isblank(c));

		/* Test white. */
		if (c == '\t' || c == ' ' || c == '\n')
			test_pass(c_iswhite(c));
		else
			test_fail(c_iswhite(c));

		/* Test space. */
		if (c == '\t' || c == '\v' || c == '\f' ||
		    c == '\r' || c == '\n' || c == ' ')
			test_pass(c_isspace(c));
		else
			test_fail(c_isspace(c));

		/* Test digit. */
		if (c >= '0' && c <= '9')
			test_pass(c_isdigit(c));
		else
			test_fail(c_isdigit(c));

		/* Test lower case. */
		if (c >= 'a' && c <= 'z')
			test_pass(c_islower(c));
		else
			test_fail(c_islower(c));

		/* Test upper case. */
		if (c >= 'A' && c <= 'Z')
			test_pass(c_isupper(c));
		else
			test_fail(c_isupper(c));

		/* Test alpha. */
		if (c_islower(c) || c_isupper(c))
			test_pass(c_isalpha(c));
		else
			test_fail(c_isalpha(c));

		/* Test alphanumeric. */
		if (c_isdigit(c) || c_isalpha(c))
			test_pass(c_isalnum(c));
		else
			test_fail(c_isalnum(c));
	}
}
Пример #2
0
/* Match a file suffix defined by this regular expression:
   /(\.[A-Za-z~][A-Za-z0-9~]*)*$/
   Scan the string *STR and return a pointer to the matching suffix, or
   NULL if not found.  Upon return, *STR points to terminating NUL.  */
static const char *
match_suffix (const char **str)
{
  const char *match = NULL;
  bool read_alpha = false;
  while (**str)
    {
      if (read_alpha)
        {
          read_alpha = false;
          if (!c_isalpha (**str) && '~' != **str)
            match = NULL;
        }
      else if ('.' == **str)
        {
          read_alpha = true;
          if (!match)
            match = *str;
        }
      else if (!c_isalnum (**str) && '~' != **str)
        match = NULL;
      (*str)++;
    }
  return match;
}
Пример #3
0
/**
 * virConfParseName:
 * @ctxt: the parsing context
 *
 * Parse one name
 *
 * Returns a copy of the new string, NULL in case of error
 */
static char *
virConfParseName(virConfParserCtxtPtr ctxt)
{
    const char *base;
    char *ret;

    SKIP_BLANKS;
    base = ctxt->cur;
    /* TODO: probably need encoding support and UTF-8 parsing ! */
    if (!c_isalpha(CUR) &&
            !((ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) && (CUR == '.'))) {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a name"));
        return NULL;
    }
    while ((ctxt->cur < ctxt->end) &&
            (c_isalnum(CUR) || (CUR == '_') ||
             ((ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) &&
              ((CUR == ':') || (CUR == '.') || (CUR == '-'))) ||
             ((ctxt->conf->flags & VIR_CONF_FLAG_LXC_FORMAT) &&
              (CUR == '.'))))
        NEXT;
    if (VIR_STRNDUP(ret, base, ctxt->cur - base) < 0)
        return NULL;
    return ret;
}
Пример #4
0
static int
uncomment_all_params(char *data,
                     size_t **ret)
{
    size_t count = 0;
    char *tmp;
    size_t *params = 0;

    tmp = data;
    while (tmp && *tmp) {
        tmp = strchr(tmp, '\n');
        if (!tmp)
            break;

        tmp++;

        /* Uncomment any lines starting   #some_var */
        if (*tmp == '#' &&
            c_isalpha(*(tmp + 1))) {
            if (VIR_EXPAND_N(params, count, 1) < 0) {
                VIR_FREE(params);
                return -1;
            }
            *tmp = ' ';
            params[count-1] = (tmp + 1) - data;
        }
    }
    if (VIR_EXPAND_N(params, count, 1) < 0) {
        VIR_FREE(params);
        return -1;
    }
    params[count-1] = 0;
    *ret = params;
    return count;
}
Пример #5
0
static void
canonical_device_name (char *dev)
{
  if (STRPREFIX (dev, "/dev/") &&
      (dev[5] == 'h' || dev[5] == 'v') &&
      dev[6] == 'd' &&
      c_isalpha (dev[7]) &&
      (c_isdigit (dev[8]) || dev[8] == '\0'))
    dev[5] = 's';
}
Пример #6
0
/* verrevcmp helper function */
static inline int
order (unsigned char c)
{
  if (c_isdigit (c))
    return 0;
  else if (c_isalpha (c))
    return c;
  else if (c == '~')
    return -1;
  else
    return (int) c + UCHAR_MAX + 1;
}
Пример #7
0
static char *
windows_path (guestfs_h *g, const char *root, const char *path)
{
  char *ret;
  size_t i;

  /* If there is a drive letter, rewrite the path. */
  if (c_isalpha (path[0]) && path[1] == ':') {
    char drive_letter = c_tolower (path[0]);
    /* This returns the newly allocated string. */
    mount_drive_letter (drive_letter, root);
    ret = strdup (path + 2);
    if (ret == NULL) {
      perror ("strdup");
      exit (EXIT_FAILURE);
    }
  }
  else if (!*path) {
    ret = strdup ("/");
    if (ret == NULL) {
      perror ("strdup");
      exit (EXIT_FAILURE);
    }
  }
  else {
    ret = strdup (path);
    if (ret == NULL) {
      perror ("strdup");
      exit (EXIT_FAILURE);
    }
  }

  /* Blindly convert any backslashes into forward slashes.  Is this good? */
  for (i = 0; i < strlen (ret); ++i)
    if (ret[i] == '\\')
      ret[i] = '/';

  char *t = guestfs_case_sensitive_path (g, ret);
  free (ret);
  ret = t;
  if (ret == NULL)
    exit (EXIT_FAILURE);

  return ret;
}
static int
check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
{
  int r;
  size_t len = strlen (fs->windows_systemroot) + 64;
  char system[len];
  snprintf (system, len, "%s/system32/config/system",
            fs->windows_systemroot);

  CLEANUP_FREE char *system_path = guestfs_case_sensitive_path (g, system);
  if (!system_path)
    return -1;

  r = guestfs_is_file (g, system_path);
  if (r == -1)
    return -1;
  /* If the system hive doesn't exist, just accept that we cannot
   * find hostname etc.
   */
  if (r == 0)
    return 0;

  int ret = -1;
  int64_t root, node, value;
  CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values = NULL;
  CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values2 = NULL;
  int32_t dword;
  size_t i, count;
  CLEANUP_FREE void *buf = NULL;
  size_t buflen;
  const char *hivepath[] =
    { NULL /* current control set */, "Services", "Tcpip", "Parameters" };

  if (guestfs_hivex_open (g, system_path,
                          GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1)
    goto out;

  root = guestfs_hivex_root (g);
  if (root == 0)
    goto out;

  /* Get the CurrentControlSet. */
  node = guestfs_hivex_node_get_child (g, root, "Select");
  if (node == -1)
    goto out;

  if (node == 0) {
    error (g, "hivex: could not locate HKLM\\SYSTEM\\Select");
    goto out;
  }

  value = guestfs_hivex_node_get_value (g, node, "Current");
  if (value == -1)
    goto out;

  if (value == 0) {
    error (g, "hivex: HKLM\\System\\Select Default entry not found");
    goto out;
  }

  /* XXX Should check the type. */
  buf = guestfs_hivex_value_value (g, value, &buflen);
  if (buflen != 4) {
    error (g, "hivex: HKLM\\System\\Select\\Current expected to be DWORD");
    goto out;
  }
  dword = le32toh (*(int32_t *)buf);
  fs->windows_current_control_set = safe_asprintf (g, "ControlSet%03d", dword);

  /* Get the drive mappings.
   * This page explains the contents of HKLM\System\MountedDevices:
   * http://www.goodells.net/multiboot/partsigs.shtml
   */
  node = guestfs_hivex_node_get_child (g, root, "MountedDevices");
  if (node == -1)
    goto out;

  if (node == 0)
    /* Not found: skip getting drive letter mappings (RHBZ#803664). */
    goto skip_drive_letter_mappings;

  values = guestfs_hivex_node_values (g, node);

  /* Count how many DOS drive letter mappings there are.  This doesn't
   * ignore removable devices, so it overestimates, but that doesn't
   * matter because it just means we'll allocate a few bytes extra.
   */
  for (i = count = 0; i < values->len; ++i) {
    CLEANUP_FREE char *key =
      guestfs_hivex_value_key (g, values->val[i].hivex_value_h);
    if (key == NULL)
      goto out;
    if (STRCASEEQLEN (key, "\\DosDevices\\", 12) &&
        c_isalpha (key[12]) && key[13] == ':')
      count++;
  }

  fs->drive_mappings = safe_calloc (g, 2*count + 1, sizeof (char *));

  for (i = count = 0; i < values->len; ++i) {
    int64_t v = values->val[i].hivex_value_h;
    CLEANUP_FREE char *key = guestfs_hivex_value_key (g, v);
    if (key == NULL)
      goto out;
    if (STRCASEEQLEN (key, "\\DosDevices\\", 12) &&
        c_isalpha (key[12]) && key[13] == ':') {
      /* Get the binary value.  Is it a fixed disk? */
      CLEANUP_FREE char *blob = NULL;
      char *device;
      size_t len;
      int64_t type;

      type = guestfs_hivex_value_type (g, v);
      blob = guestfs_hivex_value_value (g, v, &len);
      if (blob != NULL && type == 3 && len == 12) {
        /* Try to map the blob to a known disk and partition. */
        device = map_registry_disk_blob (g, blob);
        if (device != NULL) {
          fs->drive_mappings[count++] = safe_strndup (g, &key[12], 1);
          fs->drive_mappings[count++] = device;
        }
      }
    }
  }

 skip_drive_letter_mappings:;
  /* Get the hostname. */
  hivepath[0] = fs->windows_current_control_set;
  for (node = root, i = 0;
       node > 0 && i < sizeof hivepath / sizeof hivepath[0];
       ++i) {
    node = guestfs_hivex_node_get_child (g, node, hivepath[i]);
  }

  if (node == -1)
    goto out;

  if (node == 0) {
    perrorf (g, "hivex: cannot locate HKLM\\SYSTEM\\%s\\Services\\Tcpip\\Parameters",
             fs->windows_current_control_set);
    goto out;
  }

  values2 = guestfs_hivex_node_values (g, node);
  if (values2 == NULL)
    goto out;

  for (i = 0; i < values2->len; ++i) {
    int64_t v = values2->val[i].hivex_value_h;
    CLEANUP_FREE char *key = guestfs_hivex_value_key (g, v);
    if (key == NULL)
      goto out;

    if (STRCASEEQ (key, "Hostname")) {
      fs->hostname = guestfs_hivex_value_utf8 (g, v);
      if (!fs->hostname)
        goto out;
    }
    /* many other interesting fields here ... */
  }

  ret = 0;

 out:
  guestfs_hivex_close (g);

  return ret;
}
Пример #9
0
/* Parse a line like: "active raid1 sdb1[0] sdc1[1](F)" */
static guestfs_int_mdstat_list *
parse_md_stat_line (char *line)
{
  guestfs_int_mdstat_list *ret;
  guestfs_int_mdstat *t;
  size_t spaces, n, i, len;
  char *next;
  char *p, *q;

  ret = malloc (sizeof *ret);
  if (!ret) {
    reply_with_perror ("malloc");
    return NULL;
  }

  /* We don't know exactly how many entries we will need yet, but we
   * can estimate it, and this will always be an over-estimate.
   */
  spaces = count_spaces (line);
  ret->guestfs_int_mdstat_list_val =
    calloc (spaces+1, sizeof (struct guestfs_int_mdstat));
  if (ret->guestfs_int_mdstat_list_val == NULL) {
    reply_with_perror ("calloc");
    free (ret);
    return NULL;
  }

  for (n = 0; *line; line = next) {
    len = strcspn (line, " ");
    if (line[len] == '\0')
      next = &line[len];
    else {
      line[len] = '\0';
      next = &line[len+1];
    }

    if (verbose)
      printf ("mdstat: %s\n", line);

    /* Looking for entries that contain "[..]", skip ones which don't. */
    p = strchr (line, '[');
    if (p == NULL)
      continue;
    q = strchr (line, ']');
    if (q == NULL)
      continue;
    if (p > q)
      continue;

    ret->guestfs_int_mdstat_list_len = n+1;
    t = &ret->guestfs_int_mdstat_list_val[n];

    /* Device name is everything before the '[' character, but we
     * need to prefix with /dev/.
     */
    if (p == line) {
      reply_with_error ("device entry is too short: %s", line);
      goto error;
    }

    *p = '\0';
    if (asprintf (&t->mdstat_device, "/dev/%s", line) == -1) {
      reply_with_perror ("asprintf");
      goto error;
    }

    /* Device index is the number after '['. */
    line = p+1;
    *q = '\0';
    if (sscanf (line, "%" SCNi32, &t->mdstat_index) != 1) {
      reply_with_error ("not a device number: %s", line);
      goto error;
    }

    /* Looking for flags "(F)(S)...". */
    line = q+1;
    len = strlen (line);
    t->mdstat_flags = malloc (len+1);
    if (!t->mdstat_flags) {
      reply_with_error ("malloc");
      goto error;
    }

    for (i = 0; *line; line++) {
      if (c_isalpha (*line))
        t->mdstat_flags[i++] = *line;
    }
    t->mdstat_flags[i] = '\0';

    n++;
  }

  return ret;

 error:
  for (i = 0; i < spaces+1; ++i) {
    free (ret->guestfs_int_mdstat_list_val[i].mdstat_device);
    free (ret->guestfs_int_mdstat_list_val[i].mdstat_flags);
  }
  free (ret->guestfs_int_mdstat_list_val);
  free (ret);
  return NULL;
}
Пример #10
0
/**
 * Parse a version string and check for invalid syntax.
 *
 * Distinguish between lax (warnings) and strict (error) parsing.
 *
 * @param rversion The parsed version.
 * @param string The version string to parse.
 * @param err The warning or error message if any.
 *
 * @retval  0 On success.
 * @retval -1 On failure, and err is set accordingly.
 */
int
parseversion(struct dpkg_version *rversion, const char *string,
             struct dpkg_error *err)
{
  char *hyphen, *colon, *eepochcolon;
  const char *end, *ptr;

  /* Trim leading and trailing space. */
  while (*string && c_isblank(*string))
    string++;

  if (!*string)
    return dpkg_put_error(err, _("version string is empty"));

  /* String now points to the first non-whitespace char. */
  end = string;
  /* Find either the end of the string, or a whitespace char. */
  while (*end && !c_isblank(*end))
    end++;
  /* Check for extra chars after trailing space. */
  ptr = end;
  while (*ptr && c_isblank(*ptr))
    ptr++;
  if (*ptr)
    return dpkg_put_error(err, _("version string has embedded spaces"));

  colon= strchr(string,':');
  if (colon) {
    long epoch;

    errno = 0;
    epoch = strtol(string, &eepochcolon, 10);
    if (string == eepochcolon)
      return dpkg_put_error(err, _("epoch in version is empty"));
    if (colon != eepochcolon)
      return dpkg_put_error(err, _("epoch in version is not number"));
    if (epoch < 0)
      return dpkg_put_error(err, _("epoch in version is negative"));
    if (epoch > INT_MAX || errno == ERANGE)
      return dpkg_put_error(err, _("epoch in version is too big"));
    if (!*++colon)
      return dpkg_put_error(err, _("nothing after colon in version number"));
    string= colon;
    rversion->epoch= epoch;
  } else {
    rversion->epoch= 0;
  }
  rversion->version= nfstrnsave(string,end-string);
  hyphen= strrchr(rversion->version,'-');
  if (hyphen) {
    *hyphen++ = '\0';

    if (*hyphen == '\0')
      return dpkg_put_error(err, _("revision number is empty"));
  }
  rversion->revision= hyphen ? hyphen : "";

  /* XXX: Would be faster to use something like cisversion and cisrevision. */
  ptr = rversion->version;
  if (!*ptr)
    return dpkg_put_error(err, _("version number is empty"));
  if (*ptr && !c_isdigit(*ptr++))
    return dpkg_put_warn(err, _("version number does not start with digit"));
  for (; *ptr; ptr++) {
    if (!c_isdigit(*ptr) && !c_isalpha(*ptr) && strchr(".-+~:", *ptr) == NULL)
      return dpkg_put_warn(err, _("invalid character in version number"));
  }
  for (ptr = rversion->revision; *ptr; ptr++) {
    if (!c_isdigit(*ptr) && !c_isalpha(*ptr) && strchr(".+~", *ptr) == NULL)
      return dpkg_put_warn(err, _("invalid character in revision number"));
  }

  return 0;
}
Пример #11
0
static void
test_all (void)
{
  int c;

  for (c = -0x80; c < 0x100; c++)
    {
      ASSERT (c_isascii (c) == (c >= 0 && c < 0x80));

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
          ASSERT (c_isalnum (c) == 1);
          break;
        default:
          ASSERT (c_isalnum (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
          ASSERT (c_isalpha (c) == 1);
          break;
        default:
          ASSERT (c_isalpha (c) == 0);
          break;
        }

      switch (c)
        {
        case '\t': case ' ':
          ASSERT (c_isblank (c) == 1);
          break;
        default:
          ASSERT (c_isblank (c) == 0);
          break;
        }

      ASSERT (c_iscntrl (c) == ((c >= 0 && c < 0x20) || c == 0x7f));

      switch (c)
        {
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
          ASSERT (c_isdigit (c) == 1);
          break;
        default:
          ASSERT (c_isdigit (c) == 0);
          break;
        }

      switch (c)
        {
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
          ASSERT (c_islower (c) == 1);
          break;
        default:
          ASSERT (c_islower (c) == 0);
          break;
        }

      ASSERT (c_isgraph (c) == ((c >= 0x20 && c < 0x7f) && c != ' '));

      ASSERT (c_isprint (c) == (c >= 0x20 && c < 0x7f));

      ASSERT (c_ispunct (c) == (c_isgraph (c) && !c_isalnum (c)));

      switch (c)
        {
        case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
          ASSERT (c_isspace (c) == 1);
          break;
        default:
          ASSERT (c_isspace (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
          ASSERT (c_isupper (c) == 1);
          break;
        default:
          ASSERT (c_isupper (c) == 0);
          break;
        }

      switch (c)
        {
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
          ASSERT (c_isxdigit (c) == 1);
          break;
        default:
          ASSERT (c_isxdigit (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A':
          ASSERT (c_tolower (c) == 'a');
          ASSERT (c_toupper (c) == c);
          break;
        case 'B':
          ASSERT (c_tolower (c) == 'b');
          ASSERT (c_toupper (c) == c);
          break;
        case 'C':
          ASSERT (c_tolower (c) == 'c');
          ASSERT (c_toupper (c) == c);
          break;
        case 'D':
          ASSERT (c_tolower (c) == 'd');
          ASSERT (c_toupper (c) == c);
          break;
        case 'E':
          ASSERT (c_tolower (c) == 'e');
          ASSERT (c_toupper (c) == c);
          break;
        case 'F':
          ASSERT (c_tolower (c) == 'f');
          ASSERT (c_toupper (c) == c);
          break;
        case 'G':
          ASSERT (c_tolower (c) == 'g');
          ASSERT (c_toupper (c) == c);
          break;
        case 'H':
          ASSERT (c_tolower (c) == 'h');
          ASSERT (c_toupper (c) == c);
          break;
        case 'I':
          ASSERT (c_tolower (c) == 'i');
          ASSERT (c_toupper (c) == c);
          break;
        case 'J':
          ASSERT (c_tolower (c) == 'j');
          ASSERT (c_toupper (c) == c);
          break;
        case 'K':
          ASSERT (c_tolower (c) == 'k');
          ASSERT (c_toupper (c) == c);
          break;
        case 'L':
          ASSERT (c_tolower (c) == 'l');
          ASSERT (c_toupper (c) == c);
          break;
        case 'M':
          ASSERT (c_tolower (c) == 'm');
          ASSERT (c_toupper (c) == c);
          break;
        case 'N':
          ASSERT (c_tolower (c) == 'n');
          ASSERT (c_toupper (c) == c);
          break;
        case 'O':
          ASSERT (c_tolower (c) == 'o');
          ASSERT (c_toupper (c) == c);
          break;
        case 'P':
          ASSERT (c_tolower (c) == 'p');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Q':
          ASSERT (c_tolower (c) == 'q');
          ASSERT (c_toupper (c) == c);
          break;
        case 'R':
          ASSERT (c_tolower (c) == 'r');
          ASSERT (c_toupper (c) == c);
          break;
        case 'S':
          ASSERT (c_tolower (c) == 's');
          ASSERT (c_toupper (c) == c);
          break;
        case 'T':
          ASSERT (c_tolower (c) == 't');
          ASSERT (c_toupper (c) == c);
          break;
        case 'U':
          ASSERT (c_tolower (c) == 'u');
          ASSERT (c_toupper (c) == c);
          break;
        case 'V':
          ASSERT (c_tolower (c) == 'v');
          ASSERT (c_toupper (c) == c);
          break;
        case 'W':
          ASSERT (c_tolower (c) == 'w');
          ASSERT (c_toupper (c) == c);
          break;
        case 'X':
          ASSERT (c_tolower (c) == 'x');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Y':
          ASSERT (c_tolower (c) == 'y');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Z':
          ASSERT (c_tolower (c) == 'z');
          ASSERT (c_toupper (c) == c);
          break;
        case 'a':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'A');
          break;
        case 'b':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'B');
          break;
        case 'c':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'C');
          break;
        case 'd':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'D');
          break;
        case 'e':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'E');
          break;
        case 'f':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'F');
          break;
        case 'g':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'G');
          break;
        case 'h':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'H');
          break;
        case 'i':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'I');
          break;
        case 'j':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'J');
          break;
        case 'k':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'K');
          break;
        case 'l':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'L');
          break;
        case 'm':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'M');
          break;
        case 'n':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'N');
          break;
        case 'o':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'O');
          break;
        case 'p':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'P');
          break;
        case 'q':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Q');
          break;
        case 'r':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'R');
          break;
        case 's':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'S');
          break;
        case 't':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'T');
          break;
        case 'u':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'U');
          break;
        case 'v':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'V');
          break;
        case 'w':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'W');
          break;
        case 'x':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'X');
          break;
        case 'y':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Y');
          break;
        case 'z':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Z');
          break;
        default:
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == c);
          break;
        }
    }
}
Пример #12
0
enum TOKEN
scanner_get_token ()
{
  char *pend;

  if (have_peek)
    {
      have_peek = false;
      return scan_peek;
    }

  assert (scan_pos != NULL);                      /* LCOV_EXCL_LINE */

  if (*scan_pos == '\0')
    return TOK_END;

  /* White space */
  if (c_isspace (*scan_pos))
    {
      while ( c_isspace (*scan_pos) )
        ++scan_pos;
      if (scanner_keep_whitespace)
        {
          if (*scan_pos == '\0')
            return TOK_END;
          return TOK_WHITESPACE;
        }
    }

  /* special characters */
  if (*scan_pos == ',')
    {
      ++scan_pos;
      set_identifier (",", 1);
      return TOK_COMMA;
    }
  if (*scan_pos == '-')
    {
      ++scan_pos;
      set_identifier ("-", 1);
      return TOK_DASH;
    }
  if (*scan_pos == ':')
    {
      ++scan_pos;
      set_identifier (":", 1);
      return TOK_COLONS;
    }

  /* Integer or floating-point value */
  if (c_isdigit (*scan_pos))
    {
      enum TOKEN rc = TOK_INTEGER;
      errno = 0;
      scan_val_int = strtol (scan_pos, &pend, 10);

      if (*pend == '.')
        {
          /* a floating-point value */
          scan_val_float = strtold (scan_pos, &pend);
          rc = TOK_FLOAT;
        }
      if ((c_isalpha (*pend) || *pend=='_') || (errno == ERANGE))
        die (EXIT_FAILURE, 0, _("invalid numeric value '%s'"),
                                scan_pos);

      set_identifier (scan_pos, pend-scan_pos);
      scan_pos = pend;
      return rc;
    }

  /* a valid identifier ( [a-z_][a-z0-9_]+ ) */
  if (c_isalpha (*scan_pos) || *scan_pos == '_')
    {
      size_t l=1;
      char *v=scan_pos+1;
      while ( c_isalpha (*v) || c_isdigit (*v) || *v=='_' )
        ++l, ++v;

      set_identifier (scan_pos, l);
      scan_pos += l;
      return TOK_IDENTIFIER;
    }

  die (EXIT_FAILURE, 0, _("invalid operand %s"), quote (scan_pos));
  return TOK_END;
}
Пример #13
0
static void *
format_parse (const char *format, bool translated, char **invalid_reason)
{
  struct spec spec;
  struct spec *result;

  spec.directives = 0;
  spec.named_arg_count = 0;
  spec.allocated = 0;
  spec.named = NULL;

  for (; *format != '\0';)
    if (*format++ == '$')
      {
	/* A variable substitution.  */
	char *name;

	spec.directives++;

	if (*format == '{')
	  {
	    const char *name_start;
	    const char *name_end;
	    size_t n;

	    name_start = ++format;
	    for (; *format != '\0'; format++)
	      {
		if (*format == '}')
		  break;
		if (!c_isascii (*format))
		  {
		    *invalid_reason = INVALID_NON_ASCII_VARIABLE ();
		    goto bad_format;
		  }
		if (format > name_start
		    && (*format == '-' || *format == '=' || *format == '+'
			|| *format == '?' || *format == ':'))
		  {
		    *invalid_reason = INVALID_SHELL_SYNTAX ();
		    goto bad_format;
		  }
		if (!(c_isalnum (*format) || *format == '_')
		    || (format == name_start && c_isdigit (*format)))
		  {
		    *invalid_reason = INVALID_CONTEXT_DEPENDENT_VARIABLE ();
		    goto bad_format;
		  }
	      }
	    if (*format == '\0')
	      {
		*invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
		goto bad_format;
	      }
	    name_end = format++;

	    n = name_end - name_start;
	    if (n == 0)
	      {
		*invalid_reason = INVALID_EMPTY_VARIABLE ();
		goto bad_format;
	      }
	    name = (char *) xmalloc (n + 1);
	    memcpy (name, name_start, n);
	    name[n] = '\0';
	  }
	else if (c_isalpha (*format) || *format == '_')
	  {
	    const char *name_start;
	    const char *name_end;
	    size_t n;

	    name_start = format;
	    do
	      format++;
	    while (*format != '\0' && (c_isalnum (*format) || *format == '_'));
	    name_end = format;

	    n = name_end - name_start;
	    name = (char *) xmalloc (n + 1);
	    memcpy (name, name_start, n);
	    name[n] = '\0';
	  }
	else if (*format != '\0')
	  {
	    if (!c_isascii (*format))
	      {
		*invalid_reason = INVALID_NON_ASCII_VARIABLE ();
		goto bad_format;
	      }
	    else
	      {
		*invalid_reason = INVALID_CONTEXT_DEPENDENT_VARIABLE ();
		goto bad_format;
	      }
	  }
	else
	  {
	    *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
	    goto bad_format;
	  }

	/* Named argument.  */
	if (spec.allocated == spec.named_arg_count)
	  {
	    spec.allocated = 2 * spec.allocated + 1;
	    spec.named = (struct named_arg *) xrealloc (spec.named, spec.allocated * sizeof (struct named_arg));
	  }
	spec.named[spec.named_arg_count].name = name;
	spec.named_arg_count++;
      }

  /* Sort the named argument array, and eliminate duplicates.  */
  if (spec.named_arg_count > 1)
    {
      unsigned int i, j;

      qsort (spec.named, spec.named_arg_count, sizeof (struct named_arg),
	     named_arg_compare);

      /* Remove duplicates: Copy from i to j, keeping 0 <= j <= i.  */
      for (i = j = 0; i < spec.named_arg_count; i++)
	if (j > 0 && strcmp (spec.named[i].name, spec.named[j-1].name) == 0)
	  free (spec.named[i].name);
	else
	  {
	    if (j < i)
	      spec.named[j].name = spec.named[i].name;
	    j++;
	  }
      spec.named_arg_count = j;
    }

  result = (struct spec *) xmalloc (sizeof (struct spec));
  *result = spec;
  return result;

 bad_format:
  if (spec.named != NULL)
    {
      unsigned int i;
      for (i = 0; i < spec.named_arg_count; i++)
	free (spec.named[i].name);
      free (spec.named);
    }
  return NULL;
}
Пример #14
0
/* Typical crazy output from the xfs_info command:
 *
 * meta-data=/dev/sda1              isize=256    agcount=4, agsize=6392 blks
 *          =                       sectsz=512   attr=2
 *[         =                       crc=0                                    ]
 * data     =                       bsize=4096   blocks=25568, imaxpct=25
 *          =                       sunit=0      swidth=0 blks
 * naming   =version 2              bsize=4096   ascii-ci=0
 * log      =internal               bsize=4096   blocks=1200, version=2
 *          =                       sectsz=512   sunit=0 blks, lazy-count=1
 * realtime =none                   extsz=4096   blocks=0, rtextents=0
 *
 * [...] line only appears in Fedora >= 21
 *
 * We may need to revisit this parsing code if the output changes
 * in future.
 */
static guestfs_int_xfsinfo *
parse_xfs_info (char **lines)
{
  guestfs_int_xfsinfo *ret;
  CLEANUP_FREE char *section = NULL; /* first column, eg "meta-data", "data" */
  char *p;
  size_t i;

  ret = malloc (sizeof *ret);
  if (ret == NULL) {
    reply_with_error ("malloc");
    return NULL;
  }

  /* Initialize fields to NULL or -1 so the caller can tell which fields
   * were updated in the code below.
   */
  ret->xfs_mntpoint = NULL;
  ret->xfs_inodesize = -1;
  ret->xfs_agcount = -1;
  ret->xfs_agsize = -1;
  ret->xfs_sectsize = -1;
  ret->xfs_attr = -1;
  ret->xfs_blocksize = -1;
  ret->xfs_datablocks = -1;
  ret->xfs_imaxpct = -1;
  ret->xfs_sunit = -1;
  ret->xfs_swidth = -1;
  ret->xfs_dirversion = -1;
  ret->xfs_dirblocksize = -1;
  ret->xfs_cimode = -1;
  ret->xfs_logname = NULL;
  ret->xfs_logblocksize = -1;
  ret->xfs_logblocks = -1;
  ret->xfs_logversion = -1;
  ret->xfs_logsectsize = -1;
  ret->xfs_logsunit = -1;
  ret->xfs_lazycount = -1;
  ret->xfs_rtname = NULL;
  ret->xfs_rtextsize = -1;
  ret->xfs_rtblocks = -1;
  ret->xfs_rtextents = -1;

  for (i = 0; lines[i] != NULL; ++i) {
    if (verbose)
      fprintf (stderr, "xfs_info: lines[%zu] = \'%s\'\n", i, lines[i]);

    if (c_isalpha (lines[i][0])) {
      free (section);
      section = split_strdup (lines[i]);
      if (!section) goto error;

      if (verbose)
	fprintf (stderr, "xfs_info: new section %s\n", section);
    }

    if ((p = strstr (lines[i], "meta-data="))) {
      ret->xfs_mntpoint = split_strdup (p + 10);
      if (ret->xfs_mntpoint == NULL) goto error;
    }
    if ((p = strstr (lines[i], "isize="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 6);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_inodesize, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "agcount="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 8);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_agcount, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "agsize="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 7);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_agsize, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "sectsz="))) {
      if (section) {
	CLEANUP_FREE char *buf = split_strdup (p + 7);
	if (buf == NULL) goto error;
	if (STREQ (section, "meta-data")) {
	  if (parse_uint32 (&ret->xfs_sectsize, buf) == -1)
	    goto error;
	} else if (STREQ (section, "log")) {
	  if (parse_uint32 (&ret->xfs_logsectsize, buf) == -1)
	    goto error;
	}
      }
    }
    if ((p = strstr (lines[i], "attr="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 5);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_attr, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "bsize="))) {
      if (section) {
	CLEANUP_FREE char *buf = split_strdup (p + 6);
	if (buf == NULL) goto error;
	if (STREQ (section, "data")) {
	  if (parse_uint32 (&ret->xfs_blocksize, buf) == -1)
	    goto error;
	} else if (STREQ (section, "naming")) {
	  if (parse_uint32 (&ret->xfs_dirblocksize, buf) == -1)
	    goto error;
	} else if (STREQ (section, "log")) {
	  if (parse_uint32 (&ret->xfs_logblocksize, buf) == -1)
	    goto error;
	}
      }
    }
    if ((p = strstr (lines[i], "blocks="))) {
      if (section) {
	CLEANUP_FREE char *buf = split_strdup (p + 7);
	if (buf == NULL) goto error;
	if (STREQ (section, "data")) {
	  if (parse_uint64 (&ret->xfs_datablocks, buf) == -1)
	    goto error;
	} else if (STREQ (section, "log")) {
	  if (parse_uint32 (&ret->xfs_logblocks, buf) == -1)
	    goto error;
	} else if (STREQ (section, "realtime")) {
	  if (parse_uint64 (&ret->xfs_rtblocks, buf) == -1)
	    goto error;
	}
      }
    }
    if ((p = strstr (lines[i], "imaxpct="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 8);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_imaxpct, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "sunit="))) {
      if (section) {
	CLEANUP_FREE char *buf = split_strdup (p + 6);
	if (buf == NULL) goto error;
	if (STREQ (section, "data")) {
	  if (parse_uint32 (&ret->xfs_sunit, buf) == -1)
	    goto error;
	} else if (STREQ (section, "log")) {
	  if (parse_uint32 (&ret->xfs_logsunit, buf) == -1)
	    goto error;
	}
      }
    }
    if ((p = strstr (lines[i], "swidth="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 7);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_swidth, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "naming   =version "))) {
      CLEANUP_FREE char *buf = split_strdup (p + 18);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_dirversion, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "ascii-ci="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 9);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_cimode, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "log      ="))) {
      ret->xfs_logname = split_strdup (p + 10);
      if (ret->xfs_logname == NULL) goto error;
    }
    if ((p = strstr (lines[i], "version="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 8);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_logversion, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "lazy-count="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 11);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_lazycount, buf) == -1)
        goto error;
    }
    if ((p = strstr (lines[i], "realtime ="))) {
      ret->xfs_rtname = split_strdup (p + 10);
      if (ret->xfs_rtname == NULL) goto error;
    }
    if ((p = strstr (lines[i], "rtextents="))) {
      CLEANUP_FREE char *buf = split_strdup (p + 10);
      if (buf == NULL) goto error;
      if (parse_uint64 (&ret->xfs_rtextents, buf) == -1)
        goto error;
    }
  }

  if (ret->xfs_mntpoint == NULL) {
    ret->xfs_mntpoint = strdup ("");
    if (ret->xfs_mntpoint == NULL) goto error;
  }
  if (ret->xfs_logname == NULL) {
    ret->xfs_logname = strdup ("");
    if (ret->xfs_logname == NULL) goto error;
  }
  if (ret->xfs_rtname == NULL) {
    ret->xfs_rtname = strdup ("");
    if (ret->xfs_rtname == NULL) goto error;
  }

  return ret;

 error:
  free (ret->xfs_mntpoint);
  free (ret->xfs_logname);
  free (ret->xfs_rtname);
  free (ret);
  return NULL;
}