Ejemplo n.º 1
0
/**
 * Open and parse the first line of a given file as the ASCII representation
 * of an unsigned 64-bit integer.
 *
 * @param path			file path
 * @param missing		whether file may be missing (to shut up warnings)
 * @param errptr		if non-NULL, filled with error number (0 means OK)
 *
 * @return the value we parsed on the first line, 0 otherwise.
 *
 * @note
 * The ``errptr'' parameter needs to be used to distinguish between
 * a file containing "0" and a file which could not be parsed correctly.
 */
guint64
filehead_uint64(const char *path, gboolean missing, int *errptr)
{
	int fd;
	guint64 value;
	char data[FILEHEAD_LINE_MAXLEN + 1];
	ssize_t r;
	int error;

	fd = missing ?  file_open_missing(path, O_RDONLY) :
		file_open(path, O_RDONLY, 0);

	if (-1 == fd)
		goto error;

	r = read(fd, data, sizeof data - 1); /* reserve one byte for NUL */

	if ((ssize_t) -1 == r)
		goto error_close;

	g_assert(r >= 0 && UNSIGNED(r) < sizeof data);

	fd_close(&fd);
	data[r] = '\0';
	value = parse_uint64(data, NULL, 10, &error);

	if (error) {
		errno = error;
		goto error;
	}

	if (errptr != NULL)
		*errptr = 0;

	return value;

error_close:
	fd_close(&fd);
error:
	if (errptr != NULL)
		*errptr = errno;

	return 0;
}
Ejemplo n.º 2
0
static int
http_handle_content_length_header(http_t *ctx, const char *name, char *value)
{
  uint64_t u;
  int error;
  char *ep;

  RUNTIME_ASSERT(ctx);
  RUNTIME_ASSERT(name);
  RUNTIME_ASSERT(value);
  
  u = parse_uint64(value, &ep, 10, &error);
  if (error || '\0' != *ep) {
    http_set_status(ctx, 400, "Bad Request (Bad Content-Length)");
    return -1;
  }
  ctx->content_length = u;

  return 0;
}
Ejemplo n.º 3
0
/* Parses a sample count as either a number of samples or a duration in seconds.
 * Must be called after decimation parameters have been read from server. */
static bool parse_samples(const char **string, uint64_t *result)
{
    bool ok = parse_uint64(string, result);
    if (ok)
    {
        double duration = (double) *result; // In case it's a duration after all
        bool seconds = **string == '.';
        if (seconds)
        {
            long nsec;
            ok = parse_nanoseconds(string, &nsec)  &&  parse_char(string, 's');
            duration += 1e-9 * (double) nsec;
        }
        else
            seconds = read_char(string, 's');
        if (ok  &&  seconds)
            *result = (uint64_t) round(
                duration * sample_frequency / get_decimation());
    }

    return ok  &&  TEST_OK_(*result > 0, "Zero sample count");
}
Ejemplo n.º 4
0
/**
 * Reads data from the http context buffer (decodes it if the transfer-
 * encoding isn't "identity") and transfers up to ``buflen'' bytes into
 * ``buf''. The http context MUST be in state HTTP_STATE_BODY.
 *
 * @returns (ssize_t) -1 on failure and sets errno. If errno is set to EAGAIN
 *          further data may be available later.
 *           
 *          If there's a transfer-encoding
 *          error, errno will be set to EIO. If (-1) is returned and errno
 *          has any other value than EAGAIN, the function MUST NOT be called
 *          again.
 */
ssize_t
http_read_body(http_t *ctx, char *buf, ssize_t buflen)
{
  ssize_t ret = 0, count = 0;
  uint64_t left;
  
  RUNTIME_ASSERT(ctx != NULL);
  RUNTIME_ASSERT(buf != NULL);
  RUNTIME_ASSERT(buflen >= 0);

  RUNTIME_ASSERT(ctx->sane);
  RUNTIME_ASSERT(ctx->state == HTTP_STATE_BODY);
  
  switch (ctx->encoding) {
  case HTTP_TRANSFER_ENCODING_IDENTITY:
    
    RUNTIME_ASSERT(ctx->content_length >= ctx->received);
    left = ctx->content_length - ctx->received;
    if (left == 0) {
      return 0;
    }

    RUNTIME_ASSERT(left > 0);
    ret = fifo_read(ctx->input, buf, MIN(left, (size_t) buflen));
    if (ret > 0) {
      ctx->received += ret;
    } else if (ret == 0) {
      errno = EAGAIN;
      return -1;
    }
    count = ret;
    break;

  case HTTP_TRANSFER_ENCODING_CHUNKED:

    while (!ctx->last_chunk && buflen > 0) {

      RUNTIME_ASSERT(ctx->content_length >= ctx->received);
      left = ctx->chunk_size - ctx->chunk_received;
      if (left > 0) {
        ret = fifo_read(ctx->input, buf, MIN(left, (size_t) buflen));
        if (ret > 0) {
          RUNTIME_ASSERT(ret <= buflen);
          ctx->chunk_received += ret;
          ctx->received += ret;
          buf += ret;
          buflen -= ret;
          count += ret;
        } else {
          if (ret == 0 && count == 0) {
            errno = EAGAIN;
            return -1;
          }
          return count;
        }
      } else {
        char chunk_intro[1024];
        ssize_t pos, size;
        uint64_t v;
        char *endptr;
        int error;

        /* If this isn't the first chunk, wait for trailing <CR><LF> */
        if (ctx->chunk_size > 0) {
          pos = fifo_findchar(ctx->input, '\n', sizeof chunk_intro);
          if (pos == (ssize_t) -1) {
            if (count > 0)
              return count;
            
            errno = EAGAIN;
            return -1;
          }

          RUNTIME_ASSERT(pos >= 0 && (size_t) pos < sizeof chunk_intro);
          size = fifo_read(ctx->input, chunk_intro, pos + 1);
          RUNTIME_ASSERT(size == pos + 1);
          RUNTIME_ASSERT(chunk_intro[pos] == '\n');
          chunk_intro[pos] = '\0';
        }
        RUNTIME_ASSERT(ctx->chunk_received == ctx->chunk_size);
        /* Mark the previous chunk as completely handled */
        ctx->chunk_sum_received += ctx->chunk_size;
        ctx->chunk_size = 0;
        ctx->chunk_received = 0;

        /* Determine the size of the next chunk */
        pos = fifo_findchar(ctx->input, '\n', sizeof chunk_intro);
        if (pos == (ssize_t) -1) {
          if (count > 0)
            return count;
          errno = EAGAIN;
          return -1;
        }
      
        RUNTIME_ASSERT(pos >= 0 && (size_t) pos < sizeof chunk_intro);
        size = fifo_read(ctx->input, chunk_intro, pos + 1);
        RUNTIME_ASSERT(size == pos + 1);
        RUNTIME_ASSERT(chunk_intro[pos] == '\n');
        chunk_intro[pos] = '\0';

        /* Read the chunk header and determine its size (hex value) */
        v = parse_uint64(chunk_intro, &endptr, 16, &error);
        if (
            (!v && error) ||
            (*endptr != '\0' && !isspace((unsigned char) *endptr))
        ) {
          errno = EIO;
          ctx->sane = false;
          return -1;
        }
        if (v == 0) {
          /* Only the last chunk has a zero length */
#if 1 
          http_log(ctx, "Last chunk reached");
#endif
          ctx->last_chunk = true;
          return count > 0 ? count : 0;
        }
#if 0 
        http_log(ctx, "chunk_size=%" PRIu64, v);
#endif
        ctx->chunk_size = v;
      }
    }
    break;

  default:
    RUNTIME_ASSERT(0);
  }

  return count;
}
Ejemplo n.º 5
0
/**
 * Parses the payload of a HTTP "Range" header.
 *
 * A range with an "open end", is indicated by "end == (uint64_t) -1".
 *
 * @param s a NUL-terminated string containing the payload of a Ranger header.
 * @return 0 on failure, otherwise the amount of byte ranges in the header.
 */
size_t
http_parse_range(const char *s, struct byte_range_set **set_ptr)
{
  char *ep;
  int error;
  size_t n = 0;

  RUNTIME_ASSERT(s);

  if (set_ptr)
    *set_ptr = NULL;

  s = skip_spaces(s);
  s = skip_prefix(s, "bytes=");
  if (!s) {
    DBUG("Expected \"bytes=\"");
    goto failure;
  }
  
  while ('\0' != *s) {
    uint64_t start, end;
    
    s = skip_spaces(s);
    if (',' == *s) {
      s++;
      continue;
    }
    
    if ('-' == *s) {
      start = (uint64_t) -1;
      s++;

      if (!isdigit((unsigned char) *s)) {
        DBUG("Neither start nor end given");
        goto failure;
      }

    } else {
      start = parse_uint64(s, &ep, 10, &error);
      if (error || (uint64_t) -1 == start) {
        DBUG("Invalid range start");
        goto failure;
      }

      if ('-' != *ep) {
        DBUG("Expected '-'");
        goto failure;
      }

      s = ++ep;
    }

    if (!isdigit((unsigned char) *s)) {
      end = (uint64_t) -1;
    } else {
      end = parse_uint64(s, &ep, 10, &error);
      if (error || (uint64_t) -1 == end) {
        DBUG("Invalid range end");
        goto failure;
      }
      s = ep;
    }

    if ((uint64_t) -1 != start && start > end) {
      DBUG("range start is beyond range end");
      goto failure;
    }

    s = skip_spaces(s);
    if (',' == *s) {
      s++;
    } else if ('\0' != *s) {
      DBUG("bad character after byte range");
      goto failure;
    }

    n++;
    if (set_ptr) {
      struct byte_range_set *set = *set_ptr;

      if (!set) {
        const size_t min_num = 8;
        
        set = malloc(min_num * sizeof set->ranges + sizeof *set);
        if (!set) {
          CRIT("malloc() failed");
          goto failure;
        }
        set->n = 0;
        set->size = min_num;
        *set_ptr = set;
      }
      
      RUNTIME_ASSERT(*set_ptr);
      RUNTIME_ASSERT(set);
      
      if (set->n >= set->size) {
        void *p;

        set->size = 0 == set->size ? 8 : 2 * set->size;
        p = realloc(set, set->size * sizeof *set);
        if (!p) {
          CRIT("realloc() failed");
          goto failure;
        }
        *set_ptr = set = p;
      }

      set->ranges[set->n].start = start;
      set->ranges[set->n].end = end;
      set->n++;
    }
  }

  return n;

failure:

  DO_FREE(*set_ptr);
  
  return -1;
}
Ejemplo n.º 6
0
/* Typical crazy output from the xfs_info command:
 *
 * meta-data=/dev/sda1              isize=256    agcount=4, agsize=6392 blks
 *          =                       sectsz=512   attr=2
 * 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
 *
 * 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;
  char *buf = NULL, *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 ((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="))) {
      buf = split_strdup (p + 6);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_inodesize, buf) == -1)
        goto error;
      free (buf);
    }
    if ((p = strstr (lines[i], "agcount="))) {
      buf = split_strdup (p + 8);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_agcount, buf) == -1)
        goto error;
      free (buf);
    }
    if ((p = strstr (lines[i], "agsize="))) {
      buf = split_strdup (p + 7);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_agsize, buf) == -1)
        goto error;
      free (buf);
    }
    if ((p = strstr (lines[i], "sectsz="))) {
      buf = split_strdup (p + 7);
      if (buf == NULL) goto error;
      if (i == 1) {
        if (parse_uint32 (&ret->xfs_sectsize, buf) == -1)
          goto error;
        free (buf);
      } else if (i == 6) {
        if (parse_uint32 (&ret->xfs_logsectsize, buf) == -1)
          goto error;
        free (buf);
      } else goto error;
    }
    if ((p = strstr (lines[i], "attr="))) {
      buf = split_strdup (p + 5);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_attr, buf) == -1)
        goto error;
      free (buf);
    }
    if ((p = strstr (lines[i], "bsize="))) {
      buf = split_strdup (p + 6);
      if (buf == NULL) goto error;
      if (i == 2) {
        if (parse_uint32 (&ret->xfs_blocksize, buf) == -1)
          goto error;
        free (buf);
      } else if (i == 4) {
        if (parse_uint32 (&ret->xfs_dirblocksize, buf) == -1)
          goto error;
        free (buf);
      } else if (i == 5) {
        if (parse_uint32 (&ret->xfs_logblocksize, buf) == -1)
          goto error;
        free (buf);
      } else goto error;
    }
    if ((p = strstr (lines[i], "blocks="))) {
      buf = split_strdup (p + 7);
      if (buf == NULL) goto error;
      if (i == 2) {
        if (parse_uint64 (&ret->xfs_datablocks, buf) == -1)
          goto error;
        free (buf);
      } else if (i == 5) {
        if (parse_uint32 (&ret->xfs_logblocks, buf) == -1)
          goto error;
        free (buf);
      } else if (i == 7) {
        if (parse_uint64 (&ret->xfs_rtblocks, buf) == -1)
          goto error;
        free (buf);
      } else goto error;
    }
    if ((p = strstr (lines[i], "imaxpct="))) {
      buf = split_strdup (p + 8);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_imaxpct, buf) == -1)
        goto error;
      free (buf);
    }
    if ((p = strstr (lines[i], "sunit="))) {
      buf = split_strdup (p + 6);
      if (buf == NULL) goto error;
      if (i == 3) {
        if (parse_uint32 (&ret->xfs_sunit, buf) == -1)
          goto error;
        free (buf);
      } else if (i == 6) {
        if (parse_uint32 (&ret->xfs_logsunit, buf) == -1)
          goto error;
        free (buf);
      } else goto error;
    }
    if ((p = strstr (lines[i], "swidth="))) {
      buf = split_strdup (p + 7);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_swidth, buf) == -1)
        goto error;
      free (buf);
    }
    if ((p = strstr (lines[i], "naming   =version "))) {
      buf = split_strdup (p + 18);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_dirversion, buf) == -1)
        goto error;
      free (buf);
    }
    if ((p = strstr (lines[i], "ascii-ci="))) {
      buf = split_strdup (p + 9);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_cimode, buf) == -1)
        goto error;
      free (buf);
    }
    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="))) {
      buf = split_strdup (p + 8);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_logversion, buf) == -1)
        goto error;
      free (buf);
    }
    if ((p = strstr (lines[i], "lazy-count="))) {
      buf = split_strdup (p + 11);
      if (buf == NULL) goto error;
      if (parse_uint32 (&ret->xfs_lazycount, buf) == -1)
        goto error;
      free (buf);
    }
    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="))) {
      buf = split_strdup (p + 10);
      if (buf == NULL) goto error;
      if (parse_uint64 (&ret->xfs_rtextents, buf) == -1)
        goto error;
      free (buf);
    }
  }

  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 (buf);
  free (ret->xfs_mntpoint);
  free (ret->xfs_logname);
  free (ret->xfs_rtname);
  free (ret);
  return NULL;
}
Ejemplo n.º 7
0
/**
 * Load spam database from the supplied FILE.
 *
 * The current file format is as follows:
 *
 * # Comment
 * SHA1 <SHA-1>
 * ADDED <date>
 * END
 *
 * @returns the amount of entries loaded or -1 on failure.
 */
static G_GNUC_COLD gulong
spam_load(FILE *f)
{
	static const struct spam_item zero_item;
	struct spam_item item;
	char line[1024];
	guint line_no = 0;
	bit_array_t tag_used[BIT_ARRAY_SIZE(NUM_SPAM_TAGS)];
	gulong item_count = 0;

	g_assert(f);

	/* Reset state */
	item = zero_item;
	bit_array_init(tag_used, NUM_SPAM_TAGS);

	while (fgets(line, sizeof line, f)) {
		const char *tag_name, *value;
		char *sp, *nl;
		spam_tag_t tag;

		line_no++;

		nl = strchr(line, '\n');
		if (!nl) {
			/*
			 * If the line is too long or unterminated the file is either
			 * corrupt or was manually edited without respecting the
			 * exact format. If we continued, we would read from the
			 * middle of a line which could be the filename or ID.
			 */
			g_warning("spam_load(): "
				"line too long or missing newline in line %u",
				line_no);
			break;
		}
		*nl = '\0';

		/* Skip comments and empty lines */
		if (*line == '#' || *line == '\0')
			continue;

		sp = strchr(line, ' ');
		if (sp) {
			*sp = '\0';
			value = &sp[1];
		} else {
			value = strchr(line, '\0');
		}
		tag_name = line;

		tag = spam_string_to_tag(tag_name);
		g_assert(UNSIGNED(tag) < UNSIGNED(NUM_SPAM_TAGS));

		if (SPAM_TAG_UNKNOWN != tag && !bit_array_flip(tag_used, tag)) {
			g_warning("spam_load(): duplicate tag \"%s\" in entry in line %u",
				tag_name, line_no);
			continue;
		}
		
		switch (tag) {
		case SPAM_TAG_ADDED:
			{
				time_t t;
				
				t = date2time(value, tm_time());
				if ((time_t) -1 == t) {
					item.damaged = TRUE;
				}
			}
			break;
			
		case SPAM_TAG_SHA1:
			{
				if (strlen(value) != SHA1_BASE32_SIZE) {
					item.damaged = TRUE;
					g_warning("spam_load(): SHA-1 has wrong length.");
				} else {
					const struct sha1 *raw;

					raw = base32_sha1(value);
					if (raw)
						item.sha1 = *raw;
					else
						item.damaged = TRUE;
				}
			}
			break;

		case SPAM_TAG_NAME:
			{
				if ('\0' == value[0]) {
					item.damaged = TRUE;
					g_warning("spam_load(): Missing filename pattern.");
				} else if (!utf8_is_valid_string(value)) {
					item.damaged = TRUE;
					g_warning("spam_load(): Filename pattern is not UTF-8.");
				} else {
					item.name = h_strdup(value);
				}
			}
			break;

		case SPAM_TAG_SIZE:
			{
				const char *endptr;
				guint64 u;
				int error;
					
				u = parse_uint64(value, &endptr, 10, &error);
				if (error) {
					item.damaged = TRUE;
					g_warning("spam_load(): Cannot parse SIZE: %s", value);
				} else {
					item.min_size = u;
					item.max_size = u;

					if ('-' == endptr[0]) {
						u = parse_uint64(&endptr[1], &endptr, 10, &error);
						if (error) {
							item.damaged = TRUE;
							g_warning("spam_load(): Cannot parse SIZE: %s",
								value);
						}
						if (u < item.min_size) {
							item.damaged = TRUE;
							g_warning("spam_load(): "
								"Maximum size below minimum size");
						} else {
							item.max_size = u;
						}
					}
				}
			}
			break;

		case SPAM_TAG_END:
			if (
				!bit_array_get(tag_used, SPAM_TAG_SHA1) &&
				!bit_array_get(tag_used, SPAM_TAG_NAME)
			) {
				g_warning("spam_load(): missing SHA1 or NAME tag");
				item.damaged = TRUE;
			}
			if (!bit_array_get(tag_used, SPAM_TAG_ADDED)) {
				g_warning("spam_load(): missing ADDED tag");
				item.damaged = TRUE;
			}
			item.done = TRUE;
			break;

		case SPAM_TAG_UNKNOWN:
			/* Ignore */
			break;
			
		case NUM_SPAM_TAGS:
			g_assert_not_reached();
			break;
		}

		if (item.done && !item.damaged) {
			if (bit_array_get(tag_used, SPAM_TAG_SHA1)) {
				spam_sha1_add(&item.sha1);
				item_count++;
			}
			if (bit_array_get(tag_used, SPAM_TAG_NAME)) {
				if (!bit_array_get(tag_used, SPAM_TAG_SIZE)) {
					item.min_size = 0;
					item.max_size = MAX_INT_VAL(filesize_t);
				}
				if (
					spam_add_name_and_size(item.name,
						item.min_size, item.max_size)
				) {
					item.damaged = TRUE;	
				} else {
					item_count++;
				}
			}
		}

		if (item.damaged) {
			g_warning("Damaged spam entry in line %u: "
				"tag_name=\"%s\", value=\"%s\"",
				line_no, tag_name, value);
		}

		if (item.done) {
			/* Reset state */
			HFREE_NULL(item.name);
			item = zero_item;
			bit_array_clear_range(tag_used, 0, NUM_SPAM_TAGS - 1U);
		}
	}

	spam_sha1_sync();

	return item_count;
}
Ejemplo n.º 8
0
int options_parse(int argc, const char** argv, options_t* options)
{
  uint64_t val;
  int i;

  /* Initialize options to default values. */
  options->nconnections = DEFAULT_CONNECTIONS;
  options->nthreads = DEFAULT_THREADS;
  options->receive = DEFAULT_RECEIVE;
  options->number_thread_loops = DEFAULT_LOOPS;
  options->number_connection_loops = DEFAULT_LOOPS;
  options->client_sends_first = CLIENT_SENDS_FIRST;
  options->set_read_write_event = SET_READ_WRITE_EVENT;
  options->nprocessors = 0;

  files_init(&options->files);

  /* Last parameter is not an option. */
  argc--;

  i = 1;
  while (i < argc) {
    if (strcasecmp(argv[i], "--connections") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        files_free(&options->files);
        return -1;
      }

      if (parse_uint64(argv[i + 1],
                       MIN_CONNECTIONS,
                       MAX_CONNECTIONS,
                       &val) < 0) {
        files_free(&options->files);
        return -1;
      }

      options->nconnections = (unsigned) val;

      i += 2;
    } else if (strcasecmp(argv[i], "--threads") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        files_free(&options->files);
        return -1;
      }

      if (parse_uint64(argv[i + 1], MIN_THREADS, MAX_THREADS, &val) < 0) {
        files_free(&options->files);
        return -1;
      }

      options->nthreads = (unsigned) val;

      i += 2;
    } else if (strcasecmp(argv[i], "--receive") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        files_free(&options->files);
        return -1;
      }

      if (parse_uint64(argv[i + 1], MIN_RECEIVE, MAX_RECEIVE, &val) < 0) {
        files_free(&options->files);
        return -1;
      }

      options->receive = (unsigned) val;

      i += 2;
    } else if (strcasecmp(argv[i], "--thread-loops") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        files_free(&options->files);
        return -1;
      }

      if (parse_uint64(argv[i + 1],
                       MIN_LOOPS,
                       MAX_LOOPS,
                       &options->number_thread_loops) < 0) {
        files_free(&options->files);
        return -1;
      }

      i += 2;
    } else if (strcasecmp(argv[i], "--connection-loops") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        files_free(&options->files);
        return -1;
      }

      if (parse_uint64(argv[i + 1],
                       MIN_LOOPS,
                       MAX_LOOPS,
                       &options->number_connection_loops) < 0) {
        files_free(&options->files);
        return -1;
      }

      i += 2;
    } else if (strcasecmp(argv[i], "--client-sends-first") == 0) {
      options->client_sends_first = 1;

      i++;
    } else if (strcasecmp(argv[i], "--server-sends-first") == 0) {
      options->client_sends_first = 0;

      i++;
    } else if (strcasecmp(argv[i], "--set-read-write-event") == 0) {
      options->set_read_write_event = 1;

      i++;
    } else if (strcasecmp(argv[i], "--do-not-set-read-write-event") == 0) {
      options->set_read_write_event = 0;

      i++;
    } else if (strcasecmp(argv[i], "--processors") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        files_free(&options->files);
        return -1;
      }

      if (parse_processors(argv[i + 1],
                           options->processors,
                           &options->nprocessors) < 0) {
        files_free(&options->files);
        return -1;
      }

      i += 2;
    } else if (strcasecmp(argv[i], "--file") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        files_free(&options->files);
        return -1;
      }

      if (files_add(&options->files, argv[i + 1]) < 0) {
        files_free(&options->files);
        return -1;
      }

      i += 2;
    } else {
      files_free(&options->files);
      return -1;
    }
  }

  /* If no files have been specified... */
  if (options->files.used == 0) {
    if (files_add_dummy(&options->files) < 0) {
      files_free(&options->files);
      return -1;
    }
  }

  options->nthreads = MIN(options->nthreads, options->nconnections);

  if (options->receive == 0) {
    options->client_sends_first = 1;
  }

  return 0;
}
Ejemplo n.º 9
0
/*
 * scontrol_update_job - update the slurm job configuration per the supplied
 *	arguments
 * IN argc - count of arguments
 * IN argv - list of arguments
 * RET 0 if no slurm error, errno otherwise. parsing error prints
 *			error message and returns 0
 */
extern int scontrol_update_job(int argc, char **argv)
{
	bool update_size = false;
	int i, update_cnt = 0, rc = SLURM_SUCCESS, rc2;
	char *tag, *val;
	int taglen, vallen;
	job_desc_msg_t job_msg;
	job_array_resp_msg_t *resp = NULL;
	uint32_t job_uid = NO_VAL;

	slurm_init_job_desc_msg (&job_msg);
	for (i = 0; i < argc; i++) {
		char *add_info = NULL;
		tag = argv[i];
		val = strchr(argv[i], '=');
		if (val) {
			taglen = val - argv[i];
			if ((taglen > 0) && ((val[-1] == '+') ||
					     (val[-1] == '-'))) {
				add_info = val - 1;
				taglen--;
			}
			val++;
			vallen = strlen(val);
		} else if (xstrncasecmp(tag, "Nice", MAX(strlen(tag), 2)) == 0){
			/* "Nice" is the only tag that might not have an
			   equal sign, so it is handled specially. */
			job_msg.nice = NICE_OFFSET + 100;
			update_cnt++;
			continue;
		} else if (!val && argv[i + 1]) {
			tag = argv[i];
			taglen = strlen(tag);
			val = argv[++i];
			vallen = strlen(val);
		} else {
			exit_code = 1;
			fprintf (stderr, "Invalid input: %s\n", argv[i]);
			fprintf (stderr, "Request aborted\n");
			return -1;
		}

		if (xstrncasecmp(tag, "JobId", MAX(taglen, 3)) == 0) {
			job_msg.job_id_str = val;
		}
		else if (xstrncasecmp(tag, "AdminComment",
				      MAX(taglen, 3)) == 0) {
			if (add_info) {
				if (add_info[0] == '-') {
					error("Invalid syntax, AdminComment can not be subtracted from.");
					exit_code = 1;
					return 0;
				}
				job_msg.admin_comment = add_info;
				/*
				 * Mark as unset so we know we handled this
				 * correctly as there is a check later to make
				 * sure we know we got a +-.
				 */
				add_info = NULL;
			} else
				job_msg.admin_comment = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ArrayTaskThrottle",
				      MAX(taglen, 10)) == 0) {
			int throttle;
			throttle = strtoll(val, (char **) NULL, 10);
			if (throttle < 0) {
				error("Invalid ArrayTaskThrottle value");
				exit_code = 1;
				return 0;
			}
			job_msg.array_inx = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Comment", MAX(taglen, 3)) == 0) {
			job_msg.comment = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Clusters", MAX(taglen, 8)) == 0) {
			job_msg.clusters = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ClusterFeatures",
				      MAX(taglen, 8)) == 0) {
			job_msg.cluster_features = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "DelayBoot", MAX(taglen, 5)) == 0) {
			int time_sec = time_str2secs(val);
			if (time_sec == NO_VAL) {
				error("Invalid DelayBoot value");
				exit_code = 1;
				return 0;
			}
			job_msg.delay_boot = time_sec;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "TimeLimit", MAX(taglen, 5)) == 0) {
			uint32_t job_current_time, time_limit;

			if (val && ((val[0] == '+') || (val[0] == '-'))) {
				if (add_info) {
					error("Invalid syntax, variations of +=- are not accepted.");
					exit_code = 1;
					return 0;
				}
				add_info = val;
				val++;
			}

			time_limit = time_str2mins(val);
			if (time_limit == NO_VAL) {
				error("Invalid TimeLimit value");
				exit_code = 1;
				return 0;
			}
			if (add_info) {
				if (!job_msg.job_id_str) {
					error("JobId must precede TimeLimit "
					      "increment or decrement");
					exit_code = 1;
					return 0;
				}

				job_current_time = _get_job_time(job_msg.
								 job_id_str);
				if (job_current_time == NO_VAL) {
					exit_code = 1;
					return 0;
				}
				if (add_info[0] == '+') {
					time_limit += job_current_time;
				} else if (time_limit > job_current_time) {
					error("TimeLimit decrement larger than"
					      " current time limit (%u > %u)",
					      time_limit, job_current_time);
					exit_code = 1;
					return 0;
				} else {
					time_limit = job_current_time -
						     time_limit;
				}
				/*
				 * Mark as unset so we know we handled this
				 * correctly as there is a check later to make
				 * sure we know we got a +-.
				 */
				add_info = NULL;
			}
			job_msg.time_limit = time_limit;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "TimeMin", MAX(taglen, 5)) == 0) {
			int time_min = time_str2mins(val);
			if ((time_min < 0) && (time_min != INFINITE)) {
				error("Invalid TimeMin value");
				exit_code = 1;
				return 0;
			}
			job_msg.time_min = time_min;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Priority", MAX(taglen, 2)) == 0) {
			if (parse_uint32(val, &job_msg.priority)) {
				error ("Invalid Priority value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Nice", MAX(taglen, 2)) == 0) {
			long long tmp_nice;
			tmp_nice = strtoll(val, (char **)NULL, 10);
			if (llabs(tmp_nice) > (NICE_OFFSET - 3)) {
				error("Nice value out of range (+/- %u). Value "
				      "ignored", NICE_OFFSET - 3);
				exit_code = 1;
				return 0;
			}
			job_msg.nice = NICE_OFFSET + tmp_nice;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "CPUsPerTask", MAX(taglen, 9))) {
			if (parse_uint16(val, &job_msg.cpus_per_task)) {
				error("Invalid CPUsPerTask value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "CpusPerTres", MAX(taglen, 9))) {
			job_msg.cpus_per_tres = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "NumCPUs", MAX(taglen, 6)) == 0) {
			int min_cpus, max_cpus=0;
			if (!get_resource_arg_range(val, "NumCPUs", &min_cpus,
						   &max_cpus, false) ||
			    (min_cpus <= 0) ||
			    (max_cpus && (max_cpus < min_cpus))) {
				error ("Invalid NumCPUs value: %s", val);
				exit_code = 1;
				return 0;
			}
			job_msg.min_cpus = min_cpus;
			if (max_cpus)
				job_msg.max_cpus = max_cpus;
			update_cnt++;
		}
		/* ReqProcs was removed in Slurm version 2.1 */
		else if ((xstrncasecmp(tag, "NumTasks", MAX(taglen, 8)) == 0) ||
			 (xstrncasecmp(tag, "ReqProcs", MAX(taglen, 8)) == 0)) {
			if (parse_uint32(val, &job_msg.num_tasks)) {
				error ("Invalid NumTasks value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Requeue", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.requeue)) {
				error ("Invalid Requeue value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		/* ReqNodes was replaced by NumNodes in Slurm version 2.1 */
		else if ((xstrncasecmp(tag, "ReqNodes", MAX(taglen, 8)) == 0) ||
		         (xstrncasecmp(tag, "NumNodes", MAX(taglen, 8)) == 0)) {
			int min_nodes, max_nodes, rc;
			if (xstrcmp(val, "0") == 0) {
				job_msg.min_nodes = 0;
			} else if (xstrcasecmp(val, "ALL") == 0) {
				job_msg.min_nodes = INFINITE;
			} else {
				min_nodes = (int) job_msg.min_nodes;
				max_nodes = (int) job_msg.max_nodes;
				rc = get_resource_arg_range(
						val, "requested node count",
						&min_nodes, &max_nodes, false);
				if (!rc)
					return rc;
				job_msg.min_nodes = (uint32_t) min_nodes;
				job_msg.max_nodes = (uint32_t) max_nodes;
			}
			update_size = true;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ReqSockets", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.sockets_per_node)) {
				error ("Invalid ReqSockets value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ReqCores", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.cores_per_socket)) {
				error ("Invalid ReqCores value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
                else if (xstrncasecmp(tag, "TasksPerNode", MAX(taglen, 2))==0) {
			if (parse_uint16(val, &job_msg.ntasks_per_node)) {
				error ("Invalid TasksPerNode value: %s", val);
				exit_code = 1;
				return 0;
			}
                        update_cnt++;
                }
		else if (xstrncasecmp(tag, "ReqThreads", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.threads_per_core)) {
				error ("Invalid ReqThreads value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "MinCPUsNode", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.pn_min_cpus)) {
				error ("Invalid MinCPUsNode value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "MinMemoryNode",
				     MAX(taglen, 10)) == 0) {
			if (parse_uint64(val, &job_msg.pn_min_memory)) {
				error ("Invalid MinMemoryNode value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "MinMemoryCPU",
				     MAX(taglen, 10)) == 0) {
			if (parse_uint64(val, &job_msg.pn_min_memory)) {
				error ("Invalid MinMemoryCPU value: %s", val);
				exit_code = 1;
				return 0;
			}
			job_msg.pn_min_memory |= MEM_PER_CPU;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "MinTmpDiskNode",
				     MAX(taglen, 5)) == 0) {
			if (parse_uint32(val, &job_msg.pn_min_tmp_disk)) {
				error ("Invalid MinTmpDiskNode value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Partition", MAX(taglen, 2)) == 0) {
			job_msg.partition = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "QOS", MAX(taglen, 2)) == 0) {
			job_msg.qos = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ReservationName",
				     MAX(taglen, 3)) == 0) {
			job_msg.reservation = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "Name", MAX(taglen, 2)) ||
			 !xstrncasecmp(tag, "JobName", MAX(taglen, 4))) {
			job_msg.name = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "WCKey", MAX(taglen, 1)) == 0) {
			job_msg.wckey = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "StdOut", MAX(taglen, 6)) == 0) {
			job_msg.std_out = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Switches", MAX(taglen, 5)) == 0) {
			char *sep_char;
			job_msg.req_switch =
				(uint32_t) strtol(val, &sep_char, 10);
			update_cnt++;
			if (sep_char && sep_char[0] == '@') {
				job_msg.wait4switch = time_str2mins(sep_char+1)
						      * 60;
			}
		}
		else if (xstrncasecmp(tag, "wait-for-switch", MAX(taglen, 5))
			 == 0) {
			if (parse_uint32(val, &job_msg.wait4switch)) {
				error ("Invalid wait-for-switch value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "OverSubscribe", MAX(taglen, 2)) ||
			 !xstrncasecmp(tag, "Shared", MAX(taglen, 2))) {
			if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				job_msg.shared = 1;
			else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				job_msg.shared = 0;
			else if (parse_uint16(val, &job_msg.shared)) {
				error("Invalid OverSubscribe value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Contiguous", MAX(taglen, 3)) == 0) {
			if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				job_msg.contiguous = 1;
			else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				job_msg.contiguous = 0;
			else if (parse_uint16(val, &job_msg.contiguous)) {
				error ("Invalid Contiguous value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "CoreSpec", MAX(taglen, 4)) == 0) {
			if (!xstrcmp(val, "-1") || !xstrcmp(val, "*"))
				job_msg.core_spec = INFINITE16;
			else if (parse_uint16(val, &job_msg.core_spec)) {
				error ("Invalid CoreSpec value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "MemPerTres", MAX(taglen, 5))) {
			job_msg.mem_per_tres = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ThreadSpec", MAX(taglen, 4)) == 0) {
			if (!xstrcmp(val, "-1") || !xstrcmp(val, "*"))
				job_msg.core_spec = INFINITE16;
			else if (parse_uint16(val, &job_msg.core_spec)) {
				error ("Invalid ThreadSpec value: %s", val);
				exit_code = 1;
				return 0;
			} else
				job_msg.core_spec |= CORE_SPEC_THREAD;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresBind", MAX(taglen, 5))) {
			job_msg.tres_bind = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresFreq", MAX(taglen, 5))) {
			job_msg.tres_freq = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresPerJob", MAX(taglen, 8))) {
			job_msg.tres_per_job = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresPerNode", MAX(taglen, 8))) {
			/* "gres" replaced by "tres_per_node" in v18.08 */
			if (job_msg.tres_per_node)
				xstrfmtcat(job_msg.tres_per_node, ",%s", val);
			else
				job_msg.tres_per_node = xstrdup(val);
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresPerSocket", MAX(taglen, 8))) {
			job_msg.tres_per_socket = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresPerTask", MAX(taglen, 8))) {
			job_msg.tres_per_task = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ExcNodeList", MAX(taglen, 3)) == 0){
			job_msg.exc_nodes = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "NodeList",    MAX(taglen, 8)) ||
			 !xstrncasecmp(tag, "ReqNodeList", MAX(taglen, 8))) {
			job_msg.req_nodes = val;
			update_size = true;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Features", MAX(taglen, 1)) == 0) {
			job_msg.features = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Gres", MAX(taglen, 2)) == 0) {
			/* "gres" replaced by "tres_per_node" in v18.08 */
			if (!xstrcasecmp(val, "help") ||
			    !xstrcasecmp(val, "list")) {
				print_gres_help();
			} else if (job_msg.tres_per_node) {
				xstrfmtcat(job_msg.tres_per_node, ",%s", val);
			} else {
				job_msg.tres_per_node = xstrdup(val);
				update_cnt++;
			}
		}
		else if (xstrncasecmp(tag, "Account", MAX(taglen, 1)) == 0) {
			job_msg.account = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "BurstBuffer", MAX(taglen, 1)) == 0) {
			job_msg.burst_buffer = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Dependency", MAX(taglen, 1)) == 0) {
			job_msg.dependency = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Licenses", MAX(taglen, 1)) == 0) {
			job_msg.licenses = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "EligibleTime", MAX(taglen, 2)) ||
			 !xstrncasecmp(tag, "StartTime",    MAX(taglen, 2))) {
			if ((job_msg.begin_time = parse_time(val, 0))) {
				if (job_msg.begin_time < time(NULL))
					job_msg.begin_time = time(NULL);
				update_cnt++;
			}
		}
		else if (!xstrncasecmp(tag, "EndTime", MAX(taglen, 2))) {
			job_msg.end_time = parse_time(val, 0);
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "Reboot", MAX(taglen, 3))) {
			if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				job_msg.reboot = 1;
			else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				job_msg.reboot = 0;
			else if (parse_uint16(val, &job_msg.reboot)) {
				error ("Invalid reboot value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "UserID", MAX(taglen, 3))) {
			uid_t user_id = 0;
			if (uid_from_string(val, &user_id) < 0) {
				exit_code = 1;
				fprintf (stderr, "Invalid UserID: %s\n", val);
				fprintf (stderr, "Request aborted\n");
				return 0;
			}
			job_uid = (uint32_t) user_id;
		}
		else if (!xstrncasecmp(tag, "Deadline", MAX(taglen, 3))) {
			if ((job_msg.deadline = parse_time(val, 0))) {
				update_cnt++;
			}
		}
		else {
			exit_code = 1;
			fprintf (stderr, "Update of this parameter is not "
				 "supported: %s\n", argv[i]);
			fprintf (stderr, "Request aborted\n");
			return 0;
		}

		if (add_info) {
			error("Option %s does not accept [+|-]= syntax", tag);
			exit_code = 1;
			return 0;
		}
	}

	if (update_cnt == 0) {
		exit_code = 1;
		fprintf (stderr, "No changes specified\n");
		return 0;
	}

	/* If specified, override uid with effective uid provided by
	 * -u <uid> or --uid=<uid> */
	if (euid != NO_VAL)
		job_msg.user_id = euid;

	if (!job_msg.job_id_str && job_msg.name) {
		/* Translate name to job ID string */
		job_msg.job_id_str = _job_name2id(job_msg.name, job_uid);
		if (!job_msg.job_id_str) {
			exit_code = 1;
			return 0;
		}
	}

	if (!job_msg.job_id_str) {
		error("No job ID specified");
		exit_code = 1;
		return 0;
	}

	if (update_size && !_is_single_job(job_msg.job_id_str)) {
		exit_code = 1;
		return 0;
	}

	if (_is_job_id(job_msg.job_id_str)) {
		job_msg.job_id_str = _next_job_id();
		while (job_msg.job_id_str) {
			rc2 = slurm_update_job2(&job_msg, &resp);
			if (update_size && (rc2 == SLURM_SUCCESS)) {
				/* See check above for one job ID */
				job_msg.job_id = slurm_atoul(job_msg.job_id_str);
				_update_job_size(job_msg.job_id);
			}
			if (rc2 != SLURM_SUCCESS) {
				rc2 = slurm_get_errno();
				rc = MAX(rc, rc2);
				exit_code = 1;
				if (quiet_flag != 1) {
					fprintf(stderr, "%s for job %s\n",
						slurm_strerror(slurm_get_errno()),
						job_msg.job_id_str);
				}
			} else if (resp) {
				for (i = 0; i < resp->job_array_count; i++) {
					if ((resp->error_code[i] == SLURM_SUCCESS)
					    && (resp->job_array_count == 1))
						continue;
					exit_code = 1;
					if (quiet_flag == 1)
						continue;
					fprintf(stderr, "%s: %s\n",
						resp->job_array_id[i],
						slurm_strerror(resp->
							       error_code[i]));
				}
				slurm_free_job_array_resp(resp);
				resp = NULL;
			}
			job_msg.job_id_str = _next_job_id();
		}
	} else if (job_msg.job_id_str) {
		exit_code = 1;
		rc = ESLURM_INVALID_JOB_ID;
		slurm_seterrno(rc);
		if (quiet_flag != 1) {
			fprintf(stderr, "%s for job %s\n",
				slurm_strerror(rc), job_msg.job_id_str);
		}
	}

	return rc;
}
Ejemplo n.º 10
0
/* Processes the current directive.
 * If the encoder returns an error, a message including current file and
 * line number together with the pt error string is printed on stderr.
 *
 * Returns 0 on success; a negative enum errcode otherwise.
 * Returns -err_internal if @p or @e is the NULL pointer.
 * Returns -err_parse_missing_directive if there was a pt directive marker,
 * but no directive.
 * Returns -stop_process if the .exp directive was encountered.
 * Returns -err_pt_lib if the pt encoder returned an error.
 * Returns -err_parse if a general parsing error was encountered.
 * Returns -err_parse_unknown_directive if there was an unknown pt directive.
 */
static int p_process(struct parser *p, struct pt_encoder *e)
{
	int bytes_written;
	int errcode;
	char *directive, *payload, *pt_label_name, *tmp;
	struct pt_directive *pd;
	struct pt_packet packet;

	if (bug_on(!p))
		return -err_internal;

	if (bug_on(!e))
		return -err_internal;

	pd = p->pd;
	if (!pd)
		return -err_internal;

	directive = pd->name;
	payload = pd->payload;

	pt_label_name = NULL;
	bytes_written = 0;
	errcode = 0;

	/* find a label name.  */
	tmp = strchr(directive, ':');
	if (tmp) {
		uint64_t x;

		pt_label_name = directive;
		directive = tmp+1;
		*tmp = '\0';

		/* ignore whitespace between label and directive. */
		while (isspace(*directive))
			directive += 1;

		/* if we can lookup a yasm label with the same name, the
		 * current pt directive label is invalid.  */
		errcode = yasm_lookup_label(p->y, &x, pt_label_name);
		if (errcode == 0)
			errcode = -err_label_not_unique;

		if (errcode != -err_no_label)
			return yasm_print_err(p->y, "label lookup",
					      errcode);

		/* if we can lookup a pt directive label with the same
		 * name, the current pt directive label is invalid.  */
		errcode = l_lookup(p->pt_labels, &x, pt_label_name);
		if (errcode == 0)
			errcode = -err_label_not_unique;

		if (errcode != -err_no_label)
			return yasm_print_err(p->y, "label lookup",
					      -err_label_not_unique);
	}

	/* now try to match the directive string and call the
	 * corresponding function that parses the payload and emits an
	 * according packet.
	 */
	if (strcmp(directive, "") == 0)
		return yasm_print_err(p->y, "invalid syntax",
				      -err_parse_missing_directive);
	else if (strcmp(directive, ".exp") == 0) {
		/* this is the end of processing pt directives, so we
		 * add a p_last label to the pt directive labels.
		 */
		errcode = l_append(p->pt_labels, "eos", p->pt_bytes_written);
		if (errcode < 0)
			return yasm_print_err(p->y, "append label", errcode);

		return -stop_process;
	}

	if (strcmp(directive, "psb") == 0) {
		errcode = parse_empty(payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "psb: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_psb;
	} else if (strcmp(directive, "psbend") == 0) {
		errcode = parse_empty(payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "psbend: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_psbend;
	} else if (strcmp(directive, "pad") == 0) {
		errcode = parse_empty(payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "pad: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_pad;
	} else if (strcmp(directive, "ovf") == 0) {
		errcode = parse_empty(payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "ovf: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_ovf;
	} else if (strcmp(directive, "tnt") == 0) {
		errcode = parse_tnt(&packet.payload.tnt.payload,
				    &packet.payload.tnt.bit_size, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tnt: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_tnt_8;
	} else if (strcmp(directive, "tnt64") == 0) {
		errcode = parse_tnt(&packet.payload.tnt.payload,
				    &packet.payload.tnt.bit_size, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tnt64: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_tnt_64;
	} else if (strcmp(directive, "tip") == 0) {
		errcode = parse_ip(p, &packet.payload.ip.ip,
				   &packet.payload.ip.ipc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tip: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_tip;
	} else if (strcmp(directive, "tip.pge") == 0) {
		errcode = parse_ip(p, &packet.payload.ip.ip,
				   &packet.payload.ip.ipc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tip.pge: parsing failed",
				       errcode);
			goto error;
		}
		packet.type = ppt_tip_pge;
	} else if (strcmp(directive, "tip.pgd") == 0) {
		errcode = parse_ip(p, &packet.payload.ip.ip,
				   &packet.payload.ip.ipc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tip.pgd: parsing failed",
				       errcode);
			goto error;
		}
		packet.type = ppt_tip_pgd;
	} else if (strcmp(directive, "fup") == 0) {
		errcode = parse_ip(p, &packet.payload.ip.ip,
				   &packet.payload.ip.ipc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "fup: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_fup;
	} else if (strcmp(directive, "mode.exec") == 0) {
		if (strcmp(payload, "16bit") == 0) {
			packet.payload.mode.bits.exec.csl = 0;
			packet.payload.mode.bits.exec.csd = 0;
		} else if (strcmp(payload, "64bit") == 0) {
			packet.payload.mode.bits.exec.csl = 1;
			packet.payload.mode.bits.exec.csd = 0;
		} else if (strcmp(payload, "32bit") == 0) {
			packet.payload.mode.bits.exec.csl = 0;
			packet.payload.mode.bits.exec.csd = 1;
		} else {
			errcode = yasm_print_err(p->y,
						 "mode.exec: argument must be one of \"16bit\", \"64bit\" or \"32bit\"",
						 -err_parse);
			goto error;
		}
		packet.payload.mode.leaf = pt_mol_exec;
		packet.type = ppt_mode;
	} else if (strcmp(directive, "mode.tsx") == 0) {
		if (strcmp(payload, "begin") == 0) {
			packet.payload.mode.bits.tsx.intx = 1;
			packet.payload.mode.bits.tsx.abrt = 0;
		} else if (strcmp(payload, "abort") == 0) {
			packet.payload.mode.bits.tsx.intx = 0;
			packet.payload.mode.bits.tsx.abrt = 1;
		} else if (strcmp(payload, "commit") == 0) {
			packet.payload.mode.bits.tsx.intx = 0;
			packet.payload.mode.bits.tsx.abrt = 0;
		} else {
			errcode = yasm_print_err(p->y,
						 "mode.tsx: argument must be one of \"begin\", \"abort\" or \"commit\"",
						 -err_parse);
			goto error;
		}
		packet.payload.mode.leaf = pt_mol_tsx;
		packet.type = ppt_mode;
	} else if (strcmp(directive, "pip") == 0) {
		errcode = parse_uint64(&packet.payload.pip.cr3, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "pip: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_pip;
	} else if (strcmp(directive, "tsc") == 0) {
		errcode = parse_uint64(&packet.payload.tsc.tsc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tsc: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_tsc;
	} else if (strcmp(directive, "cbr") == 0) {
		errcode = parse_uint8(&packet.payload.cbr.ratio, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "cbr: parsing cbr failed",
				       errcode);
			goto error;
		}
		packet.type = ppt_cbr;
	} else {
		errcode = yasm_print_err(p->y, "invalid syntax",
					 -err_parse_unknown_directive);
		goto error;
	}

	bytes_written = pt_enc_next(e, &packet);
	if (bytes_written < 0) {
		const char *errstr, *format;
		char *msg;
		size_t n;

		errstr = pt_errstr(pt_errcode(bytes_written));
		format = "encoder error in directive %s (status %s)";
		/* the length of format includes the "%s" (-2)
		 * characters, we add errstr (+-0) and then we need
		 * space for a terminating null-byte (+1).
		 */
		n = strlen(format)-4 + strlen(directive) + strlen(errstr) + 1;

		msg = malloc(n);
		if (!msg)
			errcode = yasm_print_err(p->y,
				       "encoder error not enough memory to show error code",
				       -err_pt_lib);
		else {
			sprintf(msg, format, directive, errstr);
			errcode = yasm_print_err(p->y, msg, -err_pt_lib);
			free(msg);
		}
	} else {
		if (pt_label_name) {
			errcode = l_append(p->pt_labels, pt_label_name,
					   p->pt_bytes_written);
			if (errcode < 0)
				goto error;
		}
		p->pt_bytes_written += bytes_written;
	}

error:
	if (errcode < 0)
		bytes_written = errcode;
	return bytes_written;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
int options_parse(int argc, const char** argv, options_t* options)
{
  uint64_t val;
  int i;

  /* Initialize options to default values. */
  options->number_messages_per_receive = DEFAULT_MESSAGES_PER_RECEIVE;
  options->nthreads = DEFAULT_THREADS;

#ifdef SO_REUSEPORT
  options->single_receiver_socket = SINGLE_RECEIVER_SOCKET;
#else
  options->single_receiver_socket = 1;
#endif

  options->nprocessors = 0;

  /* Last parameter is not an option. */
  argc--;

  i = 1;
  while (i < argc) {
    if (strcasecmp(argv[i], "--messages-per-receive") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        return -1;
      }

      if (parse_uint64(argv[i + 1],
                       MIN_MESSAGES_PER_RECEIVE,
                       MAX_MESSAGES_PER_RECEIVE,
                       &val) < 0) {
        return -1;
      }

      options->number_messages_per_receive = (unsigned) val;

      i += 2;
    } else if (strcasecmp(argv[i], "--threads") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        return -1;
      }

      if (parse_uint64(argv[i + 1], MIN_THREADS, MAX_THREADS, &val) < 0) {
        return -1;
      }

      options->nthreads = (unsigned) val;

      i += 2;
#ifdef SO_REUSEPORT
    } else if (strcasecmp(argv[i], "--single-receiver-socket") == 0) {
      options->single_receiver_socket = 1;

      i++;
    } else if (strcasecmp(argv[i], "--one-receiver-socket-per-thread") == 0) {
      options->single_receiver_socket = 0;

      i++;
#endif /* SO_REUSEPORT */
    } else if (strcasecmp(argv[i], "--processors") == 0) {
      /* Last parameter? */
      if (i + 1 == argc) {
        return -1;
      }

      if (parse_processors(argv[i + 1],
                           options->processors,
                           &options->nprocessors) < 0) {
        return -1;
      }

      i += 2;
    } else {
      return -1;
    }
  }

  return 0;
}
Ejemplo n.º 13
0
/* parses a 4-touple of the form {x, y, z, w}
 * where x, y, z, w are numbers */
static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
                                    union tgsi_immediate_data *values)
{
   unsigned i;
   int ret;

   eat_opt_white( &ctx->cur );
   if (*ctx->cur != '{') {
      report_error( ctx, "Expected `{'" );
      return FALSE;
   }
   ctx->cur++;
   for (i = 0; i < 4; i++) {
      eat_opt_white( &ctx->cur );
      if (i > 0) {
         if (*ctx->cur != ',') {
            report_error( ctx, "Expected `,'" );
            return FALSE;
         }
         ctx->cur++;
         eat_opt_white( &ctx->cur );
      }

      switch (type) {
      case TGSI_IMM_FLOAT64:
         ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
         i++;
         break;
      case TGSI_IMM_INT64:
         ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
         i++;
         break;
      case TGSI_IMM_UINT64:
         ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
         i++;
         break;
      case TGSI_IMM_FLOAT32:
         ret = parse_float(&ctx->cur, &values[i].Float);
         break;
      case TGSI_IMM_UINT32:
         ret = parse_uint(&ctx->cur, &values[i].Uint);
         break;
      case TGSI_IMM_INT32:
         ret = parse_int(&ctx->cur, &values[i].Int);
         break;
      default:
         assert(0);
         ret = FALSE;
         break;
      }

      if (!ret) {
         report_error( ctx, "Expected immediate constant" );
         return FALSE;
      }
   }
   eat_opt_white( &ctx->cur );
   if (*ctx->cur != '}') {
      report_error( ctx, "Expected `}'" );
      return FALSE;
   }
   ctx->cur++;

   return TRUE;
}
Ejemplo n.º 14
0
static int key_value_parse_line_with_key(struct key_value_specification *k, char *line, void *base_address[])
{
	char *valuestr;
	int rc, len, klen;

	klen = strlen(k->key);
	len = strlen(line);
	if (len < klen + 1)
		return 1;
	if (strncmp(line, k->key, klen) != 0)
		return 1;
	if (line[klen] != ':')
		return 1;

	/* Skip leading spaces */
	klen = klen + 1;
	while (line[klen] == ' ')
		klen++;
	/* At this point, we have a match on the key */
	valuestr = &line[klen];
	switch (k->type) {
	case KVS_STRING:
		rc = parse_string(valuestr, k, base_address);
		break;
	case KVS_INT64:
		rc = parse_int64(valuestr, k, base_address);
		break;
	case KVS_INT32:
		rc = parse_int32(valuestr, k, base_address);
		break;
	case KVS_INT16:
		rc = parse_int16(valuestr, k, base_address);
		break;
	case KVS_INT8:
		rc = parse_int8(valuestr, k, base_address);
		break;
	case KVS_UINT64:
		rc = parse_uint64(valuestr, k, base_address);
		break;
	case KVS_UINT32:
		rc = parse_uint32(valuestr, k, base_address);
		break;
	case KVS_UINT16:
		rc = parse_uint16(valuestr, k, base_address);
		break;
	case KVS_UINT8:
		rc = parse_uint8(valuestr, k, base_address);
		break;
	case KVS_DOUBLE:
		rc = parse_double(valuestr, k, base_address);
		break;
	case KVS_FLOAT:
		rc = parse_float(valuestr, k, base_address);
		break;
	default:
		fprintf(stderr, "%s:%d: unknown key type '%c' for key '%s'\n",
			__func__, __LINE__, k->type, k->key);
		rc = -1;
		break;
	}
	return rc;
}
Ejemplo n.º 15
0
G_GNUC_COLD void
upload_stats_load_history(void)
{
	FILE *upload_stats_file;
	file_path_t fp;
	char line[FILENAME_MAX + 64];
	guint lineno = 0;

	gcu_upload_stats_gui_freeze();
	
	file_path_set(&fp, settings_config_dir(), ul_stats_file);

	/* open file for reading */
	upload_stats_file = file_config_open_read(ul_stats_what, &fp, 1);
	if (upload_stats_file == NULL)
		goto done;

	/* parse, insert names into ul_stats_clist */
	while (fgets(line, sizeof(line), upload_stats_file)) {
		static const struct ul_stats zero_item;
		struct ul_stats item;
		struct sha1 sha1_buf;
		const char *p;
		size_t i;

		lineno++;
		if (line[0] == '#' || line[0] == '\n')
			continue;

		p = strchr(line, '\t');
		if (NULL == p)
			goto corrupted;

		line[p - line] = '\0';		/* line is now the URL-escaped file name */
		p++;

		/* URL-unescape in-place */
		if (!url_unescape(line, TRUE))
			goto corrupted;

		item = zero_item;
		item.pathname = line;

		for (i = 0; i < 8; i++) {
			guint64 v;
			int error;
			const char *endptr;

			p = skip_ascii_spaces(p);

			/* SVN versions up to 15322 had only 6 fields in the history */
			if (5 == i && '\0' == *p)
				break;

			switch (i) {
			case 7:
				/* We have a SHA1 or '*' if none known */
				if ('*' != *p) {
					size_t len = clamp_strlen(p, SHA1_BASE32_SIZE);
					
					error = !parse_base32_sha1(p, len, &sha1_buf);
					item.sha1 = error ? NULL : &sha1_buf;
				} else {
					error = FALSE;
				}
				p = skip_ascii_non_spaces(p);
				v = 0;
				break;
			default:
				v = parse_uint64(p, &endptr, 10, &error);
				p = deconstify_gchar(endptr);
			}

			if (error || !is_ascii_space(*endptr))
				goto corrupted;

			switch (i) {
			case 0: item.size = v; break;
			case 1: item.attempts = v; break;
			case 2: item.complete = v; break;
			case 3: item.bytes_sent |= ((guint64) (guint32) v) << 32; break;
			case 4: item.bytes_sent |= (guint32) v; break;
			case 5: item.rtime = MIN(v + (time_t) 0, TIME_T_MAX + (guint64) 0);
			case 6: item.dtime = MIN(v + (time_t) 0, TIME_T_MAX + (guint64) 0); 
			case 7: break;	/* Already stored above */
			default:
				g_assert_not_reached();
				goto corrupted;
			}
		}

		/* 
		 * We store the filenames UTF-8 encoded but the file might have been
		 * edited or corrupted.
		 */
		if (is_absolute_path(item.pathname)) {
			item.filename = lazy_filename_to_utf8_normalized(
						filepath_basename(item.pathname), UNI_NORM_NFC);
		} else {
			item.filename = lazy_unknown_to_utf8_normalized(
						filepath_basename(item.pathname), UNI_NORM_NFC, NULL);
		}

		if (upload_stats_find(NULL, item.pathname, item.size)) {
			g_warning("upload_stats_load_history():"
				" Ignoring line %u due to duplicate file.", lineno);
		} else if (upload_stats_find(item.sha1, item.pathname, item.size)) {
			g_warning("upload_stats_load_history():"
				" Ignoring line %u due to duplicate file.", lineno);
		} else {
			upload_stats_add(item.pathname, item.size, item.filename,
				item.attempts, item.complete, item.bytes_sent,
				item.rtime, item.dtime, item.sha1);
		}
		continue;

	corrupted:
		g_warning("upload statistics file corrupted at line %u.", lineno);
	}

	/* close file */
	fclose(upload_stats_file);

done:
	gcu_upload_stats_gui_thaw();
	return;
}
Ejemplo n.º 16
0
/**
 * This function is used to read the disk cache into memory.
 *
 * It must be passed one line from the cache (ending with '\n'). It
 * performs all the syntactic processing to extract the fields from
 * the line and calls add_volatile_cache_entry() to append the record
 * to the in-memory cache.
 */
static G_GNUC_COLD void
parse_and_append_cache_entry(char *line)
{
	const char *p, *end; /* pointers to scan the line */
	int c, error;
	filesize_t size;
	time_t mtime;
	struct sha1 sha1;
	struct tth tth;
	bool has_tth;

	/* Skip comments and blank lines */
	if (file_line_is_skipable(line))
		return;

	/* Scan until file size */

	p = line;
	while ((c = *p) != '\0' && c != '\t') {
		p++;
	}

	if (urn_get_bitprint(line, p - line, &sha1, &tth)) {
		has_tth = TRUE;
	} else if (urn_get_sha1(line, &sha1)) {
		has_tth = FALSE;
	} else {
		const char *sha1_digest_ascii;

		has_tth = FALSE;
		sha1_digest_ascii = line; /* SHA1 digest is the first field. */

		if (
			*p != '\t' ||
			(p - sha1_digest_ascii) != SHA1_BASE32_SIZE ||
			SHA1_RAW_SIZE != base32_decode(sha1.data, sizeof sha1.data,
								sha1_digest_ascii, SHA1_BASE32_SIZE)
		) {
			goto failure;
		}
	}
	p++; /* Skip \t */

	/* p is now supposed to point to the beginning of the file size */

	size = parse_uint64(p, &end, 10, &error);
	if (error || *end != '\t') {
		goto failure;
	}

	p = ++end;

	/*
	 * p is now supposed to point to the beginning of the file last
	 * modification time.
	 */

	mtime = parse_uint64(p, &end, 10, &error);
	if (error || *end != '\t') {
		goto failure;
	}

	p = ++end;

	/* p is now supposed to point to the file name */

	if (strchr(p, '\t') != NULL)
		goto failure;

	add_volatile_cache_entry(p, size, mtime,
		&sha1, has_tth ? &tth : NULL, FALSE);
	return;

failure:
	g_warning("malformed line in SHA1 cache file: %s", line);
}
Ejemplo n.º 17
0
static void integer_number(void)
{
	uint64_t number = parse_uint64(parser.previous.start, parser.previous.length);
	emit_constant(INT_VAL((int64_t)number));
}
Ejemplo n.º 18
0
template_t *
template_load(const char *filename)
{
  struct template_chunk *chunk;
  FILE *f;
  char *buf = NULL, *q;
  size_t buf_len, line;
  template_t *tpl = NULL;
  int c;
  char entity[128], *e = NULL;

  RUNTIME_ASSERT(filename != NULL);
  f = safer_fopen(filename, SAFER_FOPEN_RD);
  if (!f) {
    WARN("could not open \"%s\": %s", filename, compat_strerror(errno));
    goto failure;
  }

  tpl = calloc(1, sizeof *tpl);
  if (!tpl) {
    CRIT("Out of memory");
    goto failure;
  }
  tpl->chunks = NULL;
  
  buf_len = 4096;
  buf = calloc(1, buf_len);
  if (!buf) {
    CRIT("Out of memory");
    goto failure;
  }
  
  for (line = 1; /* NOTHING */; line++) {
    char *p;
    
    p = fgets(buf, buf_len, f);
    if (!p) {
      if (!ferror(f))
        break;

      CRIT("fgets() failed: %s", compat_strerror(errno));
      goto failure;
    }

    q = strchr(buf, '\n');
    if (!q) {
      CRIT("Line too long or unterminated: \"%s\"", buf);
      goto failure;
    }
    while (isspace((unsigned char) *q)) {
      *q = '\0';
      if (q == buf)
        break;
      q--;
    }
    
    if (q == buf && *q == '\0')
      break;

    if (line == 1 && 0 == strncmp(buf, "HTTP/", sizeof "HTTP/" - 1)) {
      uint64_t code;
      char *endptr;
      int error;
      struct http_response hres;
      size_t size;
      snode_t *sn;

      p = strchr(buf, ' ');
      if (!p) {
        WARN("Invalid HTTP response: \"%s\"", buf);
        goto failure;
      }
      
      p = skip_spaces(p);
      code = parse_uint64(p, &endptr, 10, &error);
      if (code < 100 || code > 999) {
        WARN("Invalid HTTP result code: \"%s\"", buf);
        goto failure;
      }
      p = skip_spaces(endptr);

      hres.code = code;
      size = sizeof hres.msg;
      append_string(hres.msg, &size, p);
      RUNTIME_ASSERT(hres.msg == (char *) &hres);
      chunk = template_raw_chunk_new(chunk_http_response,
                (char *) &hres, sizeof hres);

      if (NULL == (sn = snode_new(chunk))) {
        CRIT("snode_new() failed");
        goto failure;
      }
      tpl->chunks = snode_prepend(tpl->chunks, sn);
    } else {
      size_t len;
      snode_t *sn;

      if (!isalpha((unsigned char) buf[0]) || NULL == strchr(buf, ':')) {
        WARN("Invalid HTTP header: \"%s\"", buf);
        goto failure;
      }

      for (p = buf; (c = (unsigned char) *p) != ':'; ++p)
        if (!isalpha(c) && c != '-') {
          WARN("Invalid character HTTP in header name: \"%s\"", buf);
          goto failure;
        }
      
      len = strlen(buf) + 1;
      chunk = template_raw_chunk_new(chunk_http_header, buf, len);
      if (NULL == (sn = snode_new(chunk))) {
        CRIT("snode_new() failed");
        goto failure;
      }
      tpl->chunks = snode_prepend(tpl->chunks, sn);
    }
  }

  if (feof(f)) {
    tpl->chunks = snode_reverse(tpl->chunks);
    return tpl;
  }
  
  q = buf;
  e = NULL;
  
  for (;;) {
    c = fgetc(f);
    if (c == EOF) {
      if (!ferror(f))
        break;
      
      CRIT("fgetc() failed: %s", compat_strerror(errno));
      goto failure;
    }
    
    if ((size_t) (q - buf) >= buf_len) {
      char *n;
      
      buf_len += 4096;
      n = realloc(buf, buf_len);
      if (!n) {
        CRIT("Out of memory");
        goto failure;
      }
      q = &n[q - buf];
      buf = n;
    }
    *q++ = c;

    if (c == ';' && e != NULL) {
      RUNTIME_ASSERT(e >= entity && e < &entity[sizeof entity]);
      *e = '\0';
      
      chunk = template_chunk_new(entity);
      if (chunk) {
        struct template_chunk *data;
        size_t data_len;
        snode_t *sn;
     
        data_len = (q - buf) - strlen(entity) - 2;
        RUNTIME_ASSERT(data_len <= INT_MAX);
        if (data_len > 0) {
          data = template_raw_chunk_new(chunk_data, buf, data_len);
          if (NULL == (sn = snode_new(data))) {
            CRIT("snode_new() failed");
            goto failure;
          }
          tpl->chunks = snode_prepend(tpl->chunks, sn);
      
          buf_len = 4096;
          buf = calloc(1, buf_len);
          if (!buf) {
            CRIT("Out of memory");
            goto failure;
          }
        }
        q = buf;
    
        if (NULL == (sn = snode_new(chunk))) {
          CRIT("snode_new() failed");
          goto failure;
        }
        tpl->chunks = snode_prepend(tpl->chunks, sn);
      }

      e = NULL;
    }
    
    if (e) {
      bool b = isalnum(c) || c == '.' || c == '_';
      
      if (b && e < &entity[sizeof entity - 1]) {
        *e++ = c;
      } else {
        e = NULL;
      }
    }
    
    if (c == '&') {
      e = entity;
    }
  }
  fclose(f);
  f = NULL;

  if (q != buf) {
    snode_t *sn;

    chunk = template_raw_chunk_new(chunk_data, buf, q - buf);
    if (NULL == (sn = snode_new(chunk))) {
      CRIT("snode_new() failed");
      goto failure;
    }
    tpl->chunks = snode_prepend(tpl->chunks, sn);
  }
  DO_FREE(buf);
 
  tpl->chunks = snode_reverse(tpl->chunks);
  
#if 0
  {
    size_t n = 0;
    
    snode_t *sn = tpl->chunks;
    while (sn) {
      struct gwc_data_chunk *data = sn->ptr;
      DBUG("data->type=%d; data->buf=%p; data->size=%d",
          (int) data->type, data->buf, (int) data->size);
      sn = sn->next;
      n += data->size;
    }
    
    DBUG("n=%d", (int) n);
  }
#endif
  
  return tpl;

failure:

  CRIT("Loading data template from \"%s\" failed.", filename);

  if (f) {
    fclose(f);
    f = NULL;
  }
  DO_FREE(buf);
  if (tpl) {
    while (tpl->chunks != NULL) {
      snode_t *sn = tpl->chunks->next;
    
      DO_FREE(tpl->chunks);
      tpl->chunks = sn;
    }
    DO_FREE(tpl);
  }
  return NULL;
}
Ejemplo n.º 19
0
/* reads, corrects and parses the verity table, validates parameters, and if
   `f->flags' does not have `FEC_VERITY_DISABLE' set, calls `verify_tree' to
   load and validate the hash tree */
static int parse_table(fec_handle *f, uint64_t offset, uint32_t size, bool useecc)
{
    check(f);
    check(size >= VERITY_MIN_TABLE_SIZE);
    check(size <= VERITY_MAX_TABLE_SIZE);

    debug("offset = %" PRIu64 ", size = %u", offset, size);

    verity_info *v = &f->verity;
    std::unique_ptr<char[]> table(new (std::nothrow) char[size + 1]);

    if (!table) {
        errno = ENOMEM;
        return -1;
    }

    if (!useecc) {
        if (!raw_pread(f, table.get(), size, offset)) {
            error("failed to read verity table: %s", strerror(errno));
            return -1;
        }
    } else if (fec_pread(f, table.get(), size, offset) != (ssize_t)size) {
        error("failed to ecc read verity table: %s", strerror(errno));
        return -1;
    }

    table[size] = '\0';
    debug("verity table: '%s'", table.get());

    int i = 0;
    std::unique_ptr<uint8_t[]> salt;
    uint8_t root[SHA256_DIGEST_LENGTH];

    auto tokens = android::base::Split(table.get(), " ");

    for (const auto& token : tokens) {
        switch (i++) {
        case 0: /* version */
            if (token != stringify(VERITY_TABLE_VERSION)) {
                error("unsupported verity table version: %s", token.c_str());
                return -1;
            }
            break;
        case 3: /* data_block_size */
        case 4: /* hash_block_size */
            /* assume 4 KiB block sizes for everything */
            if (token != stringify(FEC_BLOCKSIZE)) {
                error("unsupported verity block size: %s", token.c_str());
                return -1;
            }
            break;
        case 5: /* num_data_blocks */
            if (parse_uint64(token.c_str(), f->data_size / FEC_BLOCKSIZE,
                    &v->data_blocks) == -1) {
                error("invalid number of verity data blocks: %s",
                    token.c_str());
                return -1;
            }
            break;
        case 6: /* hash_start_block */
            if (parse_uint64(token.c_str(), f->data_size / FEC_BLOCKSIZE,
                    &v->hash_start) == -1) {
                error("invalid verity hash start block: %s", token.c_str());
                return -1;
            }

            v->hash_start *= FEC_BLOCKSIZE;
            break;
        case 7: /* algorithm */
            if (token != "sha256") {
                error("unsupported verity hash algorithm: %s", token.c_str());
                return -1;
            }
            break;
        case 8: /* digest */
            if (parse_hex(root, sizeof(root), token.c_str()) == -1) {
                error("invalid verity root hash: %s", token.c_str());
                return -1;
            }
            break;
        case 9: /* salt */
            v->salt_size = token.size();
            check(v->salt_size % 2 == 0);
            v->salt_size /= 2;

            salt.reset(new (std::nothrow) uint8_t[v->salt_size]);

            if (!salt) {
                errno = ENOMEM;
                return -1;
            }

            if (parse_hex(salt.get(), v->salt_size, token.c_str()) == -1) {
                error("invalid verity salt: %s", token.c_str());
                return -1;
            }
            break;
        default:
            break;
        }
    }

    if (i < VERITY_TABLE_ARGS) {
        error("not enough arguments in verity table: %d; expected at least "
            stringify(VERITY_TABLE_ARGS), i);
        return -1;
    }

    check(v->hash_start < f->data_size);

    if (v->metadata_start < v->hash_start) {
        check(v->data_blocks == v->metadata_start / FEC_BLOCKSIZE);
    } else {
        check(v->data_blocks == v->hash_start / FEC_BLOCKSIZE);
    }

    if (v->salt) {
        delete[] v->salt;
        v->salt = NULL;
    }

    v->salt = salt.release();

    if (v->table) {
        delete[] v->table;
        v->table = NULL;
    }

    v->table = table.release();

    if (!(f->flags & FEC_VERITY_DISABLE)) {
        if (verify_tree(f, root) == -1) {
            return -1;
        }

        check(v->hash);

        uint8_t zero_block[FEC_BLOCKSIZE];
        memset(zero_block, 0, FEC_BLOCKSIZE);

        if (verity_hash(f, zero_block, v->zero_hash) == -1) {
            error("failed to hash");
            return -1;
        }
    }

    return 0;
}
Ejemplo n.º 20
0
extern int
scontrol_parse_part_options (int argc, char **argv, int *update_cnt_ptr,
			     update_part_msg_t *part_msg_ptr)
{
	int i, min, max;
	char *tag, *val;
	int taglen, vallen;

	if (!update_cnt_ptr) {
		error("scontrol_parse_part_options internal error, "
		      "update_cnt_ptr == NULL");
		exit_code = 1;
		return -1;
	}
	if (!part_msg_ptr) {
		error("scontrol_parse_part_options internal error, "
		      "part_msg_ptr == NULL");
		exit_code = 1;
		return -1;
	}

	for (i=0; i<argc; i++) {
		tag = argv[i];
		val = strchr(argv[i], '=');
		if (val) {
			taglen = val - argv[i];
			val++;
			vallen = strlen(val);
		} else {
			exit_code = 1;
			error("Invalid input: %s  Request aborted", argv[i]);
			return -1;
		}

		if (strncasecmp(tag, "PartitionName", MAX(taglen, 2)) == 0) {
			part_msg_ptr->name = val;
			(*update_cnt_ptr)++;
		} else if (strncasecmp(tag, "MaxTime", MAX(taglen, 4)) == 0) {
			int max_time = time_str2mins(val);
			if ((max_time < 0) && (max_time != INFINITE)) {
				exit_code = 1;
				error("Invalid input %s", argv[i]);
				return -1;
			}
			part_msg_ptr->max_time = max_time;
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "DefaultTime", MAX(taglen, 8)) == 0){
			int default_time = time_str2mins(val);
			if ((default_time < 0) && (default_time != INFINITE)) {
				exit_code = 1;
				error("Invalid input %s", argv[i]);
				return -1;
			}
			part_msg_ptr->default_time = default_time;
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "MaxCPUsPerNode", MAX(taglen, 4))
			  == 0) {
			if ((xstrcasecmp(val,"UNLIMITED") == 0) ||
			    (xstrcasecmp(val,"INFINITE") == 0)) {
				part_msg_ptr->max_cpus_per_node =
					(uint32_t) INFINITE;
			} else if (parse_uint32(val, &part_msg_ptr->
						      max_cpus_per_node)) {
				error("Invalid MaxCPUsPerNode value: %s", val);
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "MaxNodes", MAX(taglen, 4)) == 0) {
			if ((xstrcasecmp(val,"UNLIMITED") == 0) ||
			    (xstrcasecmp(val,"INFINITE") == 0))
				part_msg_ptr->max_nodes = (uint32_t) INFINITE;
			else {
				min = 1;
				get_resource_arg_range(val,
					"MaxNodes", &min, &max, true);
				part_msg_ptr->max_nodes = min;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "MinNodes", MAX(taglen, 2)) == 0) {
			min = 1;
			verify_node_count(val, &min, &max);
			part_msg_ptr->min_nodes = min;
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "Default", MAX(taglen, 7)) == 0) {
			if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_DEFAULT_CLR;
			else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_DEFAULT;
			else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable Default values "
					"are YES and NO");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "DisableRootJobs", MAX(taglen, 1))) {
			if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_NO_ROOT_CLR;
			else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_NO_ROOT;
			else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable DisableRootJobs values "
					"are YES and NO");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "ExclusiveUser", MAX(taglen, 1))) {
			if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_EXC_USER_CLR;
			else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_EXCLUSIVE_USER;
			else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable ExclusiveUser values "
					"are YES and NO");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "Hidden", MAX(taglen, 1)) == 0) {
			if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_HIDDEN_CLR;
			else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_HIDDEN;
			else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable Hidden values "
					"are YES and NO");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "LLN", MAX(taglen, 1)) == 0) {
			if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_LLN_CLR;
			else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_LLN;
			else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable LLN values "
					"are YES and NO");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "RootOnly", MAX(taglen, 3)) == 0) {
			if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_ROOT_ONLY_CLR;
			else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_ROOT_ONLY;
			else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable RootOnly values "
					"are YES and NO");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "ReqResv", MAX(taglen, 3)) == 0) {
			if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_REQ_RESV_CLR;
			else if (strncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				part_msg_ptr->flags |= PART_FLAG_REQ_RESV;
			else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable ReqResv values "
					"are YES and NO");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "OverSubscribe", MAX(taglen, 5)) ||
			 !strncasecmp(tag, "Shared", MAX(taglen, 2))) {
			char *colon_pos = strchr(val, ':');
			if (colon_pos) {
				*colon_pos = '\0';
				vallen = strlen(val);
			}
			if (strncasecmp(val, "NO", MAX(vallen, 1)) == 0) {
				part_msg_ptr->max_share = 1;

			} else if (strncasecmp(val, "EXCLUSIVE",
				   MAX(vallen, 1)) == 0) {
				part_msg_ptr->max_share = 0;

			} else if (strncasecmp(val, "YES", MAX(vallen, 1))
				   == 0) {
				if (colon_pos) {
					part_msg_ptr->max_share =
						(uint16_t) strtol(colon_pos+1,
							(char **) NULL, 10);
				} else {
					part_msg_ptr->max_share = (uint16_t) 4;
				}
			} else if (strncasecmp(val, "FORCE", MAX(vallen, 1))
				   == 0) {
				if (colon_pos) {
					part_msg_ptr->max_share =
						(uint16_t) strtol(colon_pos+1,
							(char **) NULL, 10) |
							SHARED_FORCE;
				} else {
					part_msg_ptr->max_share =
						(uint16_t) 4 |SHARED_FORCE;
				}
			} else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable OverSubscribe values are "
					"NO, EXCLUSIVE, YES:#, and FORCE:#");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "OverTimeLimit", MAX(taglen, 5))
			  == 0) {
			if ((xstrcasecmp(val,"UNLIMITED") == 0) ||
			    (xstrcasecmp(val,"INFINITE") == 0)) {
				part_msg_ptr->over_time_limit =
					(uint16_t) INFINITE;
			} else if (parse_uint16(val, &part_msg_ptr->
						      over_time_limit)) {
				error("Invalid OverTimeLimit value: %s", val);
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "PreemptMode", MAX(taglen, 3)) == 0) {
			uint16_t new_mode = preempt_mode_num(val);
			if (new_mode != (uint16_t) NO_VAL)
				part_msg_ptr->preempt_mode = new_mode;
			else {
				error("Invalid input: %s", argv[i]);
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "Priority", MAX(taglen, 3))) {
			if (parse_uint16(val, &part_msg_ptr->priority_tier)) {
				error("Invalid Priority value: %s", val);
				return -1;
			}
			part_msg_ptr->priority_job_factor =
				part_msg_ptr->priority_tier;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag,"PriorityJobFactor",MAX(taglen, 3))) {
			if (parse_uint16(val,
					 &part_msg_ptr->priority_job_factor)) {
				error("Invalid PriorityJobFactor value: %s",
				      val);
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "PriorityTier", MAX(taglen, 3))) {
			if (parse_uint16(val, &part_msg_ptr->priority_tier)) {
				error("Invalid PriorityTier value: %s", val);
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (strncasecmp(tag, "State", MAX(taglen, 2)) == 0) {
			if (strncasecmp(val, "INACTIVE", MAX(vallen, 1)) == 0)
				part_msg_ptr->state_up = PARTITION_INACTIVE;
			else if (strncasecmp(val, "DOWN", MAX(vallen, 1)) == 0)
				part_msg_ptr->state_up = PARTITION_DOWN;
			else if (strncasecmp(val, "UP", MAX(vallen, 1)) == 0)
				part_msg_ptr->state_up = PARTITION_UP;
			else if (strncasecmp(val, "DRAIN", MAX(vallen, 1)) == 0)
				part_msg_ptr->state_up = PARTITION_DRAIN;
			else {
				exit_code = 1;
				error("Invalid input: %s", argv[i]);
				error("Acceptable State values "
					"are UP, DOWN, DRAIN and INACTIVE");
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "Nodes", MAX(taglen, 1))) {
			part_msg_ptr->nodes = val;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "AllowGroups", MAX(taglen, 6))) {
			part_msg_ptr->allow_groups = val;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "AllowAccounts", MAX(taglen, 6))) {
			part_msg_ptr->allow_accounts = val;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "AllowQos", MAX(taglen, 6))) {
			part_msg_ptr->allow_qos = val;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "DenyAccounts", MAX(taglen, 5))) {
			part_msg_ptr->deny_accounts = val;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "DenyQos", MAX(taglen, 5))) {
			part_msg_ptr->deny_qos = val;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "AllocNodes", MAX(taglen, 6))) {
			part_msg_ptr->allow_alloc_nodes = val;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "Alternate", MAX(taglen, 3))) {
			part_msg_ptr->alternate = val;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "GraceTime", MAX(taglen, 5))) {
			if (parse_uint32(val, &part_msg_ptr->grace_time)) {
				error ("Invalid GraceTime value: %s", val);
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "DefMemPerCPU", MAX(taglen, 10))) {
			if (parse_uint64(val, &part_msg_ptr->def_mem_per_cpu)) {
				error ("Invalid DefMemPerCPU value: %s", val);
				return -1;
			}
			part_msg_ptr->def_mem_per_cpu |= MEM_PER_CPU;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "DefMemPerNode", MAX(taglen, 10))) {
			if (parse_uint64(val, &part_msg_ptr->def_mem_per_cpu)) {
				error ("Invalid DefMemPerNode value: %s", val);
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "MaxMemPerCPU", MAX(taglen, 10))) {
			if (parse_uint64(val, &part_msg_ptr->max_mem_per_cpu)) {
				error ("Invalid MaxMemPerCPU value: %s", val);
				return -1;
			}
			part_msg_ptr->max_mem_per_cpu |= MEM_PER_CPU;
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "MaxMemPerNode", MAX(taglen, 10))) {
			if (parse_uint64(val, &part_msg_ptr->max_mem_per_cpu)) {
				error ("Invalid MaxMemPerNode value: %s", val);
				return -1;
			}
			(*update_cnt_ptr)++;
		}
		else if (!strncasecmp(tag, "QoS", MAX(taglen, 3))) {
			part_msg_ptr->qos_char = val;
			(*update_cnt_ptr)++;
		}
		else {
			exit_code = 1;
			error("Update of this parameter is not "
			      "supported: %s\n", argv[i]);
			error("Request aborted");
			return -1;
		}
	}
	return 0;
}
Ejemplo n.º 21
0
void
pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src)
{
	const char	  *message;

	if (opt == NULL)
	{
		fprintf(stderr, "Try \"%s --help\" for more information.\n", PROGRAM_NAME);
		exit(EINVAL);
	}

	if (opt->source > src)
	{
		/* high prior value has been set already. */
		return;
	}
	else if (src >= SOURCE_CMDLINE && opt->source >= src)
	{
		/* duplicated option in command line */
		message = "specified only once";
	}
	else
	{
		/* can be overwritten if non-command line source */
		opt->source = src;

		switch (opt->type)
		{
			case 'b':
			case 'B':
				if (optarg == NULL)
				{
					*((bool *) opt->var) = (opt->type == 'b');
					return;
				}
				else if (parse_bool(optarg, (bool *) opt->var))
				{
					return;
				}
				message = "a boolean";
				break;
			case 'f':
				((pgut_optfn) opt->var)(opt, optarg);
				return;
			case 'i':
				if (parse_int32(optarg, opt->var))
					return;
				message = "a 32bit signed integer";
				break;
			case 'u':
				if (parse_uint32(optarg, opt->var))
					return;
				message = "a 32bit unsigned integer";
				break;
			case 'I':
				if (parse_int64(optarg, opt->var))
					return;
				message = "a 64bit signed integer";
				break;
			case 'U':
				if (parse_uint64(optarg, opt->var))
					return;
				message = "a 64bit unsigned integer";
				break;
			case 's':
				if (opt->source != SOURCE_DEFAULT)
					free(*(char **) opt->var);
				*(char **) opt->var = pgut_strdup(optarg);
				return;
			case 't':
				if (parse_time(optarg, opt->var))
					return;
				message = "a time";
				break;
			case 'y':
			case 'Y':
				if (optarg == NULL)
				{
					*(YesNo *) opt->var = (opt->type == 'y' ? YES : NO);
					return;
				}
				else
				{
					bool	value;
					if (parse_bool(optarg, &value))
					{
						*(YesNo *) opt->var = (value ? YES : NO);
						return;
					}
				}
				message = "a boolean";
				break;
			default:
				ereport(ERROR,
					(errcode(EINVAL),
					 errmsg("invalid option type: %c", opt->type)));
				return;	/* keep compiler quiet */
		}
	}

	if (isprint(opt->sname))
		ereport(ERROR,
			(errcode(EINVAL),
			 errmsg("option -%c, --%s should be %s: '%s'",
				opt->sname, opt->lname, message, optarg)));
	else
		ereport(ERROR,
			(errcode(EINVAL),
			 errmsg("option --%s should be %s: '%s'",
				opt->lname, message, optarg)));
}
Ejemplo n.º 22
0
static void
hub_handle_command(char *buf, uint32_t len)
{
    char *hub_my_nick; /* XXX */

    hub_my_nick = main_to_hub_string(my_nick);

    if (len >= 6 && strncmp(buf, "$Lock ", 6) == 0) {
        char *key;

        if (!check_state(buf, (DCUserState) DC_HUB_LOCK))
            goto hub_handle_command_cleanup;

        key = (char*) memmem(buf+6, len-6, " Pk=", 4);
        if (key == NULL) {
            warn(_("Invalid $Lock message: Missing Pk value\n"));
            key = buf+len;
        }
        key = decode_lock(buf+6, key-buf-6, DC_CLIENT_BASE_KEY);
        if (strleftcmp("EXTENDEDPROTOCOL", buf+6) == 0) {
            if (!hub_putf("$Supports TTHSearch NoGetINFO NoHello|")) {
                free(key);
                goto hub_handle_command_cleanup;
            }
        }
        if (!hub_putf("$Key %s|", key)) {
            free(key);
            goto hub_handle_command_cleanup;
        }
        free(key);
        if (!hub_putf("$ValidateNick %s|", hub_my_nick))
            goto hub_handle_command_cleanup;
        hub_state = DC_HUB_HELLO;
    }
    else if (len >= 10 && strncmp(buf, "$Supports ", 10) == 0) {
        char *p0, *p1;

        hub_extensions = 0;
        for (p0 = buf+10; (p1 = strchr(p0, ' ')) != NULL; p0 = p1+1) {
            *p1 = '\0';
            parse_hub_extension(p0);
        }
        if (*p0 != '\0')
            parse_hub_extension(p0);
    }
    else if (strcmp(buf, "$GetPass") == 0) {
        if (my_password == NULL) {
            screen_putf(_("Hub requires password.\n"));
            hub_disconnect();
            goto hub_handle_command_cleanup;
        }
        screen_putf(_("Sending password to hub.\n"));
        if (!hub_putf("$MyPass %s|", my_password))
            goto hub_handle_command_cleanup;
    }
    else if (strcmp(buf, "$BadPass") == 0) {
        warn(_("Password not accepted.\n"));
        hub_disconnect();
    }
    else if (strcmp(buf, "$LogedIn") == 0) {
        screen_putf(_("You have received operator status.\n"));
    }
    else if (len >= 9 && strncmp(buf, "$HubName ", 9) == 0) {
        free(hub_name);
        hub_name = hub_to_main_string(buf + 9);
        screen_putf(_("Hub name is %s.\n"), quotearg(hub_name));
    }
    else if (strcmp(buf, "$GetNetInfo") == 0) {
        hub_putf("$NetInfo %d$1$%c|", my_ul_slots, is_active ? 'A' : 'P');
    }
    else if (strcmp(buf, "$ValidateDenide") == 0) {
        if (!check_state(buf, (DCUserState) DC_HUB_HELLO))
            goto hub_handle_command_cleanup;
        /* DC++ disconnects immediately if this is received.
         * But shouldn't we give the client a chance to change the nick?
         * Also what happens if we receive this when correctly logged in?
         */
        warn(_("Hub did not accept nick. Nick may be in use.\n"));
        hub_disconnect();
    }
    else if (len >= 7 && strncmp(buf, "$Hello ", 7) == 0) {
        DCUserInfo *ui;
        char *conv_nick;

        conv_nick = hub_to_main_string(buf + 7);

        if (hub_state == DC_HUB_HELLO) {
            if (strcmp(buf+7, hub_my_nick) == 0) {
                screen_putf(_("Nick accepted. You are now logged in.\n"));
            } else {
                /* This probably won't happen, but better safe... */
                free(my_nick);
                my_nick = xstrdup(conv_nick);
                free(hub_my_nick);
                hub_my_nick = xstrdup(buf + 7);
                screen_putf(_("Nick accepted but modified to %s. You are now logged in.\n"), quotearg(my_nick));
            }

            ui = user_info_new(conv_nick);
            ui->info_quered = true; /* Hub is sending this automaticly */
            hmap_put(hub_users, ui->nick, ui);

            free (conv_nick);

            if (!hub_putf("$Version 1,0091|"))
                goto hub_handle_command_cleanup;
            if (!hub_putf("$GetNickList|"))
                goto hub_handle_command_cleanup;
            if (!send_my_info())
                goto hub_handle_command_cleanup;

            hub_state = DC_HUB_LOGGED_IN;
        } else {
            flag_putf(DC_DF_JOIN_PART, _("User %s logged in.\n"), quotearg(conv_nick));
            ui = user_info_new(conv_nick);
            hmap_put(hub_users, ui->nick, ui);
            free (conv_nick);
            if ((hub_extensions & HUB_EXT_NOGETINFO) == 0) {
                if (!hub_putf("$GetINFO %s %s|", buf+7, hub_my_nick))
                    goto hub_handle_command_cleanup;
                ui->info_quered = true;
            }
        }
    }
    else if (len >= 8 && strncmp(buf, "$MyINFO ", 8) == 0) {
        DCUserInfo *ui;
        char *token;
        uint32_t len;
        char* conv_buf;
        char *work_buf;

        buf += 8;
        work_buf = conv_buf = hub_to_main_string(buf);
        token = strsep(&work_buf, " ");
        if (strcmp(token, "$ALL") != 0) {
            warn(_("Invalid $MyINFO message: Missing $ALL parameter, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }

        token = strsep(&work_buf, " ");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing nick parameter, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        ui = (DCUserInfo*) hmap_get(hub_users, token);
        if (ui == NULL) {
            /*
             * if the full buf has not been converted from hub to local charset,
             * we should try to convert nick only
             */
            /*
            char *conv_nick = hub_to_main_string(token);
            if ((ui = hmap_get(hub_users, conv_nick)) == NULL) {
            */
            ui = user_info_new(token);
            ui->info_quered = true;
            hmap_put(hub_users, ui->nick, ui);
            /*
            }
            free(conv_nick);
            */
        }

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing description parameter, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        free(ui->description);
        ui->description = xstrdup(token);

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing description separator, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing connection speed, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        len = strlen(token);
        free(ui->speed);
        if (len == 0) {
            ui->speed = xstrdup("");
            ui->level = 0; /* XXX: or 1? acceptable level? */
        } else {
            ui->speed = xstrndup(token, len-1);
            ui->level = token[len-1];
        }

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing e-mail address, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        free(ui->email);
        ui->email = xstrdup(token);

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing share size, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        if (!parse_uint64(token, &ui->share_size)) {
            warn(_("Invalid $MyINFO message: Invalid share size, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }

        if (ui->active_state == DC_ACTIVE_RECEIVED_PASSIVE
                || ui->active_state == DC_ACTIVE_KNOWN_ACTIVE)
            ui->active_state = DC_ACTIVE_UNKNOWN;

        /* XXX: Now that user's active_state may have changed, try queue again? */
        free(conv_buf);
    }
    else if (strcmp(buf, "$HubIsFull") == 0) {
        warn(_("Hub is full.\n"));
        /* DC++ does not disconnect immediately. So I guess we won't either. */
        /* Maybe we should be expecting an "hub follow" message? */
        /* hub_disconnect(); */
    }
    else if (len >= 3 && (buf[0] == '<' || strncmp(buf, " * ", 3) == 0)) {
        char *head;
        char *tail;
        char *msg;
        bool first = true;
        /*
        int scrwidth;
        size_t firstlen;
        size_t otherlen;

        screen_get_size(NULL, &scrwidth);
        firstlen = scrwidth - strlen(_("Public:"));
        otherlen = scrwidth - strlen(_(" | "));
        */

        msg = prepare_chat_string_for_display(buf);

        for (head = msg; (tail = strchr(head, '\n')) != NULL; head = tail+1) {
            /*PtrV *wrapped;*/

            if (tail[-1] == '\r') /* end > buf here, buf[0] == '<' or ' ' */
                tail[-1] = '\0';
            else
                tail[0] = '\0';

            /*wrapped = wordwrap(quotearg(buf), first ? firstlen : otherlen, otherlen);
            for (c = 0; c < wrapped->cur; c++)
            flag_putf(DC_DF_PUBLIC_CHAT, first ? _("Public: %s\n") : _(" | %s\n"), );
            ptrv_foreach(wrapped, free);
            ptrv_free(wrapped);*/
            flag_putf(DC_DF_PUBLIC_CHAT, first ? _("Public: %s\n") : _(" | %s\n"), quotearg(head));
            first = false;
        }
        flag_putf(DC_DF_PUBLIC_CHAT, first ? _("Public: %s\n") : _(" | %s\n"), quotearg(head));
        free(msg);
    }
    else if (len >= 5 && strncmp(buf, "$To: ", 5) == 0) {
        char *msg;
        char *tail;
        char *frm;
        char *head;
        bool first = true;

        msg = strchr(buf+5, '$');
        if (msg == NULL) {
            warn(_("Invalid $To message: Missing text separator, ignoring\n"));
            goto hub_handle_command_cleanup;
        }
        *msg = '\0';
        msg++;

        /* FIXME: WTF is this? Remove multiple "From: "? Why!? */
        frm = buf+5;
        while ((tail = strstr(msg, "From: ")) != NULL && tail < msg)
            frm = tail+6;

        msg = prepare_chat_string_for_display(msg);
        frm = prepare_chat_string_for_display(frm);
        for (head = msg; (tail = strchr(head, '\n')) != NULL; head = tail+1) {
            if (tail[-1] == '\r') /* tail > buf here because head[0] == '<' or ' ' */
                tail[-1] = '\0';
            else
                tail[0] = '\0';
            if (first) {
                screen_putf(_("Private: [%s] %s\n"), quotearg_n(0, frm), quotearg_n(1, head));
                first = false;
            } else {
                screen_putf(_(" | %s\n"), quotearg(head));
            }
        }
        if (first) {
            screen_putf(_("Private: [%s] %s\n"), quotearg_n(0, frm), quotearg_n(1, head));
        } else {
            screen_putf(_(" | %s\n"), quotearg(head));
        }
        free(msg);
        free(frm);
    }
    else if (len >= 13 && strncmp(buf, "$ConnectToMe ", 13) == 0) {
        struct sockaddr_in addr;

        buf += 13;
        if (strsep(&buf, " ") == NULL) {
            warn(_("Invalid $ConnectToMe message: Missing or invalid nick\n"));
            goto hub_handle_command_cleanup;
        }
        if (!parse_ip_and_port(buf, &addr, 0)) {
            warn(_("Invalid $ConnectToMe message: Invalid address specification.\n"));
            goto hub_handle_command_cleanup;
        }

        flag_putf(DC_DF_CONNECTIONS, _("Connecting to user on %s\n"), sockaddr_in_str(&addr));
        user_connection_new(&addr, -1);
    }
    else if (len >= 16 && strncmp(buf, "$RevConnectToMe ", 16) == 0) {
        char *nick;
        char *local_nick;
        DCUserInfo *ui;

        nick = strtok(buf+16, " ");
        if (nick == NULL) {
            warn(_("Invalid $RevConnectToMe message: Missing nick parameter\n"));
            goto hub_handle_command_cleanup;
        }
        if (strcmp(nick, hub_my_nick) == 0) {
            warn(_("Invalid $RevConnectToMe message: Remote nick is our nick\n"));
            goto hub_handle_command_cleanup;
        }
        local_nick = hub_to_main_string(nick);
        ui = (DCUserInfo*) hmap_get(hub_users, local_nick);
        if (ui == NULL) {
            warn(_("Invalid $RevConnectToMe message: Unknown user %s, ignoring\n"), quotearg(local_nick));
            free(local_nick);
            goto hub_handle_command_cleanup;
        }
        free(local_nick);

        if (ui->conn_count >= DC_USER_MAX_CONN) {
            warn(_("No more connections to user %s allowed.\n"), quotearg(ui->nick));
            goto hub_handle_command_cleanup;
        }

        if (!is_active) {
            if (ui->active_state == DC_ACTIVE_SENT_PASSIVE) {
                warn(_("User %s is also passive. Cannot establish connection.\n"), quotearg(ui->nick));
                /* We could set this to DC_ACTIVE_UNKNOWN too. This would mean
                 * we would keep sending RevConnectToMe next time the download
                 * queue is modified or some timer expired and told us to retry
                 * download. The remote would then send back RevConnectToMe
                 * and this would happen again. This way we would try again -
                 * maybe remote has become active since last time we checked?
                 * But no - DC++ only replies with RevConnectToMe to our first
                 * RevConnectToMe. After that it ignores them all.
                 */
                ui->active_state = DC_ACTIVE_RECEIVED_PASSIVE;
                if (hmap_remove(pending_userinfo, ui->nick) != NULL)
                    ui->refcount--;
                goto hub_handle_command_cleanup;
            }
            if (ui->active_state != DC_ACTIVE_RECEIVED_PASSIVE) {
                /* Inform remote that we are also passive. */
                if (!hub_putf("$RevConnectToMe %s %s|", hub_my_nick, nick))
                    goto hub_handle_command_cleanup;
            }
        }
        ui->active_state = DC_ACTIVE_RECEIVED_PASSIVE;

        if (!hub_connect_user(ui))
            goto hub_handle_command_cleanup;
    }
    else if ( (len >= 10 && strncmp(buf, "$NickList ", 10) == 0)
              || (len >= 8 && strncmp(buf, "$OpList ", 8) == 0) ) {
        char *nick;
        char *end;
        int oplist;
        char *conv_nick;

        if ( strncmp(buf, "$NickList ", 10) == 0) {
            nick = buf + 10;
            oplist = 0;
        } else {
            nick = buf + 8;
            oplist = 1;
        }

        for (; (end = strstr(nick, "$$")) != NULL; nick = end+2) {
            DCUserInfo *ui;
            *end = '\0';

            conv_nick = hub_to_main_string(nick);

            ui = (DCUserInfo*) hmap_get(hub_users, conv_nick);
            if (ui == NULL) {
                ui = user_info_new(conv_nick);
                hmap_put(hub_users, ui->nick, ui);
            }

            free(conv_nick);

            if (!ui->info_quered && (hub_extensions & HUB_EXT_NOGETINFO) == 0) {
                if (!hub_putf("$GetINFO %s %s|", nick, hub_my_nick))  {
                    goto hub_handle_command_cleanup;
                }
                ui->info_quered = true;
            }

            if (oplist)
                ui->is_operator = true;
        }
    }
    else if (len >= 6 && strncmp(buf, "$Quit ", 6) == 0) {
        DCUserInfo *ui;
        char *conv_nick = hub_to_main_string(buf+6);

        // I don't want these messages.
        //flag_putf(DC_DF_JOIN_PART, "User %s quits.\n", quotearg(conv_nick));
        ui = (DCUserInfo*) hmap_remove(hub_users, conv_nick);
        if (ui == NULL) {
            /* Some hubs print quit messages for users that never joined,
             * so print this as debug only.
             */
            flag_putf(DC_DF_DEBUG, _("Invalid $Quit message: Unknown user %s.\n"), quotearg(conv_nick));
        } else
            user_info_free(ui);
        free(conv_nick);
    }
    else if (len >= 8 && strncmp(buf, "$Search ", 8) == 0) {
        char *source;
        int parse_result = 0;
        DCSearchSelection sel;
        sel.patterns = NULL;

        buf += 8;
        source = strsep(&buf, " ");
        if (source == NULL) {
            warn(_("Invalid $Search message: Missing source specification.\n"));
            goto hub_handle_command_cleanup;
        }
        /* charset handling is in parse_search_selection */
        parse_result = parse_search_selection(buf, &sel);
        if (parse_result != 1) {
            if (sel.patterns != NULL) {
                int i = 0;
                for (i = 0; i < sel.patterncount; i++) {
                    search_string_free(sel.patterns+i);
                }
                free(sel.patterns);
            }
            if (parse_result == 0)
                warn(_("Invalid $Search message: %s: Invalid search specification.\n"), buf);
            goto hub_handle_command_cleanup;
        }
        if (strncmp(source, "Hub:", 4) == 0) {
            DCUserInfo *ui;
            char *conv_nick = hub_to_main_string(source+4);
            ui = (DCUserInfo*) hmap_get(hub_users, conv_nick);

            if (ui == NULL) {
                warn(_("Invalid $Search message: Unknown user %s.\n"), quotearg(conv_nick));
                if (sel.patterns != NULL) {
                    int i = 0;
                    for (i = 0; i < sel.patterncount; i++) {
                        search_string_free(sel.patterns+i);
                    }
                    free(sel.patterns);
                }
                free(conv_nick);
                goto hub_handle_command_cleanup;
            }
            free(conv_nick);

            if (strcmp(ui->nick, my_nick) == 0) {
                if (sel.patterns != NULL) {
                    int i = 0;
                    for (i = 0; i < sel.patterncount; i++) {
                        search_string_free(sel.patterns+i);
                    }
                    free(sel.patterns);
                }
                goto hub_handle_command_cleanup;
            }
            perform_inbound_search(&sel, ui, NULL);
            if (sel.patterns != NULL) {
                int i = 0;
                for (i = 0; i < sel.patterncount; i++) {
                    search_string_free(sel.patterns+i);
                }
                free(sel.patterns);
            }
        } else {
            struct sockaddr_in addr;
            if (!parse_ip_and_port(source, &addr, DC_CLIENT_UDP_PORT)) {
                warn(_("Invalid $Search message: Invalid address specification.\n"));
                if (sel.patterns != NULL) {
                    int i = 0;
                    for (i = 0; i < sel.patterncount; i++) {
                        search_string_free(sel.patterns+i);
                    }
                    free(sel.patterns);
                }
                goto hub_handle_command_cleanup;
            }
            if (local_addr.sin_addr.s_addr == addr.sin_addr.s_addr && listen_port == ntohs(addr.sin_port)) {
                if (sel.patterns != NULL) {
                    int i = 0;
                    for (i = 0; i < sel.patterncount; i++) {
                        search_string_free(sel.patterns+i);
                    }
                    free(sel.patterns);
                }
                goto hub_handle_command_cleanup;
            }
            perform_inbound_search(&sel, NULL, &addr);
            if (sel.patterns != NULL) {
                int i = 0;
                for (i = 0; i < sel.patterncount; i++) {
                    search_string_free(sel.patterns+i);
                }
                free(sel.patterns);
            }
        }
    } else if (len >= 4 && strncmp(buf, "$SR ", 4) == 0) {
        handle_search_result(buf, len);
    } else if (len == 0) {
        /* Ignore empty commands. */
    }
hub_handle_command_cleanup:
    free(hub_my_nick);
}
Ejemplo n.º 23
0
FLAC__bool parse_option(int option_index, const char *option_argument, CommandLineOptions *options)
{
	const char *opt = long_options_[option_index].name;
	Operation *op;
	Argument *arg;
	FLAC__bool ok = true;

	if(0 == strcmp(opt, "preserve-modtime")) {
		options->preserve_modtime = true;
	}
	else if(0 == strcmp(opt, "with-filename")) {
		options->prefix_with_filename = true;
	}
	else if(0 == strcmp(opt, "no-filename")) {
		options->prefix_with_filename = false;
	}
	else if(0 == strcmp(opt, "no-utf8-convert")) {
		options->utf8_convert = false;
	}
	else if(0 == strcmp(opt, "dont-use-padding")) {
		options->use_padding = false;
	}
	else if(0 == strcmp(opt, "no-cued-seekpoints")) {
		options->cued_seekpoints = false;
	}
	else if(0 == strcmp(opt, "show-md5sum")) {
		(void) append_shorthand_operation(options, OP__SHOW_MD5SUM);
	}
	else if(0 == strcmp(opt, "show-min-blocksize")) {
		(void) append_shorthand_operation(options, OP__SHOW_MIN_BLOCKSIZE);
	}
	else if(0 == strcmp(opt, "show-max-blocksize")) {
		(void) append_shorthand_operation(options, OP__SHOW_MAX_BLOCKSIZE);
	}
	else if(0 == strcmp(opt, "show-min-framesize")) {
		(void) append_shorthand_operation(options, OP__SHOW_MIN_FRAMESIZE);
	}
	else if(0 == strcmp(opt, "show-max-framesize")) {
		(void) append_shorthand_operation(options, OP__SHOW_MAX_FRAMESIZE);
	}
	else if(0 == strcmp(opt, "show-sample-rate")) {
		(void) append_shorthand_operation(options, OP__SHOW_SAMPLE_RATE);
	}
	else if(0 == strcmp(opt, "show-channels")) {
		(void) append_shorthand_operation(options, OP__SHOW_CHANNELS);
	}
	else if(0 == strcmp(opt, "show-bps")) {
		(void) append_shorthand_operation(options, OP__SHOW_BPS);
	}
	else if(0 == strcmp(opt, "show-total-samples")) {
		(void) append_shorthand_operation(options, OP__SHOW_TOTAL_SAMPLES);
	}
	else if(0 == strcmp(opt, "set-md5sum")) {
		op = append_shorthand_operation(options, OP__SET_MD5SUM);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_md5(option_argument, op->argument.streaminfo_md5.value)) {
			flac_fprintf(stderr, "ERROR (--%s): bad MD5 sum\n", opt);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "set-min-blocksize")) {
		op = append_shorthand_operation(options, OP__SET_MIN_BLOCKSIZE);
		if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value < FLAC__MIN_BLOCK_SIZE || op->argument.streaminfo_uint32.value > FLAC__MAX_BLOCK_SIZE) {
			flac_fprintf(stderr, "ERROR (--%s): value must be >= %u and <= %u\n", opt, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "set-max-blocksize")) {
		op = append_shorthand_operation(options, OP__SET_MAX_BLOCKSIZE);
		if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value < FLAC__MIN_BLOCK_SIZE || op->argument.streaminfo_uint32.value > FLAC__MAX_BLOCK_SIZE) {
			flac_fprintf(stderr, "ERROR (--%s): value must be >= %u and <= %u\n", opt, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "set-min-framesize")) {
		op = append_shorthand_operation(options, OP__SET_MIN_FRAMESIZE);
		if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value >= (1u<<FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN)) {
			flac_fprintf(stderr, "ERROR (--%s): value must be a %u-bit unsigned integer\n", opt, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "set-max-framesize")) {
		op = append_shorthand_operation(options, OP__SET_MAX_FRAMESIZE);
		if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value >= (1u<<FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN)) {
			flac_fprintf(stderr, "ERROR (--%s): value must be a %u-bit unsigned integer\n", opt, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "set-sample-rate")) {
		op = append_shorthand_operation(options, OP__SET_SAMPLE_RATE);
		if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || !FLAC__format_sample_rate_is_valid(op->argument.streaminfo_uint32.value)) {
			flac_fprintf(stderr, "ERROR (--%s): invalid sample rate\n", opt);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "set-channels")) {
		op = append_shorthand_operation(options, OP__SET_CHANNELS);
		if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value > FLAC__MAX_CHANNELS) {
			flac_fprintf(stderr, "ERROR (--%s): value must be > 0 and <= %u\n", opt, FLAC__MAX_CHANNELS);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "set-bps")) {
		op = append_shorthand_operation(options, OP__SET_BPS);
		if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value < FLAC__MIN_BITS_PER_SAMPLE || op->argument.streaminfo_uint32.value > FLAC__MAX_BITS_PER_SAMPLE) {
			flac_fprintf(stderr, "ERROR (--%s): value must be >= %u and <= %u\n", opt, FLAC__MIN_BITS_PER_SAMPLE, FLAC__MAX_BITS_PER_SAMPLE);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "set-total-samples")) {
		op = append_shorthand_operation(options, OP__SET_TOTAL_SAMPLES);
		if(!parse_uint64(option_argument, &(op->argument.streaminfo_uint64.value)) || op->argument.streaminfo_uint64.value >= (((FLAC__uint64)1)<<FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)) {
			flac_fprintf(stderr, "ERROR (--%s): value must be a %u-bit unsigned integer\n", opt, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN);
			ok = false;
		}
		else
			undocumented_warning(opt);
	}
	else if(0 == strcmp(opt, "show-vendor-tag")) {
		(void) append_shorthand_operation(options, OP__SHOW_VC_VENDOR);
	}
	else if(0 == strcmp(opt, "show-tag")) {
		const char *violation;
		op = append_shorthand_operation(options, OP__SHOW_VC_FIELD);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_vorbis_comment_field_name(option_argument, &(op->argument.vc_field_name.value), &violation)) {
			FLAC__ASSERT(0 != violation);
			flac_fprintf(stderr, "ERROR (--%s): malformed vorbis comment field name \"%s\",\n       %s\n", opt, option_argument, violation);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "remove-all-tags")) {
		(void) append_shorthand_operation(options, OP__REMOVE_VC_ALL);
	}
	else if(0 == strcmp(opt, "remove-tag")) {
		const char *violation;
		op = append_shorthand_operation(options, OP__REMOVE_VC_FIELD);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_vorbis_comment_field_name(option_argument, &(op->argument.vc_field_name.value), &violation)) {
			FLAC__ASSERT(0 != violation);
			flac_fprintf(stderr, "ERROR (--%s): malformed vorbis comment field name \"%s\",\n       %s\n", opt, option_argument, violation);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "remove-first-tag")) {
		const char *violation;
		op = append_shorthand_operation(options, OP__REMOVE_VC_FIRSTFIELD);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_vorbis_comment_field_name(option_argument, &(op->argument.vc_field_name.value), &violation)) {
			FLAC__ASSERT(0 != violation);
			flac_fprintf(stderr, "ERROR (--%s): malformed vorbis comment field name \"%s\",\n       %s\n", opt, option_argument, violation);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "set-tag")) {
		const char *violation;
		op = append_shorthand_operation(options, OP__SET_VC_FIELD);
		FLAC__ASSERT(0 != option_argument);
		op->argument.vc_field.field_value_from_file = false;
		if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) {
			FLAC__ASSERT(0 != violation);
			flac_fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n       %s\n", opt, option_argument, violation);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "set-tag-from-file")) {
		const char *violation;
		op = append_shorthand_operation(options, OP__SET_VC_FIELD);
		FLAC__ASSERT(0 != option_argument);
		op->argument.vc_field.field_value_from_file = true;
		if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) {
			FLAC__ASSERT(0 != violation);
			flac_fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n       %s\n", opt, option_argument, violation);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "import-tags-from")) {
		op = append_shorthand_operation(options, OP__IMPORT_VC_FROM);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_string(option_argument, &(op->argument.filename.value))) {
			flac_fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "export-tags-to")) {
		op = append_shorthand_operation(options, OP__EXPORT_VC_TO);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_string(option_argument, &(op->argument.filename.value))) {
			flac_fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "import-cuesheet-from")) {
		if(0 != find_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM)) {
			flac_fprintf(stderr, "ERROR (--%s): may be specified only once\n", opt);
			ok = false;
		}
		op = append_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_string(option_argument, &(op->argument.import_cuesheet_from.filename))) {
			flac_fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "export-cuesheet-to")) {
		op = append_shorthand_operation(options, OP__EXPORT_CUESHEET_TO);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_string(option_argument, &(op->argument.filename.value))) {
			flac_fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "import-picture-from")) {
		op = append_shorthand_operation(options, OP__IMPORT_PICTURE_FROM);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_string(option_argument, &(op->argument.specification.value))) {
			flac_fprintf(stderr, "ERROR (--%s): missing specification\n", opt);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "export-picture-to")) {
		arg = find_argument(options, ARG__BLOCK_NUMBER);
		op = append_shorthand_operation(options, OP__EXPORT_PICTURE_TO);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_string(option_argument, &(op->argument.export_picture_to.filename))) {
			flac_fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
			ok = false;
		}
		op->argument.export_picture_to.block_number_link = arg? &(arg->value.block_number) : 0;
	}
	else if(0 == strcmp(opt, "add-seekpoint")) {
		const char *violation;
		char *spec;
		FLAC__ASSERT(0 != option_argument);
		if(!parse_add_seekpoint(option_argument, &spec, &violation)) {
			FLAC__ASSERT(0 != violation);
			flac_fprintf(stderr, "ERROR (--%s): malformed seekpoint specification \"%s\",\n       %s\n", opt, option_argument, violation);
			ok = false;
		}
		else {
			op = find_shorthand_operation(options, OP__ADD_SEEKPOINT);
			if(0 == op)
				op = append_shorthand_operation(options, OP__ADD_SEEKPOINT);
			local_strcat(&(op->argument.add_seekpoint.specification), spec);
			local_strcat(&(op->argument.add_seekpoint.specification), ";");
			free(spec);
		}
	}
	else if(0 == strcmp(opt, "add-replay-gain")) {
		(void) append_shorthand_operation(options, OP__ADD_REPLAY_GAIN);
	}
	else if(0 == strcmp(opt, "remove-replay-gain")) {
		const FLAC__byte * const tags[5] = {
			GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS,
			GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN,
			GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK,
			GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN,
			GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK
		};
		size_t i;
		for(i = 0; i < sizeof(tags)/sizeof(tags[0]); i++) {
			op = append_shorthand_operation(options, OP__REMOVE_VC_FIELD);
			op->argument.vc_field_name.value = local_strdup((const char *)tags[i]);
		}
	}
	else if(0 == strcmp(opt, "add-padding")) {
		op = append_shorthand_operation(options, OP__ADD_PADDING);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_add_padding(option_argument, &(op->argument.add_padding.length))) {
			flac_fprintf(stderr, "ERROR (--%s): illegal length \"%s\", length must be >= 0 and < 2^%u\n", opt, option_argument, FLAC__STREAM_METADATA_LENGTH_LEN);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "help")) {
		options->show_long_help = true;
	}
	else if(0 == strcmp(opt, "version")) {
		options->show_version = true;
	}
	else if(0 == strcmp(opt, "list")) {
		(void) append_major_operation(options, OP__LIST);
	}
	else if(0 == strcmp(opt, "append")) {
		(void) append_major_operation(options, OP__APPEND);
	}
	else if(0 == strcmp(opt, "remove")) {
		(void) append_major_operation(options, OP__REMOVE);
	}
	else if(0 == strcmp(opt, "remove-all")) {
		(void) append_major_operation(options, OP__REMOVE_ALL);
	}
	else if(0 == strcmp(opt, "merge-padding")) {
		(void) append_major_operation(options, OP__MERGE_PADDING);
	}
	else if(0 == strcmp(opt, "sort-padding")) {
		(void) append_major_operation(options, OP__SORT_PADDING);
	}
	else if(0 == strcmp(opt, "block-number")) {
		arg = append_argument(options, ARG__BLOCK_NUMBER);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_block_number(option_argument, &(arg->value.block_number))) {
			flac_fprintf(stderr, "ERROR: malformed block number specification \"%s\"\n", option_argument);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "block-type")) {
		arg = append_argument(options, ARG__BLOCK_TYPE);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_block_type(option_argument, &(arg->value.block_type))) {
			flac_fprintf(stderr, "ERROR (--%s): malformed block type specification \"%s\"\n", opt, option_argument);
			ok = false;
		}
		options->args.checks.has_block_type = true;
	}
	else if(0 == strcmp(opt, "except-block-type")) {
		arg = append_argument(options, ARG__EXCEPT_BLOCK_TYPE);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_block_type(option_argument, &(arg->value.block_type))) {
			flac_fprintf(stderr, "ERROR (--%s): malformed block type specification \"%s\"\n", opt, option_argument);
			ok = false;
		}
		options->args.checks.has_except_block_type = true;
	}
	else if(0 == strcmp(opt, "data-format")) {
		arg = append_argument(options, ARG__DATA_FORMAT);
		FLAC__ASSERT(0 != option_argument);
		if(!parse_data_format(option_argument, &(arg->value.data_format))) {
			flac_fprintf(stderr, "ERROR (--%s): illegal data format \"%s\"\n", opt, option_argument);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "application-data-format")) {
		FLAC__ASSERT(0 != option_argument);
		if(!parse_application_data_format(option_argument, &(options->application_data_format_is_hexdump))) {
			flac_fprintf(stderr, "ERROR (--%s): illegal application data format \"%s\"\n", opt, option_argument);
			ok = false;
		}
	}
	else if(0 == strcmp(opt, "from-file")) {
		arg = append_argument(options, ARG__FROM_FILE);
		FLAC__ASSERT(0 != option_argument);
		arg->value.from_file.file_name = local_strdup(option_argument);
	}
	else {
		FLAC__ASSERT(0);
	}

	return ok;
}
Ejemplo n.º 24
0
static void
magnet_handle_key(struct magnet_resource *res,
	const char *name, const char *value)
{
	char *to_free = NULL;

	g_return_if_fail(res);
	g_return_if_fail(name);
	g_return_if_fail(value);
	
	if (!utf8_is_valid_string(value)) {
		const char *encoding;
		char *result;
			
		g_message("MAGNET URI key \"%s\" is not UTF-8 encoded", name);

		if (MAGNET_KEY_DISPLAY_NAME != magnet_key_get(name))
			return;

		result = unknown_to_utf8(value, &encoding);
		if (result != value) {
			to_free = result;
		}
		value = result;
		g_message("assuming MAGNET URI key \"%s\" is %s encoded",
			name, encoding);
	}

	switch (magnet_key_get(name)) {
	case MAGNET_KEY_DISPLAY_NAME:
		if (!res->display_name) {
			magnet_set_display_name(res, value);
		}
		break;

	case MAGNET_KEY_ALTERNATE_SOURCE:
	case MAGNET_KEY_EXACT_SOURCE:
		{
			struct magnet_source *ms;
			const char *error;

			ms = magnet_parse_exact_source(value, &error);
			if (ms) {
				if (!res->sha1 && ms->sha1) {
					res->sha1 = atom_sha1_get(ms->sha1);
				}
				if (!ms->sha1 || sha1_eq(res->sha1, ms->sha1)) {
					res->sources = g_slist_prepend(res->sources, ms);
				} else {
					magnet_source_free(&ms);
				}
			} else {
				g_message("could not parse source \"%s\" in MAGNET URI: %s",
					value, NULL_STRING(error));
			}
		}
		break;

	case MAGNET_KEY_EXACT_TOPIC:
		if (!magnet_set_exact_topic(res, value)) {
			g_message("MAGNET URI contained unsupported exact topic \"%s\"",
				value);
		}
		break;

	case MAGNET_KEY_KEYWORD_TOPIC:
		magnet_add_search(res, value);
		break;

	case MAGNET_KEY_EXACT_LENGTH:
		{
			int error;
			uint64 u;

			u = parse_uint64(value, NULL, 10, &error);
			if (!error) {
				magnet_set_filesize(res, u);
			}
		}
		break;

	case MAGNET_KEY_PARQ_ID:
		magnet_set_parq_id(res, value);
		break;

	case MAGNET_KEY_VENDOR:
		magnet_set_vendor(res, value);
		break;

	case MAGNET_KEY_GUID:
		magnet_set_guid(res, value);
		break;

	case MAGNET_KEY_DHT:
		{
			int error;
			uint8 u;

			u = parse_uint8(value, NULL, 10, &error);
			if (!error) {
				magnet_set_dht(res, u);
			}
		}
		break;

	case MAGNET_KEY_NONE:
		g_message("unhandled parameter in MAGNET URI: \"%s\"", name);
		break;

	case NUM_MAGNET_KEYS:
		g_assert_not_reached();
	}

	G_FREE_NULL(to_free);
}