示例#1
0
/**
 * Fill supplied buffer with the formatted string describing the message.
 *
 * @param data		start of the G2 message
 * @param len		length of the message
 * @param buf		buffer where formatted string is written
 * @param buflen	length of the destination buffer
 *
 * @return the amount of bytes written.
 */
size_t
g2_msg_infostr_to_buf(const void *data, size_t len, char *buf, size_t buflen)
{
	enum g2_msg m;
	const guid_t *muid = NULL;

	g_assert(size_is_non_negative(len));
	g_assert(size_is_non_negative(buflen));

	/*
	 * Check whether we need to decompile the packet to access the GUID, which
	 * is the payload of the root element in the tree.  Given the way things
	 * are serialized, that would be the last 16 bytes of the message, so
	 * we don't have to deserialize everything just to access it.
	 */

	m = g2_msg_type(data, len);

	switch (m) {
	case G2_MSG_Q2:
	case G2_MSG_QA:
	case G2_MSG_QH2:
		if (len > GUID_RAW_SIZE)
			muid = const_ptr_add_offset(data, len - GUID_RAW_SIZE);
		/* FALL THROUGH */
	default:
		break;
	}

	return str_bprintf(buf, buflen,
		"/%s (%zu byte%s)%s%s",
		g2_msg_type_name(m), len, plural(len),
		NULL == muid ? "" : " #",
		NULL == muid ? "" : guid_hex_str(muid));
}
示例#2
0
/**
 * Creates an incremental zlib deflater for `len' bytes starting at `data',
 * with specified compression `level'.
 *
 * @param data		data to compress; if NULL, will be incrementally given
 * @param len		length of data to compress (if data not NULL) or estimation
 * @param dest		where compressed data should go, or NULL if allocated
 * @param destlen	length of supplied output buffer, if dest != NULL
 * @param level		compression level, between 0 and 9.
 *
 * @return new deflater, or NULL if error.
 */
static zlib_deflater_t *
zlib_deflater_alloc(
    const void *data, size_t len, void *dest, size_t destlen, int level)
{
    zlib_deflater_t *zd;
    z_streamp outz;
    int ret;

    g_assert(size_is_non_negative(len));
    g_assert(size_is_non_negative(destlen));
    g_assert(level == Z_DEFAULT_COMPRESSION || (level >= 0 && level <= 9));

    WALLOC(outz);
    outz->zalloc = zlib_alloc_func;
    outz->zfree = zlib_free_func;
    outz->opaque = NULL;

    ret = deflateInit(outz, level);

    if (ret != Z_OK) {
        WFREE(outz);
        g_carp("%s(): unable to initialize compressor: %s",
               G_STRFUNC, zlib_strerror(ret));
        return NULL;
    }

    WALLOC0(zd);
    zd->zs.magic = ZLIB_DEFLATER_MAGIC;
    zd->zs.z = outz;
    zd->zs.closed = FALSE;

    zlib_stream_init(&zd->zs, data, len, dest, destlen);

    return zd;
}
示例#3
0
/**
 * Initialize internal state for our incremental zlib stream.
 *
 * @param zs		the zlib stream structure to initialize
 * @param data		input data to process; if NULL, will be incrementally given
 * @param len		length of data to process (if data not NULL) or estimation
 * @param dest		where processed data should go, or NULL if allocated
 * @param destlen	length of supplied output buffer, if dest != NULL
 */
static void
zlib_stream_init(zlib_stream_t *zs,
                 const void *data, size_t len, void *dest, size_t destlen)
{
    z_streamp z;

    g_assert(size_is_non_negative(len));
    g_assert(size_is_non_negative(destlen));

    zs->in = data;
    zs->inlen = data ? len : 0;
    zs->inlen_total = zs->inlen;

    /*
     * When deflating zlib requires normally 0.1% more + 12 bytes, we use
     * 0.5% to be safe.
     *
     * When inflating, assume we'll double the input at least.
     */

    if (NULL == dest) {
        /* Processed data go to a dynamically allocated buffer */
        if (!zs->allocated) {
            if (data == NULL && len == 0)
                len = 512;

            if (ZLIB_DEFLATER_MAGIC == zs->magic) {
                zs->outlen = (len * 1.005 + 12.0);
                g_assert(zs->outlen > len);
                g_assert(zs->outlen - len >= 12);
            } else {
                zs->outlen = UNSIGNED(len) * 2;
            }

            zs->out = halloc(zs->outlen);
            zs->allocated = TRUE;
        }
    } else {
        /* Processed data go to a supplied buffer, not-resizable */
        if (zs->allocated)
            hfree(zs->out);
        zs->out = dest;
        zs->outlen = destlen;
        zs->allocated = FALSE;
    }

    /*
     * Initialize Z stream.
     */

    z = zs->z;
    g_assert(z != NULL);			/* Stream not closed yet */

    z->next_out = zs->out;
    z->avail_out = zs->outlen;
    z->next_in = deconstify_pointer(zs->in);
    z->avail_in = 0;			/* Will be set by zlib_xxx_step() */
}
示例#4
0
/**
 * Initialize expanded list.
 *
 * Assuming items in the list are defined as:
 *
 *     struct item {
 *         <data fields>
 *         struct chaining {
 *             <some chaining links>
 *             struct chaining *next;	// our "next" pointer, linking field
 *         } chain;
 *     };
 *
 * then the offset argument can be given as:
 *
 *     offsetof(struct item, chain)
 *
 * and the link_offset argument can be given as:
 *
 *     offsetof(struct chaining, next)
 *
 * to indicate the place of the field chaining items together.
 *
 * @param list			the list structure to initialize
 * @param offset		the offset of the expanded link field within items
 * @param link_offset	the offset of the linking field in the chaining struct
 */
void
xslist_init(xslist_t *list, size_t offset, size_t link_offset)
{
	g_assert(list != NULL);
	g_assert(size_is_non_negative(offset));
	g_assert(size_is_non_negative(link_offset));

	list->magic = XSLIST_MAGIC;
	list->head = NULL;
	list->tail = NULL;
	list->count = 0;
	list->offset = offset;
	list->link_offset = link_offset;
}
示例#5
0
/**
 * Appends `n_bytes' to the pmsg_t buffer. If the last pmsg_t is writable
 * it is filled with as much data as space is still available. Otherwise
 * or if this space is not sufficient another pmsg_t is created and
 * appendded to the list.
 */
void
pmsg_slist_append(slist_t *slist, const void *data, size_t n_bytes)
{
	pmsg_t *mb;

	g_assert(slist);
	g_assert_log(size_is_non_negative(n_bytes),
		"%s(): n_bytes=%zd", G_STRFUNC, n_bytes);

	if (0 == n_bytes)
		return;
	g_assert(NULL != data);

	mb = slist_tail(slist);
	if (mb && pmsg_is_writable(mb)) {
		size_t n;

		n = pmsg_write(mb, data, n_bytes);
		data = (const char *) data + n;
		n_bytes -= n;
	}
	if (n_bytes > 0) {
		mb = pmsg_new(PMSG_P_DATA, NULL, MAX(n_bytes, PMSG_SLIST_GROW_MIN));
		pmsg_write(mb, data, n_bytes);
		slist_append(slist, mb);
	}
}
示例#6
0
/**
 * Read data from the pmsg list into supplied buffer.  Copied data is
 * removed from the list.
 *
 * @param slist		the pmsg list
 * @param buf		start of buffer where data must be copied
 * @param len		length of buffer
 *
 * @return amount of copied bytes.
 */
size_t
pmsg_slist_read(slist_t *slist, void *buf, size_t len)
{
	slist_iter_t *iter;
	size_t remain = len;
	void *p;

	g_assert(slist != NULL);
	g_assert_log(size_is_non_negative(len), "%s(): len=%zd", G_STRFUNC, len);

	iter = slist_iter_removable_on_head(slist);
	p = buf;

	while (remain != 0 && slist_iter_has_item(iter)) {
		pmsg_t *mb = slist_iter_current(iter);
		int n;

		n = pmsg_read(mb, p, remain);
		remain -= n;
		p = ptr_add_offset(p, n);
		if (0 == pmsg_size(mb)) {			/* Fully copied message */
			pmsg_free(mb);
			slist_iter_remove(iter);		/* Warning: moves to next */
		} else {
			break;		/* No need to continue on partial copy */
		}
	}
	slist_iter_free(&iter);

	return len - remain;
}
示例#7
0
/**
 * Convenience routine: format tree to memory buffer.
 *
 * @param root		tree to dump
 * @param buf		buffer where formatting is done
 * @param len		buffer length
 * @param options	formatting options
 *
 * @return length of generated string, -1 on failure.
 */
size_t
xfmt_tree_to_buffer(const xnode_t *root, void *buf, size_t len, uint32 options)
{
    ostream_t *os;
    pdata_t *pd;
    pmsg_t *mb;
    bool ok;
    size_t written = (size_t) -1;

    g_assert(root != NULL);
    g_assert(buf != NULL);
    g_assert(size_is_non_negative(len));

    pd = pdata_allocb_ext(buf, len, pdata_free_nop, NULL);
    mb = pmsg_alloc(PMSG_P_DATA, pd, 0, 0);
    os = ostream_open_pmsg(mb);

    ok = xfmt_tree(root, os, options);
    ok = ostream_close(os) && ok;

    if (ok)
        written = pmsg_size(mb);

    pmsg_free(mb);

    g_assert((size_t) -1 == written || written <= len);

    return written;
}
示例#8
0
/**
 * Initialize and load linked items into a list.
 *
 * This routine is meant to allow the creation of an expanded list from
 * homogeneous items that happen to be linked into another data structure
 * through a single pointer.
 *
 * It is useful to allow reuse of code that can process such lists, such
 * as xslist_sort(), xslist_shuffle(), etc...  It is naturally up to the
 * caller to then refetch the proper head pointer.
 *
 * @param list			the list into which we are loading items
 * @param head			first data item part of the linked list (NULL possible)
 * @param offset		the offset of the expanded link field within items
 * @param link_offset	the offset of the linking field in the chaining struct
 *
 * @return the amount of loaded items, as a convenience.
 */
size_t
xslist_load(xslist_t *list, void *head, size_t offset, size_t link_offset)
{
	xslink_t *lk, *next;
	size_t n;

	g_assert(list != NULL);
	g_assert(size_is_non_negative(offset));

	xslist_init(list, offset, link_offset);

	if G_UNLIKELY(NULL == head)
		return 0;

	lk = ptr_add_offset(head, offset);
	list->head = lk;

	for (n = 1; NULL != (next = xslist_next(list, lk)); n++, lk = next)
		/* empty */;

	list->tail = lk;
	list->count = n;

	safety_assert(xslist_length(list, list->head) == list->count);

	return n;
}
示例#9
0
/**
 * Initialize embedded tree.
 *
 * Assuming items in the tree are defined as:
 *
 *     struct item {
 *         <data fields>
 *         node_t n;
 *     };
 *
 * then the last argument can be given as:
 *
 *     offsetof(struct item, n)
 *
 * to indicate the place of the node field within the item.
 *
 * Extended trees are available to make etree_append_child() efficient but if
 * children can only be prepended, use normal trees (less overhead per node).
 *
 * @param tree		the tree structure to initialize
 * @param extended	whether extended nodex_t are used instead of node_t
 * @param offset	the offset of the embedded link field within items
 */
void
etree_init(etree_t *tree, bool extended, size_t offset)
{
	g_assert(tree != NULL);
	g_assert(size_is_non_negative(offset));

	tree->magic = extended ? ETREE_EXT_MAGIC : ETREE_MAGIC;
	tree->root = NULL;
	tree->offset = offset;
	tree->count = 0;
}
示例#10
0
/**
 * Shuffle array in-place.
 */
static void
entropy_array_shuffle(void *ary, size_t len, size_t elem_size)
{
	g_assert(ary != NULL);
	g_assert(size_is_non_negative(len));
	g_assert(size_is_positive(elem_size));

	if (len > RANDOM_SHUFFLE_MAX)
		s_carp("%s: cannot shuffle %zu items without bias", G_STRFUNC, len);

	shuffle_with((random_fn_t) entropy_rand31, ary, len, elem_size);
}
示例#11
0
/**
 * Collect entropy by randomly executing the callbacks given in the array.
 */
static void
entropy_array_cb_collect(SHA1Context *ctx, entropy_cb_t *ary, size_t len)
{
	size_t i;

	g_assert(ctx != NULL);
	g_assert(ary != NULL);
	g_assert(size_is_non_negative(len));

	entropy_array_shuffle(ary, len, sizeof ary[0]);

	for (i = 0; i < len; i++) {
		(*ary[i])(ctx);
	}
}
示例#12
0
/**
 * Replace value data in-place.
 *
 * @param db		the sdbm database
 * @param bval		start of big value in the page
 * @param data		the new value
 * @param len		length of data
 *
 * @return 0 if OK, -1 on error with errno set.
 */
int
big_replace(DBM *db, char *bval, const char *data, size_t len)
{
	size_t old_len = big_length(bval);

	g_assert(size_is_non_negative(len));
	g_assert(bigblocks(old_len) == bigblocks(len));
	g_assert(len <= MAX_INT_VAL(guint32));

	/*
	 * Write data on the same blocks as before, since we know it will fit.
	 */

	poke_be32(bval, (guint32) len);		/* First 4 bytes: real data length */

	return big_store(db, bigval_blocks(bval), data, len);
}
示例#13
0
/**
 * Write NUL-terminated string, up to `n' characters or the first seen NUL
 * in the buffer, whichever comes first.
 *
 * The string is written as: <ule64(length)><bytes>, no trailing NUL.
 */
void
pmsg_write_fixed_string(pmsg_t *mb, const char *str, size_t n)
{
	size_t len;

	g_assert(pmsg_is_writable(mb));	/* Not shared, or would corrupt data */
	g_assert(UNSIGNED(pmsg_available(mb)) >= n + 10);	/* Need ule64 length */
	g_assert_log(size_is_non_negative(n), "%s(): n=%zd", G_STRFUNC, n);

	len = strlen(str);
	len = MIN(n, len);
	pmsg_write_ule64(mb, (uint64) len);

	if (len != 0) {
		pmsg_write(mb, str, len);
	}
}
示例#14
0
/**
 * Write NUL-terminated string.
 *
 * If (size_t) -1 is given as length, then it is computed via strlen(), in
 * which case the string buffer must be NUL-terminated.  Otherwise, the value
 * is taken to be the pre-computed string length.
 *
 * The string is written as: <ule64(length)><bytes>, no trailing NUL.
 */
void
pmsg_write_string(pmsg_t *mb, const char *str, size_t length)
{
	size_t len;

	g_assert(pmsg_is_writable(mb));	/* Not shared, or would corrupt data */
	g_assert_log(size_is_non_negative(length) || (size_t) -1 == length,
		"%s(): length=%zd", G_STRFUNC, length);

	len = (size_t) -1 == length ? strlen(str) : length;

	g_assert(UNSIGNED(pmsg_available(mb)) >= len + 10);	/* Need ule64 length */

	pmsg_write_ule64(mb, (uint64) len);
	if (len != 0) {
		pmsg_write(mb, str, len);
	}
}
示例#15
0
/**
 * Copies up to ``*size'' bytes from current data block
 * (bh->b_data + bh->b_offset) to the buffer ``dest''.
 *
 * @param bh an initialized browse host context.
 * @param dest the destination buffer.
 * @param size must point to a ``size_t'' variable and initialized to the
 *			   number of bytes that ``dest'' can hold. It's value is
 *			   automagically decreased by the amount of bytes copied.
 * @return The amount of bytes copied. Use this to advance ``dest''.
 */
static inline size_t
browse_host_read_data(struct browse_host_upload *bh, char *dest, size_t *size)
{
	size_t len;

	g_assert(NULL != size);
	g_assert(size_is_non_negative(bh->b_offset));
	g_assert(bh->b_offset <= bh->b_size);
	g_assert(bh->b_data != NULL);
	g_assert(*size <= INT_MAX);

	len = bh->b_size - bh->b_offset;
	len = MIN(*size, len);
	memcpy(dest, &bh->b_data[bh->b_offset], len);
	bh->b_offset += len;
	*size -= len;

	return len;
}
示例#16
0
/**
 * Create a new formatting context for a header line.
 *
 * @param `field' is the header field name, without trailing ':'.
 *
 * @param `separator' is the optional default separator to emit between
 * the values added via header_fmd_append_value().  To supersede the
 * default separator, use header_fmd_append() and specify another separator
 * explicitly.  If set to NULL, there will be no default separator and
 * values will be simply concatenated together.  The value given must
 * NOT be freed before the header_fmt_end() call (usually it will just
 * be a static string).  Trailing spaces in the separator will be stripped
 * if it is emitted at the end of a line before a continuation.
 *
 * @param `len_hint' is the expected line size, for pre-sizing purposes.
 * (0 to guess).
 *
 * @param `max_size' is the maximum header size, including the final "\r\n"
 * and the trailing NUL.  If the initial field name is larger than the
 * configured maximum size, the header field will remain completely empty.
 *
 * @return pointer to the formatting object.
 */
header_fmt_t *
header_fmt_make(const char *field, const char *separator,
	size_t len_hint, size_t max_size)
{
	struct header_fmt *hf;

	g_assert(size_is_non_negative(len_hint));

	WALLOC(hf);
	hf->magic = HEADER_FMT_MAGIC;
	hf->header = str_new(len_hint ? len_hint : HEADER_FMT_DFLT_LEN);
	hf->maxlen = HEADER_FMT_LINE_LEN;
	hf->data_emitted = FALSE;
	hf->frozen = FALSE;
	hf->max_size = max_size;
	hf->sep = atom_str_get(separator ? separator : "");
	hf->seplen = strlen(hf->sep);
	hf->stripped_seplen = stripped_strlen(hf->sep, hf->seplen);
	str_cat(hf->header, field);
	STR_CAT(hf->header, ": ");

	hf->current_len = str_len(hf->header);

	/*
	 * If right from the start the header would be larger than the configured
	 * size, force it to stay empty.  That means, the final string returned
	 * will be "", the empty string.
	 */

	if (str_len(hf->header) + sizeof("\r\n") > hf->max_size) {
		hf->empty = TRUE;
		str_setlen(hf->header, 0);
	} else {
		hf->empty = FALSE;
	}

	header_fmt_check(hf);

	return hf;
}
示例#17
0
/**
 * Collect entropy by randomly feeding values from array.
 */
static void
entropy_array_data_collect(SHA1Context *ctx,
	enum entropy_data data, void *ary, size_t len, size_t elem_size)
{
	size_t i;
	void *p;

	g_assert(ctx != NULL);
	g_assert(ary != NULL);
	g_assert(size_is_non_negative(len));
	g_assert(size_is_positive(elem_size));

	entropy_array_shuffle(ary, len, elem_size);

	for (i = 0, p = ary; i < len; i++, p = ptr_add_offset(p, elem_size)) {
		switch (data) {
		case ENTROPY_ULONG:
			sha1_feed_ulong(ctx, *(unsigned long *) p);
			break;
		case ENTROPY_STRING:
			sha1_feed_string(ctx, *(char **) p);
			break;
		case ENTROPY_STAT:
			sha1_feed_stat(ctx, *(char **) p);
			break;
		case ENTROPY_FSTAT:
			sha1_feed_fstat(ctx, *(int *) p);
			break;
		case ENTROPY_DOUBLE:
			sha1_feed_double(ctx, *(double *) p);
			break;
		case ENTROPY_POINTER:
			sha1_feed_pointer(ctx, *(void **) p);
			break;
		}
	}
}
示例#18
0
/**
 * Pending data were all flushed.
 */
static void
deflate_flushed(txdrv_t *tx)
{
	struct attr *attr = tx->opaque;
	double flush = 0.0;

	g_assert(size_is_non_negative(attr->unflushed));

	attr->total_input += attr->unflushed;
	attr->total_output += attr->flushed;

	g_return_unless(attr->total_input != 0);

	attr->ratio = 1.0 - ((double) attr->total_output / attr->total_input);

	if (0 != attr->unflushed) {
		/*
		 * Fast EMA for compression ratio is computed for the last n=3 flushes,
		 * so the smoothing factor sm=2/(n+1) is 1/2.
		 */

		flush = 1.0 - ((double) attr->flushed / attr->unflushed);
		attr->ratio_ema += (flush / 2.0) - (attr->ratio_ema / 2.0);
	}

	if (tx_deflate_debugging(4)) {
		g_debug("TX %s: (%s) deflated %zu bytes into %zu "
			"(%.2f%%, EMA=%.2f%%, overall %.2f%%)",
			G_STRFUNC, gnet_host_to_string(&tx->host),
			attr->unflushed, attr->flushed,
			100 * flush, 100 * attr->ratio_ema, 100 * attr->ratio);
	}

	attr->unflushed = attr->flushed = 0;
	attr->flags &= ~DF_FLUSH;
}
示例#19
0
/**
 * Append data `str' to the header line, atomically.
 *
 * @param `hf' no brief description.
 * @param `str' no brief description.
 * @param `separator' is an optional separator string that will be emitted
 *         BEFORE outputting the data, and only when nothing has been emitted
 *         already.
 * @param `slen' is the separator length, 0 if empty.
 * @param `sslen' is the stripped separator length, (size_t)-1 if unknown yet.
 *
 * @return TRUE if we were able to fit the string, FALSE if it would have
 * resulted in the header being larger than the configured max size (the
 * header line is left in the state it was in upon entry, in that case).
 */
static bool
header_fmt_append_full(header_fmt_t *hf, const char *str,
	const char *separator, size_t slen, size_t sslen)
{
	size_t len, curlen;
	gsize gslen;
	bool success;

	header_fmt_check(hf);
	g_assert(size_is_non_negative(slen));
	g_assert((size_t)-1 == sslen || size_is_non_negative(sslen));

	if (hf->empty)
		return FALSE;

	gslen = str_len(hf->header);
	len = strlen(str);
	curlen = hf->current_len;
	g_assert(size_is_non_negative(curlen));

	g_assert(len <= INT_MAX);	/* Legacy bug */

	if (
		size_saturate_add(curlen, size_saturate_add(len, slen)) >
			UNSIGNED(hf->maxlen)
	) {
		/*
		 * Emit sperator, if any and data was already emitted.
		 */

		if (separator != NULL && hf->data_emitted) {
			sslen = (size_t)-1 != sslen ? sslen :
				stripped_strlen(separator, slen);
			str_cat_len(hf->header, separator, sslen);
		}

		STR_CAT(hf->header, "\r\n\t");			/* Includes continuation */
		curlen = 1;								/* One tab */
	} else if (hf->data_emitted) {
		str_cat(hf->header, separator);
		curlen += slen;
	}

	str_cat(hf->header, str);

	/*
	 * Check for overflows, undoing string changes if needed.
	 */

	if (str_len(hf->header) + sizeof("\r\n") > hf->max_size) {
		success = FALSE;
		str_setlen(hf->header, gslen);			/* Undo! */
	} else {
		success = TRUE;
		hf->data_emitted = TRUE;
		hf->current_len = curlen + len;
	}

	g_assert(str_len(hf->header) + sizeof("\r\n") <= hf->max_size);

	return success;
}
示例#20
0
/**
 * Create a security token from host address and port using specified key.
 *
 * Optionally, extra contextual data may be given (i.e. the token is not
 * only based on the address and port) to make the token more unique to
 * a specific context.
 *
 * @param stg		the security token generator
 * @param n			key index to use
 * @param tok		where security token is written
 * @param addr		address of the host for which we're generating a token
 * @param port		port of the host for which we're generating a token
 * @param data		optional contextual data
 * @param len		length of contextual data
 */
static void
sectoken_generate_n(sectoken_gen_t *stg, size_t n,
	sectoken_t *tok, host_addr_t addr, uint16 port,
	const void *data, size_t len)
{
	char block[8];
	char enc[8];
	char *p = block;

	sectoken_gen_check(stg);
	g_assert(tok != NULL);
	g_assert(size_is_non_negative(n));
	g_assert(n < stg->keycnt);
	g_assert((NULL != data) == (len != 0));

	switch (host_addr_net(addr)) {
	case NET_TYPE_IPV4:
		p = poke_be32(p, host_addr_ipv4(addr));
		break;
	case NET_TYPE_IPV6:
		{
			uint val;

			val = binary_hash(host_addr_ipv6(&addr), 16);
			p = poke_be32(p, val);
		}
		break;
	case NET_TYPE_LOCAL:
	case NET_TYPE_NONE:
		g_error("unexpected address for security token generation: %s",
			host_addr_to_string(addr));
	}

	p = poke_be16(p, port);
	p = poke_be16(p, 0);		/* Filler */

	g_assert(p == &block[8]);

	STATIC_ASSERT(sizeof(tok->v) == sizeof(uint32));
	STATIC_ASSERT(sizeof(block) == sizeof(enc));

	tea_encrypt(&stg->keys[n], enc, block, sizeof block);

	/*
	 * If they gave contextual data, encrypt them by block of 8 bytes,
	 * filling the last partial block with zeroes if needed.
	 */

	if (data != NULL) {
		const void *q = data;
		size_t remain = len;
		char denc[8];

		STATIC_ASSERT(sizeof(denc) == sizeof(enc));

		while (remain != 0) {
			size_t fill = MIN(remain, 8U);
			unsigned i;

			if (fill != 8U)
				ZERO(&block);

			memcpy(block, q, fill);
			remain -= fill;
			q = const_ptr_add_offset(q, fill);

			/*
			 * Encrypt block of contextual data (possibly filled with trailing
			 * zeroes) and merge back the result into the main encryption
			 * output with XOR.
			 */

			tea_encrypt(&stg->keys[n], denc, block, sizeof block);

			for (i = 0; i < sizeof denc; i++)
				enc[i] ^= denc[i];
		}
	}

	poke_be32(tok->v, tea_squeeze(enc, sizeof enc));
}
示例#21
0
/**
 * Needs brief description here.
 *
 * Substitutes variables from string:
 *
 * - The leading "~" is replaced by the home directory.
 * - Variables like "$PATH" or "${PATH}" are replaced by their value, as
 *   fetched from the environment, or the empty string if not found.
 *
 * If given a NULL input, we return NULL.
 *
 * @return string constant, which is not meant to be freed until exit time.
 */
const char *
eval_subst(const char *str)
{
	char buf[MAX_STRING];
	char *end = &buf[sizeof(buf)];
	char *p;
	size_t len;
	char c;

	if (str == NULL)
		return NULL;

	len = g_strlcpy(buf, str, sizeof buf);
	if (len >= sizeof buf) {
		g_warning("%s(): string too large for substitution (%zu bytes)",
			G_STRFUNC, len);
		return constant_str(str);
	}


	if (common_dbg > 3)
		g_debug("%s: on entry: \"%s\"", G_STRFUNC, buf);

	for (p = buf, c = *p++; c; c = *p++) {
		const char *val = NULL;
		char *start = p - 1;

		switch (c) {
		case '~':
			if (start == buf && ('\0' == buf[1] || '/' == buf[1])) {
				/* Leading ~ only */
				val = gethomedir();
				g_assert(val);
				memmove(start, &start[1], len - (start - buf));
				len--;

				g_assert(size_is_non_negative(len));
			}
			break;
		case '$':
			{
				const char *after;

				val = get_variable(p, &after);
				g_assert(val);
				memmove(start, after, len + 1 - (after - buf));
				len -= after - start;		/* Also removing leading '$' */

				g_assert(size_is_non_negative(len));
			}
			break;
		}

		if (val != NULL) {
			char *next;

			next = insert_value(val, start, start - buf, len, sizeof buf - 1);
			len += next - start;
			p = next;

			g_assert(len < sizeof buf);
			g_assert(p < end);
		}

		g_assert(p <= &buf[len]);
	}

	if (common_dbg > 3)
		g_debug("%s: on exit: \"%s\"", G_STRFUNC, buf);

	g_assert(len == strlen(buf));

	return constant_str(buf);
}