int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len)
{
	uint8_t ch = 0;
	size_t sl = 0;
	const char* s = str;
	/* skip length byte */
	if(*len < 1)
		return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;

	/* read characters */
	while(sldns_parse_char(&ch, &s)) {
		if(sl >= 255)
			return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str);
		if(*len < sl+2)
			return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
				s-str);
		rd[++sl] = ch;
	}
	if(!s)
		return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE;
	rd[0] = (uint8_t)sl;
	*len = sl+1;
	return LDNS_WIREPARSE_ERR_OK;
}


int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len)
{
	size_t slen = strlen(str);
	const char* ptr;

	if (slen > 255)
		return LDNS_WIREPARSE_ERR_SYNTAX_TAG;
	if(*len < slen+1)
		return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
	for (ptr = str; *ptr; ptr++) {
		if(!isalnum((unsigned char)*ptr))
			return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str);
	}
	rd[0] = (uint8_t)slen;
	memmove(rd+1, str, slen);
	*len = slen+1;
	return LDNS_WIREPARSE_ERR_OK;
}


int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len)
{
	char* end;
	uint16_t r = (uint16_t)strtol((char*)str, &end, 10);
	if(*end != 0)
		return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str);
	if(*len < 2)
		return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
	sldns_write_uint16(rd, r);
	*len = 2;
	return LDNS_WIREPARSE_ERR_OK;
}


int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len)
{
	const char *delim = "\n\t ";
	char token[64]; /* for a type name */
	size_t type_count = 0;
	int block;
	size_t used = 0;
	uint16_t maxtype = 0;
	uint8_t typebits[8192]; /* 65536 bits */
	uint8_t window_in_use[256];

	/* string in buffer */
	sldns_buffer strbuf;
	sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str));

	/* parse the types */
	memset(typebits, 0, sizeof(typebits));
	memset(window_in_use, 0, sizeof(window_in_use));
	while(sldns_buffer_remaining(&strbuf) > 0 &&
		sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) {
		uint16_t t = sldns_get_rr_type_by_name(token);
		if(token[0] == 0)
			continue;
		if(t == 0 && strcmp(token, "TYPE0") != 0)
			return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE,
				sldns_buffer_position(&strbuf));
		typebits[t/8] |= (0x80>>(t%8));
		window_in_use[t/256] = 1;
		type_count++;
		if(t > maxtype) maxtype = t;
	}

	/* empty NSEC bitmap */
	if(type_count == 0) {
		*len = 0;
		return LDNS_WIREPARSE_ERR_OK;
	}

	/* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap},
	 * block is 0-255 upper octet of types, length if 0-32. */
	for(block = 0; block <= (int)maxtype/256; block++) {
		int i, blocklen = 0;
		if(!window_in_use[block])
			continue;
		for(i=0; i<32; i++) {
			if(typebits[block*32+i] != 0)
				blocklen = i+1;
		}
		if(blocklen == 0)
			continue; /* empty window should have been !in_use */
		if(used+blocklen+2 > *len)
			return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
		rd[used+0] = (uint8_t)block;
		rd[used+1] = (uint8_t)blocklen;
		for(i=0; i<blocklen; i++) {
			rd[used+2+i] = typebits[block*32+i];
		}
		used += blocklen+2;
	}
	*len = used;
	return LDNS_WIREPARSE_ERR_OK;
}


uint8_t* sldns_str2wire_dname(const char* str, size_t* len)
{
	uint8_t dname[LDNS_MAX_DOMAINLEN+1];
	*len = sizeof(dname);
	if(sldns_str2wire_dname_buf(str, dname, len) == 0) {
		uint8_t* r;
		if(*len > sizeof(dname)) return NULL;
		r = (uint8_t*)malloc(*len);
		if(r) return memcpy(r, dname, *len);
	}
	*len = 0;
	return NULL;
}


loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
{
	uint32_t meters = 0, cm = 0, val;
	while (isblank((unsigned char)*my_str)) {
		my_str++;
	}
	meters = (uint32_t)strtol(my_str, &my_str, 10);
	if (*my_str == '.') {
		my_str++;
		cm = (uint32_t)strtol(my_str, &my_str, 10);
	}
	if (meters >= 1) {
		*e = 2;
		val = meters;
	} else	{
		*e = 0;
		val = cm;
	}
	while(val >= 10) {
		(*e)++;
		val /= 10;
	}
	*m = (uint8_t)val;

	if (*e > 9)
		return 0;
	if (*my_str == 'm' || *my_str == 'M') {
		my_str++;
	}
	*endstr = my_str;
	return 1;
}


uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len)
{
	if(len < dname_len+4)
		return 0;
	return sldns_read_uint16(rr+dname_len+2);
}


int sldns_str2wire_tsigerror_buf(const char* str, uint8_t* rd, size_t* len)
{
	sldns_lookup_table *lt = sldns_lookup_by_name(sldns_tsig_errors, str);
	if(*len < 2)
		return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
	if(lt) {
		sldns_write_uint16(rd, (uint16_t)lt->id);
		*len = 2;
	} else {
		/* try as-is (a number) */
		return sldns_str2wire_int16_buf(str, rd, len);
	}
	return LDNS_WIREPARSE_ERR_OK;
}


uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len)
{
	if(len < dname_len+10)
		return NULL;
	return rr+dname_len+8;
}


int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len)
{
#ifdef AF_INET6
	uint8_t address[LDNS_IP6ADDRLEN + 1];
	if(inet_pton(AF_INET6, (char*)str, address) != 1)
		return LDNS_WIREPARSE_ERR_SYNTAX_IP6;
	if(*len < LDNS_IP6ADDRLEN)
		return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
	memmove(rd, address, LDNS_IP6ADDRLEN);
	*len = LDNS_IP6ADDRLEN;
	return LDNS_WIREPARSE_ERR_OK;
#else
	return LDNS_WIREPARSE_ERR_NOT_IMPL;
#endif
}


cmsUInt32Number CMSEXPORT cmsGetPostScriptCRD(cmsContext ContextID,
                              cmsHPROFILE hProfile,
                              cmsUInt32Number Intent, cmsUInt32Number dwFlags,
                              void* Buffer, cmsUInt32Number dwBufferLen)
{
    cmsIOHANDLER* mem;
    cmsUInt32Number dwBytesUsed;

    // Set up the serialization engine
    if (Buffer == NULL)
        mem = cmsOpenIOhandlerFromNULL(ContextID);
    else
        mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w");

    if (!mem) return 0;

    dwBytesUsed =  cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CRD, hProfile, Intent, dwFlags, mem);

    // Get rid of memory stream
    cmsCloseIOhandler(mem);

    return dwBytesUsed;
}


smtp_decode_status_code (const gchar *in,
                         gsize len)
{
	guchar *inptr, *outptr;
	const guchar *inend;
	gchar *outbuf;

	outbuf = (gchar *) g_malloc (len + 1);
	outptr = (guchar *) outbuf;

	inptr = (guchar *) in;
	inend = inptr + len;
	while (inptr < inend) {
		if (*inptr == '+') {
			if (isxdigit (inptr[1]) && isxdigit (inptr[2])) {
				*outptr++ = HEXVAL (inptr[1]) * 16 + HEXVAL (inptr[2]);
				inptr += 3;
			} else
				*outptr++ = *inptr++;
		} else
			*outptr++ = *inptr++;
	}

	*outptr = '\0';

	return outbuf;
}


stream_flush (CamelStream *stream,
              GCancellable *cancellable,
              GError **error)
{
	/* nop? */
	return 0;
}


camel_pop3_store_expunge (CamelPOP3Store *store,
                          GCancellable *cancellable,
                          GError **error)
{
	CamelPOP3Command *pc;
	CamelPOP3Engine *pop3_engine;
	CamelServiceConnectionStatus status;

	status = camel_service_get_connection_status (CAMEL_SERVICE (store));

	if (status != CAMEL_SERVICE_CONNECTED) {
		g_set_error (
			error, CAMEL_SERVICE_ERROR,
			CAMEL_SERVICE_ERROR_UNAVAILABLE,
			_("You must be working online to complete this operation"));
		return FALSE;
	}

	pop3_engine = camel_pop3_store_ref_engine (store);

	if (!camel_pop3_engine_busy_lock (pop3_engine, cancellable, error)) {
		g_clear_object (&pop3_engine);
		return FALSE;
	}

	pc = camel_pop3_engine_command_new (
		pop3_engine, 0, NULL, NULL, cancellable, error, "QUIT\r\n");

	while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0)
		;

	camel_pop3_engine_command_free (pop3_engine, pc);

	camel_pop3_engine_busy_unlock (pop3_engine);
	g_clear_object (&pop3_engine);

	return TRUE;
}


smtp_data (CamelSmtpTransport *transport,
	   CamelStreamBuffer *istream,
	   CamelStream *ostream,
           CamelMimeMessage *message,
           GCancellable *cancellable,
           GError **error)
{
	CamelNameValueArray *previous_headers;
	const gchar *header_name = NULL, *header_value = NULL;
	CamelBestencEncoding enctype = CAMEL_BESTENC_8BIT;
	CamelStream *filtered_stream;
	gchar *cmdbuf, *respbuf = NULL;
	CamelMimeFilter *filter;
	gsize bytes_written;
	gint ret;
	guint ii;

	/* If the server doesn't support 8BITMIME, set our required encoding to be 7bit */
	if (!(transport->flags & CAMEL_SMTP_TRANSPORT_8BITMIME))
		enctype = CAMEL_BESTENC_7BIT;

	/* FIXME: should we get the best charset too?? */
	/* Changes the encoding of all mime parts to fit within our required
	 * encoding type and also force any text parts with long lines (longer
	 * than 998 octets) to wrap by QP or base64 encoding them. */
	camel_mime_message_set_best_encoding (
		message, CAMEL_BESTENC_GET_ENCODING, enctype);

	cmdbuf = g_strdup ("DATA\r\n");

	d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));

	if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
		g_free (cmdbuf);
		g_prefix_error (error, _("DATA command failed: "));
		camel_service_disconnect_sync (
			CAMEL_SERVICE (transport),
			FALSE, cancellable, NULL);
		return FALSE;
	}
	g_free (cmdbuf);

	respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
	d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
	if (respbuf == NULL) {
		g_prefix_error (error, _("DATA command failed: "));
		camel_service_disconnect_sync (
			CAMEL_SERVICE (transport),
			FALSE, cancellable, NULL);
		return FALSE;
	}
	if (strncmp (respbuf, "354", 3) != 0) {
		/* We should have gotten instructions on how to use the DATA
		 * command: 354 Enter mail, end with "." on a line by itself
		 */
		smtp_set_error (transport, istream, respbuf, cancellable, error);
		g_prefix_error (error, _("DATA command failed: "));
		g_free (respbuf);
		return FALSE;
	}

	g_free (respbuf);
	respbuf = NULL;

	/* unlink the bcc headers and keep a copy of them */
	previous_headers = camel_medium_dup_headers (CAMEL_MEDIUM (message));
	camel_medium_remove_header (CAMEL_MEDIUM (message), "Bcc");

	/* find out how large the message is... */
	bytes_written = camel_data_wrapper_calculate_size_sync (CAMEL_DATA_WRAPPER (message), NULL, NULL);

	/* Set the upload timeout to an equal of 512 bytes per second */
	smtp_maybe_update_socket_timeout (ostream, bytes_written / 512);

	filtered_stream = camel_stream_filter_new (ostream);

	/* setup progress reporting for message sending... */
	filter = camel_mime_filter_progress_new (cancellable, bytes_written);
	camel_stream_filter_add (
		CAMEL_STREAM_FILTER (filtered_stream), filter);
	g_object_unref (filter);

	/* setup LF->CRLF conversion */
	filter = camel_mime_filter_crlf_new (
		CAMEL_MIME_FILTER_CRLF_ENCODE,
		CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS);
	camel_stream_filter_add (
		CAMEL_STREAM_FILTER (filtered_stream), filter);
	g_object_unref (filter);

	/* write the message */
	ret = camel_data_wrapper_write_to_stream_sync (
		CAMEL_DATA_WRAPPER (message),
		filtered_stream, cancellable, error);

	if (camel_debug ("smtp")) {
		CamelStream *mem_stream, *sec_filtered_stream;
		GError *local_error = NULL;

		mem_stream = camel_stream_mem_new ();
		sec_filtered_stream = camel_stream_filter_new (mem_stream);

		filter = camel_mime_filter_crlf_new (
			CAMEL_MIME_FILTER_CRLF_ENCODE,
			CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS);
		camel_stream_filter_add (CAMEL_STREAM_FILTER (sec_filtered_stream), filter);
		g_object_unref (filter);

		if (camel_data_wrapper_write_to_stream_sync (CAMEL_DATA_WRAPPER (message), sec_filtered_stream, cancellable, &local_error) == -1) {
			printf ("[SMTP] Failed to write message to memory stream: %s\n", local_error ? local_error->message : "Unknown error");
		} else {
			GByteArray *bytes;

			camel_stream_flush (sec_filtered_stream, cancellable, NULL);

			bytes = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (mem_stream));

			if (!bytes) {
				printf ("[SMTP] Failed to get filtered stream bytes\n");
			} else {
				printf ("[SMTP] sent data (re-encoded):\n%.*s\n", (gint) bytes->len, (const gchar *) bytes->data);
			}
		}

		g_clear_object (&sec_filtered_stream);
		g_clear_object (&mem_stream);
		g_clear_error (&local_error);
	}

	/* restore the bcc headers */
	for (ii = 0; camel_name_value_array_get (previous_headers, ii, &header_name, &header_value); ii++) {
		if (!g_ascii_strcasecmp (header_name, "Bcc")) {
			camel_medium_add_header (CAMEL_MEDIUM (message), header_name, header_value);
		}
	}

	camel_name_value_array_free (previous_headers);

	if (ret == -1) {
		g_prefix_error (error, _("DATA command failed: "));

		g_object_unref (filtered_stream);

		camel_service_disconnect_sync (
			CAMEL_SERVICE (transport),
			FALSE, cancellable, NULL);
		return FALSE;
	}

	camel_stream_flush (filtered_stream, cancellable, NULL);
	g_object_unref (filtered_stream);

	/* terminate the message body */

	d (fprintf (stderr, "[SMTP] sending: \\r\\n.\\r\\n\n"));

	if (camel_stream_write (ostream, "\r\n.\r\n", 5, cancellable, error) == -1) {
		g_prefix_error (error, _("DATA command failed: "));
		camel_service_disconnect_sync (
			CAMEL_SERVICE (transport),
			FALSE, cancellable, NULL);
		return FALSE;
	}

	do {
		/* Check for "250 Sender OK..." */
		g_free (respbuf);
		respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
		d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
		if (respbuf == NULL) {
			g_prefix_error (error, _("DATA command failed: "));
			camel_service_disconnect_sync (
				CAMEL_SERVICE (transport),
				FALSE, cancellable, NULL);
			return FALSE;
		}
		if (strncmp (respbuf, "250", 3) != 0) {
			smtp_set_error (transport, istream, respbuf, cancellable, error);
			g_prefix_error (error, _("DATA command failed: "));
			g_free (respbuf);
			return FALSE;
		}
	} while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */
	g_free (respbuf);

	return TRUE;
}


camel_stream_buffer_truncate (CamelStreamBuffer *sbf)
{
	g_return_if_fail (CAMEL_IS_STREAM_BUFFER (sbf));

	sbf->priv->ptr = sbf->priv->buf;
	sbf->priv->end = sbf->priv->buf;
	sbf->priv->ptr[0] = '\0';
}


stream_read (CamelStream *stream,
             gchar *buffer,
             gsize n,
             GCancellable *cancellable,
             GError **error)
{
	CamelPOP3Stream *is = (CamelPOP3Stream *) stream;
	gchar *o, *oe;
	guchar *p, *e, c;
	gint state;

	if (is->mode != CAMEL_POP3_STREAM_DATA || n == 0)
		return 0;

	o = buffer;
	oe = buffer + n;
	state = is->state;

	/* Need to copy/strip '.'s and whatnot */
	p = is->ptr;
	e = is->end;

	switch (state) {
	state_0:
	case 0:		/* start of line, always read at least 3 chars */
		while (e - p < 3) {
			is->ptr = p;
			if (stream_fill (is, cancellable, error) == -1)
				return -1;
			p = is->ptr;
			e = is->end;
		}
		if (p[0] == '.') {
			if (p[1] == '\r' && p[2] == '\n') {
				is->ptr = p + 3;
				is->mode = CAMEL_POP3_STREAM_EOD;
				is->state = 0;
				return o - buffer;
			}
			p++;
		}
		state = 1;
		/* FALLS THROUGH */
	case 1:		/* looking for next sol */
		while (o < oe) {
			c = *p++;
			if (c == '\n') {
				/* end of input sentinal check */
				if (p > e) {
					is->ptr = e;
					if (stream_fill (is, cancellable, error) == -1)
						return -1;
					p = is->ptr;
					e = is->end;
				} else {
					*o++ = '\n';
					state = 0;
					goto state_0;
				}
			} else if (c != '\r') {
				*o++ = c;
			}
		}
		break;
	}

	is->ptr = p;
	is->state = state;

	return o - buffer;
}


camel_stream_buffer_gets (CamelStreamBuffer *sbf,
                          gchar *buf,
                          guint max,
                          GCancellable *cancellable,
                          GError **error)
{
	register gchar *outptr, *inptr, *inend, c, *outend;
	gint bytes_read;
	GError *local_error = NULL;

	outptr = buf;
	inptr = (gchar *) sbf->priv->ptr;
	inend = (gchar *) sbf->priv->end;
	outend = buf + max-1;	/* room for NUL */

	do {
		while (inptr < inend && outptr < outend) {
			c = *inptr++;
			*outptr++ = c;
			if (c == '\n') {
				*outptr = 0;
				sbf->priv->ptr = (guchar *) inptr;
				return outptr - buf;
			}
		}
		if (outptr == outend)
			break;

		bytes_read = camel_stream_read (
			sbf->priv->stream, (gchar *) sbf->priv->buf,
			sbf->priv->size, cancellable, &local_error);
		if (bytes_read == -1) {
			if (buf == outptr) {
				if (local_error)
					g_propagate_error (error, local_error);
				return -1;
			} else
				bytes_read = 0;
		}
		sbf->priv->ptr = sbf->priv->buf;
		sbf->priv->end = sbf->priv->buf + bytes_read;
		inptr = (gchar *) sbf->priv->ptr;
		inend = (gchar *) sbf->priv->end;
	} while (bytes_read > 0);

	sbf->priv->ptr = (guchar *) inptr;
	*outptr = 0;

	g_clear_error (&local_error);

	return (gint)(outptr - buf);
}


int fileblobAddData(fileblob *fb, const unsigned char *data, size_t len)
{
    if (len == 0)
        return 0;

    assert(data != NULL);

    if (fb->fp) {
#if defined(MAX_SCAN_SIZE) && (MAX_SCAN_SIZE > 0)
        const cli_ctx *ctx = fb->ctx;

        if (fb->isInfected) /* pretend all was written */
            return 0;
        if (ctx) {
            int do_scan = 1;

            if (cli_checklimits("fileblobAddData", ctx, fb->bytes_scanned, 0, 0) != CL_CLEAN)
                do_scan = 0;

            if (fb->bytes_scanned > MAX_SCAN_SIZE)
                do_scan = 0;
            if (do_scan) {
                if (ctx->scanned)
                    *ctx->scanned += (unsigned long)len / CL_COUNT_PRECISION;
                fb->bytes_scanned += (unsigned long)len;

                if ((len > 5) && cli_updatelimits(ctx, len) == CL_CLEAN && (cli_scanbuff(data, (unsigned int)len, 0, ctx->virname, ctx->engine, CL_TYPE_BINARY_DATA, NULL) == CL_VIRUS)) {
                    cli_dbgmsg("fileblobAddData: found %s\n", cli_get_last_virus_str(ctx->virname));
                    fb->isInfected = 1;
                }
            }
        }
#endif

        if (fwrite(data, len, 1, fb->fp) != 1) {
            cli_errmsg("fileblobAddData: Can't write %lu bytes to temporary file %s\n",
                       (unsigned long)len, fb->b.name);
            return -1;
        }
        fb->isNotEmpty = 1;
        return 0;
    }
    return blobAddData(&(fb->b), data, len);
}


const char* getMagicHeaderName(uint32_t magic)
{
    const char* magicName = NULL;

    switch (magic) {
        case EGG_HEADER_MAGIC:
            magicName = "EGG_HEADER_MAGIC";
            break;
        case FILE_HEADER_MAGIC:
            magicName = "FILE_HEADER_MAGIC";
            break;
        case BLOCK_HEADER_MAGIC:
            magicName = "BLOCK_HEADER_MAGIC";
            break;
        case ENCRYPT_HEADER_MAGIC:
            magicName = "ENCRYPT_HEADER_MAGIC";
            break;
        case WINDOWS_INFO_MAGIC:
            magicName = "WINDOWS_INFO_MAGIC";
            break;
        case POSIX_INFO_MAGIC:
            magicName = "POSIX_INFO_MAGIC";
            break;
        case DUMMY_HEADER_MAGIC:
            magicName = "DUMMY_HEADER_MAGIC";
            break;
        case FILENAME_HEADER_MAGIC:
            magicName = "FILENAME_HEADER_MAGIC";
            break;
        case COMMENT_HEADER_MAGIC:
            magicName = "COMMENT_HEADER_MAGIC";
            break;
        case SPLIT_COMPRESSION_MAGIC:
            magicName = "SPLIT_COMPRESSION_MAGIC";
            break;
        case SOLID_COMPRESSION_MAGIC:
            magicName = "SOLID_COMPRESSION_MAGIC";
            break;
        default:
            magicName = "<unknown header magic>";
    }

    return magicName;
}


blobToMem(blob *b)
{
    void *ret;

    assert(b != NULL);
#ifdef CL_DEBUG
    assert(b->magic == BLOBCLASS);
#endif

    if (!b->isClosed)
        blobClose(b);
    if (b->name)
        free(b->name);
#ifdef CL_DEBUG
    b->magic = INVALIDCLASS;
#endif
    ret = (void *)b->data;
    free(b);

    return ret;
}


int fileblobScanAndDestroy(fileblob *fb)
{
    switch (fileblobScan(fb)) {
        case CL_VIRUS:
            fileblobDestructiveDestroy(fb);
            return CL_VIRUS;
        case CL_BREAK:
            fileblobDestructiveDestroy(fb);
            return CL_CLEAN;
        default:
            fileblobDestroy(fb);
            return CL_CLEAN;
    }
}


cl_error_t cli_egg_peek_file_header(void* hArchive, cl_egg_metadata* file_metadata)
{
    cl_error_t status  = CL_EPARSE;
    egg_handle* handle = NULL;
    egg_file* currFile = NULL;

    if (!hArchive || !file_metadata) {
        cli_errmsg("cli_egg_peek_file_header: Invalid args!\n");
        return CL_EARG;
    }

    handle = (egg_handle*)hArchive;
    if (CL_SUCCESS != EGG_VALIDATE_HANDLE(handle)) {
        cli_errmsg("cli_egg_peek_file_header: Invalid handle values!\n");
        status = CL_EARG;
        goto done;
    }

    memset(file_metadata, 0, sizeof(cl_egg_metadata));

    if (handle->fileExtractionIndex >= handle->nFiles) {
        status = CL_BREAK;
        goto done;
    }

    currFile = handle->files[handle->fileExtractionIndex];
    if (NULL == currFile) {
        cli_errmsg("cli_egg_peek_file_header: invalid egg_file pointer!\n");
        goto done;
    }

    if (NULL == currFile->file) {
        cli_errmsg("cli_egg_peek_file_header: egg_file is missing file header!\n");
        goto done;
    }

    if (NULL == currFile->filename.name_utf8) {
        cli_errmsg("cli_egg_extract_file: egg_file is missing filename!\n");
        goto done;
    }

    if (handle->bSolid) {
        /*
         * TODO: Add support for extracting files from solid archives.
         *
         * See the comments in cli_egg_extract_file() for more details.
         */
        file_metadata->pack_size   = 0;
        file_metadata->unpack_size = currFile->file->file_length;
    } else {
        uint64_t i = 0;
        if (!currFile->blocks) {
            cli_dbgmsg("cli_egg_peek_file_header: Empty file!\n");
        }
        for (i = 0; i < currFile->nBlocks; i++) {
            egg_block* currBlock = currFile->blocks[i];

            if (!currBlock->blockHeader) {
                cli_errmsg("cli_egg_peek_file_header: egg_block missing block_header!\n");
                goto done;
            }
            file_metadata->pack_size += currBlock->blockHeader->compress_size;
            file_metadata->unpack_size += currBlock->blockHeader->uncompress_size;
        }
        if (file_metadata->unpack_size != currFile->file->file_length) {
            cli_warnmsg("cli_egg_peek_file_header: sum of block uncompress_size's does not match listed file_length!\n");
        }
    }

    file_metadata->filename = strdup(currFile->filename.name_utf8);

    if (NULL != currFile->encrypt)
        file_metadata->encrypted = 1;

    if (currFile->posixFileInformation && currFile->posixFileInformation->mode & POSIX_INFO_MODE_DIRECTORY)
        file_metadata->is_dir = 1;
    else if (currFile->windowsFileInformation && currFile->windowsFileInformation->attribute & WINDOWS_INFO_ATTRIBUTE_DIRECTORY)
        file_metadata->is_dir = 1;

    status = CL_SUCCESS;
done:
    return status;
}


static UINT gdi_CacheToSurface(RdpgfxClientContext* context,
                               const RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface)
{
	UINT status = ERROR_INTERNAL_ERROR;
	UINT16 index;
	gdiGfxSurface* surface;
	gdiGfxCacheEntry* cacheEntry;
	RECTANGLE_16 invalidRect;
	rdpGdi* gdi = (rdpGdi*)context->custom;
	EnterCriticalSection(&context->mux);
	surface = (gdiGfxSurface*)context->GetSurfaceData(context, cacheToSurface->surfaceId);
	cacheEntry = (gdiGfxCacheEntry*)context->GetCacheSlotData(context, cacheToSurface->cacheSlot);

	if (!surface || !cacheEntry)
		goto fail;

	for (index = 0; index < cacheToSurface->destPtsCount; index++)
	{
		const RDPGFX_POINT16* destPt = &cacheToSurface->destPts[index];
		const RECTANGLE_16 rect = { destPt->x, destPt->y, destPt->x + cacheEntry->width,
			                        destPt->y + cacheEntry->height };

		if (!is_rect_valid(&rect, surface->width, surface->height))
			goto fail;

		if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x,
		                        destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data,
		                        cacheEntry->format, cacheEntry->scanline, 0, 0, NULL,
		                        FREERDP_FLIP_NONE))
			goto fail;

		invalidRect.left = destPt->x;
		invalidRect.top = destPt->y;
		invalidRect.right = destPt->x + cacheEntry->width;
		invalidRect.bottom = destPt->y + cacheEntry->height;
		region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
		status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context,
		                      surface->surfaceId, 1, &invalidRect);

		if (status != CHANNEL_RC_OK)
			goto fail;
	}

	LeaveCriticalSection(&context->mux);

	if (!gdi->inGfxFrame)
	{
		status = CHANNEL_RC_NOT_INITIALIZED;
		IFCALLRET(context->UpdateSurfaces, status, context);
	}
	else
		status = CHANNEL_RC_OK;

	return status;
fail:
	LeaveCriticalSection(&context->mux);
	return status;
}


void gdi_graphics_pipeline_uninit(rdpGdi* gdi, RdpgfxClientContext* gfx)
{
	if (gdi)
		gdi->gfx = NULL;

	if (!gfx)
		return;

	gfx->custom = NULL;
	DeleteCriticalSection(&gfx->mux);
	PROFILER_PRINT_HEADER
	PROFILER_PRINT(gfx->SurfaceProfiler)
	PROFILER_PRINT_FOOTER
	PROFILER_FREE(gfx->SurfaceProfiler)
}


static UINT gdi_EndFrame(RdpgfxClientContext* context, const RDPGFX_END_FRAME_PDU* endFrame)
{
	UINT status = CHANNEL_RC_NOT_INITIALIZED;
	rdpGdi* gdi = (rdpGdi*)context->custom;
	IFCALLRET(context->UpdateSurfaces, status, context);
	gdi->inGfxFrame = FALSE;
	return status;
}


static UINT gdi_ResetGraphics(RdpgfxClientContext* context,
                              const RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
{
	UINT rc = ERROR_INTERNAL_ERROR;
	UINT32 index;
	UINT16 count;
	UINT32 DesktopWidth;
	UINT32 DesktopHeight;
	gdiGfxSurface* surface;
	UINT16* pSurfaceIds = NULL;
	rdpGdi* gdi = (rdpGdi*)context->custom;
	rdpUpdate* update = gdi->context->update;
	rdpSettings* settings = gdi->context->settings;
	EnterCriticalSection(&context->mux);
	DesktopWidth = resetGraphics->width;
	DesktopHeight = resetGraphics->height;

	if ((DesktopWidth != settings->DesktopWidth) || (DesktopHeight != settings->DesktopHeight))
	{
		settings->DesktopWidth = DesktopWidth;
		settings->DesktopHeight = DesktopHeight;

		if (update)
			update->DesktopResize(gdi->context);
	}

	context->GetSurfaceIds(context, &pSurfaceIds, &count);

	for (index = 0; index < count; index++)
	{
		surface = (gdiGfxSurface*)context->GetSurfaceData(context, pSurfaceIds[index]);

		if (!surface || !surface->outputMapped)
			continue;

		region16_clear(&surface->invalidRegion);
	}

	free(pSurfaceIds);

	if (!freerdp_client_codecs_reset(gdi->context->codecs, FREERDP_CODEC_ALL, gdi->width,
	                                 gdi->height))
		goto fail;

	rc = CHANNEL_RC_OK;
fail:
	LeaveCriticalSection(&context->mux);
	return rc;
}


UINT rdpgfx_write_rect16(wStream* s, const RECTANGLE_16* rect16)
{
	Stream_Write_UINT16(s, rect16->left);   /* left (2 bytes) */
	Stream_Write_UINT16(s, rect16->top);    /* top (2 bytes) */
	Stream_Write_UINT16(s, rect16->right);  /* right (2 bytes) */
	Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
	return CHANNEL_RC_OK;
}


UINT rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32)
{
	if (Stream_GetRemainingLength(s) < 4)
	{
		WLog_ERR(TAG, "not enough data!");
		return ERROR_INVALID_DATA;
	}

	Stream_Read_UINT8(s, color32->B);  /* B (1 byte) */
	Stream_Read_UINT8(s, color32->G);  /* G (1 byte) */
	Stream_Read_UINT8(s, color32->R);  /* R (1 byte) */
	Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */
	return CHANNEL_RC_OK;
}


void cdev_put(struct cdev *p)
{
	if (p) {
		struct module *owner = p->owner;
		kobject_put(&p->kobj);
		module_put(owner);
	}
}


static int exact_lock(dev_t dev, void *data)
{
	struct cdev *p = data;
	return cdev_get(p) ? 0 : -1;
}


int __register_chrdev(unsigned int major, unsigned int baseminor,
		      unsigned int count, const char *name,
		      const struct file_operations *fops)
{
	struct char_device_struct *cd;
	struct cdev *cdev;
	int err = -ENOMEM;

	cd = __register_chrdev_region(major, baseminor, count, name);
	if (IS_ERR(cd))
		return PTR_ERR(cd);

	cdev = cdev_alloc();
	if (!cdev)
		goto out2;

	cdev->owner = fops->owner;
	cdev->ops = fops;
	kobject_set_name(&cdev->kobj, "%s", name);

	err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
	if (err)
		goto out;

	cd->cdev = cdev;

	return major ? 0 : cd->major;
out:
	kobject_put(&cdev->kobj);
out2:
	kfree(__unregister_chrdev_region(cd->major, baseminor, count));
	return err;
}


void __init chrdev_init(void)
{
	cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
}


static inline int major_to_index(unsigned major)
{
	return major % CHRDEV_MAJOR_HASH_SIZE;
}


LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions,
  uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx)
{
  void *cf;
  lua_State *L;
  if (version != 1)
    return _URC_FATAL_PHASE1_ERROR;
  UNUSED(uexclass);
  cf = (void *)_Unwind_GetCFA(ctx);
  L = cframe_L(cf);
  if ((actions & _UA_SEARCH_PHASE)) {
#if LJ_UNWIND_EXT
    if (err_unwind(L, cf, 0) == NULL)
      return _URC_CONTINUE_UNWIND;
#endif
    if (!LJ_UEXCLASS_CHECK(uexclass)) {
      setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
    }
    return _URC_HANDLER_FOUND;
  }
  if ((actions & _UA_CLEANUP_PHASE)) {
    int errcode;
    if (LJ_UEXCLASS_CHECK(uexclass)) {
      errcode = LJ_UEXCLASS_ERRCODE(uexclass);
    } else {
      if ((actions & _UA_HANDLER_FRAME))
	_Unwind_DeleteException(uex);
      errcode = LUA_ERRRUN;
    }
#if LJ_UNWIND_EXT
    cf = err_unwind(L, cf, errcode);
    if ((actions & _UA_FORCE_UNWIND)) {
      return _URC_CONTINUE_UNWIND;
    } else if (cf) {
      _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode);
      _Unwind_SetIP(ctx, (uintptr_t)(cframe_unwind_ff(cf) ?
				     lj_vm_unwind_ff_eh :
				     lj_vm_unwind_c_eh));
      return _URC_INSTALL_CONTEXT;
    }
#if LJ_TARGET_X86ORX64
    else if ((actions & _UA_HANDLER_FRAME)) {
      /* Workaround for ancient libgcc bug. Still present in RHEL 5.5. :-/
      ** Real fix: http://gcc.gnu.org/viewcvs/trunk/gcc/unwind-dw2.c?r1=121165&r2=124837&pathrev=153877&diff_format=h
      */
      _Unwind_SetGR(ctx, LJ_TARGET_EHRETREG, errcode);
      _Unwind_SetIP(ctx, (uintptr_t)lj_vm_unwind_rethrow);
      return _URC_INSTALL_CONTEXT;
    }
#endif
#else
    /* This is not the proper way to escape from the unwinder. We get away with
    ** it on non-x64 because the interpreter restores all callee-saved regs.
    */
    lj_err_throw(L, errcode);
#endif
  }
  return _URC_CONTINUE_UNWIND;
}


LJ_NOINLINE GCstr *lj_err_str(lua_State *L, ErrMsg em)
{
  return lj_str_newz(L, err2msg(em));
}


static gboolean session_write_msg_cb(SockInfo *source, GIOCondition condition,
				     gpointer data)
{
	Session *session = SESSION(data);
	gint ret;

	cm_return_val_if_fail(condition == G_IO_OUT, FALSE);
	cm_return_val_if_fail(session->write_buf != NULL, FALSE);
	cm_return_val_if_fail(session->write_buf_p != NULL, FALSE);
	cm_return_val_if_fail(session->write_buf_len > 0, FALSE);

	ret = session_write_buf(session);

	if (ret < 0) {
		session->state = SESSION_ERROR;
		return FALSE;
	} else if (ret > 0)
		return TRUE;

	if (session->io_tag > 0) {
		g_source_remove(session->io_tag);
		session->io_tag = 0;
	}

	session_recv_msg(session);

	return FALSE;
}


void session_set_timeout(Session *session, guint interval)
{
	if (session->timeout_tag > 0)
		g_source_remove(session->timeout_tag);

	session->timeout_interval = interval;
	if (interval > 0) {
		if (interval % 1000 == 0)
			session->timeout_tag =
				g_timeout_add_seconds(interval/1000, session_timeout_cb, session);
		else
			session->timeout_tag =
				g_timeout_add(interval, session_timeout_cb, session);
	} else
		session->timeout_tag = 0;
}


void session_set_send_data_notify(Session *session, SendDataNotify notify_func,
				  gpointer data)
{
	session->send_data_notify = notify_func;
	session->send_data_notify_data = data;
}


static gint session_close(Session *session)
{
	cm_return_val_if_fail(session != NULL, -1);

#ifdef G_OS_UNIX
	if (session->conn_id > 0) {
		sock_connect_async_cancel(session->conn_id);
		session->conn_id = 0;
		debug_print("session (%p): connection cancelled\n", session);
	}
#endif

	session_set_timeout(session, 0);

	if (session->io_tag > 0) {
		g_source_remove(session->io_tag);
		session->io_tag = 0;
	}

	if (session->sock) {
		sock_close(session->sock, TRUE);
		session->sock = NULL;
		session->state = SESSION_DISCONNECTED;
		debug_print("session (%p): closed\n", session);
	}

	return 0;
}


camel_imapx_server_class_init (CamelIMAPXServerClass *class)
{
	GObjectClass *object_class;

	object_class = G_OBJECT_CLASS (class);
	object_class->set_property = imapx_server_set_property;
	object_class->get_property = imapx_server_get_property;
	object_class->finalize = imapx_server_finalize;
	object_class->dispose = imapx_server_dispose;
	object_class->constructed = imapx_server_constructed;

	g_object_class_install_property (
		object_class,
		PROP_STORE,
		g_param_spec_object (
			"store",
			"Store",
			"IMAPX store for this server",
			CAMEL_TYPE_IMAPX_STORE,
			G_PARAM_READWRITE |
			G_PARAM_CONSTRUCT_ONLY |
			G_PARAM_STATIC_STRINGS));

	signals[REFRESH_MAILBOX] = g_signal_new (
		"refresh-mailbox",
		G_OBJECT_CLASS_TYPE (class),
		G_SIGNAL_RUN_LAST,
		G_STRUCT_OFFSET (CamelIMAPXServerClass, refresh_mailbox),
		NULL, NULL, NULL,
		G_TYPE_NONE, 1,
		CAMEL_TYPE_IMAPX_MAILBOX);
}


XkbSendIndicatorMap(ClientPtr client,
                    XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
{
    int length;
    CARD8 *map;
    register int i;
    register unsigned bit;

    if (rep->length > 0) {
        CARD8 *to;

        to = map = xallocarray(rep->length, 4);
        if (map) {
            xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;

            length = rep->length * 4;

            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
                if (rep->which & bit) {
                    wire->flags = indicators->maps[i].flags;
                    wire->whichGroups = indicators->maps[i].which_groups;
                    wire->groups = indicators->maps[i].groups;
                    wire->whichMods = indicators->maps[i].which_mods;
                    wire->mods = indicators->maps[i].mods.mask;
                    wire->realMods = indicators->maps[i].mods.real_mods;
                    wire->virtualMods = indicators->maps[i].mods.vmods;
                    wire->ctrls = indicators->maps[i].ctrls;
                    if (client->swapped) {
                        swaps(&wire->virtualMods);
                        swapl(&wire->ctrls);
                    }
                    wire++;
                }
            }
            to = (CARD8 *) wire;
            if ((to - map) != length) {
                client->errorValue = _XkbErrCode2(0xff, length);
                free(map);
                return BadLength;
            }
        }
        else
            return BadAlloc;
    }
    else
        map = NULL;
    if (client->swapped) {
        swaps(&rep->sequenceNumber);
        swapl(&rep->length);
        swapl(&rep->which);
        swapl(&rep->realIndicators);
    }
    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
    if (map) {
        WriteToClient(client, length, map);
        free((char *) map);
    }
    return Success;
}


XkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
{
    register int i;
    xkbDoodadWireDesc *doodadWire;

    for (i = 0; i < num_doodads; i++, doodad++) {
        doodadWire = (xkbDoodadWireDesc *) wire;
        wire = (char *) &doodadWire[1];
        memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
        doodadWire->any.name = doodad->any.name;
        doodadWire->any.type = doodad->any.type;
        doodadWire->any.priority = doodad->any.priority;
        doodadWire->any.top = doodad->any.top;
        doodadWire->any.left = doodad->any.left;
        if (swap) {
            swapl(&doodadWire->any.name);
            swaps(&doodadWire->any.top);
            swaps(&doodadWire->any.left);
        }
        switch (doodad->any.type) {
        case XkbOutlineDoodad:
        case XkbSolidDoodad:
            doodadWire->shape.angle = doodad->shape.angle;
            doodadWire->shape.colorNdx = doodad->shape.color_ndx;
            doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
            if (swap) {
                swaps(&doodadWire->shape.angle);
            }
            break;
        case XkbTextDoodad:
            doodadWire->text.angle = doodad->text.angle;
            doodadWire->text.width = doodad->text.width;
            doodadWire->text.height = doodad->text.height;
            doodadWire->text.colorNdx = doodad->text.color_ndx;
            if (swap) {
                swaps(&doodadWire->text.angle);
                swaps(&doodadWire->text.width);
                swaps(&doodadWire->text.height);
            }
            wire = XkbWriteCountedString(wire, doodad->text.text, swap);
            wire = XkbWriteCountedString(wire, doodad->text.font, swap);
            break;
        case XkbIndicatorDoodad:
            doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
            doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
            doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
            break;
        case XkbLogoDoodad:
            doodadWire->logo.angle = doodad->logo.angle;
            doodadWire->logo.colorNdx = doodad->logo.color_ndx;
            doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
            wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
            break;
        default:
            ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
                   doodad->any.type);
            ErrorF("[xkb] Ignored\n");
            break;
        }
    }
    return wire;
}


CheckVirtualMods(XkbDescRec * xkb,
                 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
{
    register CARD8 *wire = *wireRtrn;
    register unsigned i, nMods, bit;

    if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
        return 1;
    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
        if (req->virtualMods & bit)
            nMods++;
    }
    *wireRtrn = (wire + XkbPaddedSize(nMods));
    return 1;
}


XkbSizeModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep)
{
    unsigned i, len, nRtrn;

    if (((rep->present & XkbModifierMapMask) == 0) || (rep->nModMapKeys < 1) ||
        (!xkb) || (!xkb->map) || (!xkb->map->modmap)) {
        rep->present &= ~XkbModifierMapMask;
        rep->firstModMapKey = rep->nModMapKeys = 0;
        rep->totalModMapKeys = 0;
        return 0;
    }
    for (nRtrn = i = 0; i < rep->nModMapKeys; i++) {
        if (xkb->map->modmap[i + rep->firstModMapKey] != 0)
            nRtrn++;
    }
    rep->totalModMapKeys = nRtrn;
    len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero modmap component */
    return len;
}


XkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
                                xkbGetCompatMapReply * rep)
{
    unsigned size, nGroups;

    nGroups = 0;
    if (rep->groups != 0) {
        register int i, bit;

        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
            if (rep->groups & bit)
                nGroups++;
        }
    }
    size = nGroups * SIZEOF(xkbModsWireDesc);
    size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
    rep->length = size / 4;
    return Success;
}


_CheckSetShapes(XkbGeometryPtr geom,
                xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
{
    register int i;
    char *wire;

    wire = *wire_inout;
    if (req->nShapes < 1) {
        client->errorValue = _XkbErrCode2(0x06, req->nShapes);
        return BadValue;
    }
    else {
        xkbShapeWireDesc *shapeWire;
        XkbShapePtr shape;
        register int o;

        shapeWire = (xkbShapeWireDesc *) wire;
        for (i = 0; i < req->nShapes; i++) {
            xkbOutlineWireDesc *olWire;
            XkbOutlinePtr ol;

            shape =
                XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
            if (!shape)
                return BadAlloc;
            olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
            for (o = 0; o < shapeWire->nOutlines; o++) {
                register int p;
                XkbPointPtr pt;
                xkbPointWireDesc *ptWire;

                ol = XkbAddGeomOutline(shape, olWire->nPoints);
                if (!ol)
                    return BadAlloc;
                ol->corner_radius = olWire->cornerRadius;
                ptWire = (xkbPointWireDesc *) &olWire[1];
                for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
                    pt->x = ptWire[p].x;
                    pt->y = ptWire[p].y;
                    if (client->swapped) {
                        swaps(&pt->x);
                        swaps(&pt->y);
                    }
                }
                ol->num_points = olWire->nPoints;
                olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
            }
            if (shapeWire->primaryNdx != XkbNoShape)
                shape->primary = &shape->outlines[shapeWire->primaryNdx];
            if (shapeWire->approxNdx != XkbNoShape)
                shape->approx = &shape->outlines[shapeWire->approxNdx];
            shapeWire = (xkbShapeWireDesc *) olWire;
        }
        wire = (char *) shapeWire;
    }
    if (geom->num_shapes != req->nShapes) {
        client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
        return BadMatch;
    }

    *wire_inout = wire;
    return Success;
}


ComputeDeviceLedInfoSize(DeviceIntPtr dev,
                         unsigned int what, XkbSrvLedInfoPtr sli)
{
    int nNames, nMaps;
    register unsigned n, bit;

    if (sli == NULL)
        return 0;
    nNames = nMaps = 0;
    if ((what & XkbXI_IndicatorNamesMask) == 0)
        sli->namesPresent = 0;
    if ((what & XkbXI_IndicatorMapsMask) == 0)
        sli->mapsPresent = 0;

    for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
        if (sli->names && sli->names[n] != None) {
            sli->namesPresent |= bit;
            nNames++;
        }
        if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
            sli->mapsPresent |= bit;
            nMaps++;
        }
    }
    return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
}


ProcXkbGetIndicatorState(ClientPtr client)
{
    xkbGetIndicatorStateReply rep;
    XkbSrvLedInfoPtr sli;
    DeviceIntPtr dev;

    REQUEST(xkbGetIndicatorStateReq);
    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);

    if (!(client->xkbClientFlags & _XkbClientInitialized))
        return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);

    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
                            XkbXI_IndicatorStateMask);
    if (!sli)
        return BadAlloc;

    rep = (xkbGetIndicatorStateReply) {
        .type = X_Reply,
        .deviceID = dev->id,
        .sequenceNumber = client->sequence,
        .length = 0,
        .state = sli->effectiveState
    };

    if (client->swapped) {
        swaps(&rep.sequenceNumber);
        swapl(&rep.state);
    }
    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
    return Success;
}


add_master(ClientPtr client, xXIAddMasterInfo * c, int flags[MAXDEVICES])
{
    DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
    char *name;
    int rc;

    name = calloc(c->name_len + 1, sizeof(char));
    if (name == NULL) {
        rc = BadAlloc;
        goto unwind;
    }
    strncpy(name, (char *) &c[1], c->name_len);

    rc = AllocDevicePair(client, name, &ptr, &keybd,
                         CorePointerProc, CoreKeyboardProc, TRUE);
    if (rc != Success)
        goto unwind;

    if (!c->send_core)
        ptr->coreEvents = keybd->coreEvents = FALSE;

    /* Allocate virtual slave devices for xtest events */
    rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd);
    if (rc != Success) {
        DeleteInputDeviceRequest(ptr);
        DeleteInputDeviceRequest(keybd);
        goto unwind;
    }

    ActivateDevice(ptr, FALSE);
    ActivateDevice(keybd, FALSE);
    flags[ptr->id] |= XIMasterAdded;
    flags[keybd->id] |= XIMasterAdded;

    ActivateDevice(XTestptr, FALSE);
    ActivateDevice(XTestkeybd, FALSE);
    flags[XTestptr->id] |= XISlaveAdded;
    flags[XTestkeybd->id] |= XISlaveAdded;

    if (c->enable) {
        EnableDevice(ptr, FALSE);
        EnableDevice(keybd, FALSE);
        flags[ptr->id] |= XIDeviceEnabled;
        flags[keybd->id] |= XIDeviceEnabled;

        EnableDevice(XTestptr, FALSE);
        EnableDevice(XTestkeybd, FALSE);
        flags[XTestptr->id] |= XIDeviceEnabled;
        flags[XTestkeybd->id] |= XIDeviceEnabled;
    }

    /* Attach the XTest virtual devices to the newly
       created master device */
    AttachDevice(NULL, XTestptr, ptr);
    AttachDevice(NULL, XTestkeybd, keybd);
    flags[XTestptr->id] |= XISlaveAttached;
    flags[XTestkeybd->id] |= XISlaveAttached;

    for (int i = 0; i < currentMaxClients; i++)
        XIBarrierNewMasterDevice(clients[i], ptr->id);

 unwind:
    free(name);
    return rc;
}


_XimEncodeStatusValue(
    Xic			 ic,
    XIMResourceList	 res,
    XIMArg		*p)
{
    if (res->xrm_name == XrmStringToQuark(XNStdColormap)) {
	XStandardColormap	*colormap_ret = NULL;
	int			 count;

	if (!(XGetRGBColormaps(ic->core.im->core.display,
				ic->core.focus_window, &colormap_ret,
				&count, (Atom)p->value)))
	    return False;

	XFree(colormap_ret);
    } else if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
	int		  list_ret;
	XFontStruct	**struct_list;
	char		**name_list;
	char		 *tmp;
	int		  len;
	register int	  i;

	if (!p->value)
	    return False;

	Xfree(ic->private.proto.status_font);

	list_ret = XFontsOfFontSet((XFontSet)p->value,
						 &struct_list, &name_list);
	for (i = 0, len = 0; i < list_ret; i++) {
	     len += (strlen(name_list[i]) + sizeof(char));
	}
	if (!(tmp = Xmalloc(len+1))) {
	    ic->private.proto.status_font = NULL;
	    return False;
	}

	tmp[0] = '\0';
	for(i = 0; i < list_ret; i++) {
	    strcat(tmp, name_list[i]);
	    strcat(tmp, ",");
	}
	tmp[len - 1] = 0;
	ic->private.proto.status_font        = tmp;
	ic->private.proto.status_font_length = len - 1;
    }
    return True;
}


_XimMakeICAttrIDList(
    Xic			 ic,
    XIMResourceList	 res_list,
    unsigned int	 res_num,
    XIMArg		*arg,
    CARD16		*buf,
    INT16		*len,
    unsigned long	 mode)
{
    register XIMArg	*p;
    XIMResourceList	 res;
    int			 check;
    XrmQuark		 pre_quark;
    XrmQuark		 sts_quark;
    char		*name;
    INT16		 new_len;

    *len = 0;
    if (!arg)
	return (char *)NULL;

    pre_quark = XrmStringToQuark(XNPreeditAttributes);
    sts_quark = XrmStringToQuark(XNStatusAttributes);

    for (p = arg; p && p->name; p++) {
	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
	    if (_XimCheckInnerICAttributes(ic, p, mode))
		continue;
	    *len = -1;
	    return p->name;
	}

	check = _XimCheckICMode(res, mode);
	if(check == XIM_CHECK_INVALID)
	    continue;
	else if(check == XIM_CHECK_ERROR) {
	    *len = -1;
	    return p->name;
	}

	*buf = res->id;
	*len += sizeof(CARD16);
	buf++;
	if (res->resource_size == XimType_NEST) {
	    if (res->xrm_name == pre_quark) {
		if ((name = _XimMakeICAttrIDList(ic, res_list, res_num,
				(XIMArg *)p->value, buf, &new_len,
				(mode | XIM_PREEDIT_ATTR)))) {
		    if (new_len < 0) *len = -1;
		    else *len += new_len;
		    return name;
		}
		*len += new_len;
		buf = (CARD16 *)((char *)buf + new_len);
	    } else if (res->xrm_name == sts_quark) {
		if ((name = _XimMakeICAttrIDList(ic, res_list, res_num,
				(XIMArg *)p->value, buf, &new_len,
				(mode | XIM_STATUS_ATTR)))) {
		    if (new_len < 0) *len = -1;
		    else *len += new_len;
		    return name;
		}
		*len += new_len;
		buf = (CARD16 *)((char *)buf + new_len);
	    }

	    if (!(res = _XimGetNestedListSeparator(res_list, res_num))) {
		p++;
		if (p) {
		    *len = -1;
		    return p->name;
		}
		else {
		    return (char *)NULL;
		}
	    }
	    *buf = res->id;
	    *len += sizeof(CARD16);
	    buf++;
	}
    }
    return (char *)NULL;
}


_XimCheckIMQuarkList(
    XrmQuark		*quark_list,
    int			 num_quark,
    XrmQuark		 quark)
{
    register int	 i;

    for (i = 0; i < num_quark; i++) {
	if (quark_list[i] == quark) {
	    return True;
	}
    }
    return False;
}


_XimConnection(
    Xim		 im)
{
    CARD32	 buf32[BUFSIZE/4];
    CARD8	*buf = (CARD8 *)buf32;
    CARD8	*buf_b = &buf[XIM_HEADER_SIZE];
    CARD16	*buf_s = (CARD16 *)((XPointer)buf_b);
    INT16	 len;
    CARD8	 num;
    CARD32	 reply32[BUFSIZE/4];
    char	*reply = (char *)reply32;
    XPointer	 preply;
    int		 buf_size;
    int		 ret_code;
    CARD8	 major_opcode;
    int		 wait_mode;
    int		 ret;

    if(!(_XimConnect(im)))	/* Transport Connect */
	return False;

    if(!_XimDispatchInit(im))
	return False;

    _XimRegProtoIntrCallback(im, XIM_ERROR, 0, _XimErrorCallback, (XPointer)im);

    if(!_XimGetAuthProtocolNames(im, &buf_s[4], &num, &len))
	return False;

    im->private.proto.protocol_major_version = PROTOCOLMAJORVERSION;
    im->private.proto.protocol_minor_version = PROTOCOLMINORVERSION;

    buf_b[0] = _XimGetMyEndian();
    buf_b[1] = 0;
    buf_s[1] = PROTOCOLMAJORVERSION;
    buf_s[2] = PROTOCOLMINORVERSION;
    buf_s[3] = num;
    len  += sizeof(CARD8)
          + sizeof(CARD8)
          + sizeof(CARD16)
          + sizeof(CARD16)
          + sizeof(CARD16);

    major_opcode = XIM_CONNECT;
    wait_mode = (IS_USE_AUTHORIZATION_FUNC(im)) ? CLIENT_WAIT1 : CLIENT_WAIT2;

    for(;;) {
	_XimSetHeader((XPointer)buf, major_opcode, 0, &len);
	if (!(_XimWrite(im, len, (XPointer)buf)))
	    return False;
	_XimFlush(im);
	buf_size = BUFSIZE;
	ret_code = _XimRead(im, &len, reply, buf_size, _XimAllRecv, 0);
	if(ret_code == XIM_TRUE) {
	    preply = reply;
	} else if(ret_code == XIM_OVERFLOW) {
	    if(len <= 0) {
		preply = reply;
	    } else {
		buf_size = len;
		preply = Xmalloc(buf_size);
		ret_code = _XimRead(im, &len, preply, buf_size, _XimAllRecv, 0);
		if(ret_code != XIM_TRUE) {
		    Xfree(preply);
		    return False;
		}
	    }
	} else
	    return False;

	major_opcode = *((CARD8 *)preply);
	buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);

	if (wait_mode == CLIENT_WAIT1) {
	    if (major_opcode == XIM_AUTH_REQUIRED) {
		ret = _XimClientAuthCheck(im, (XPointer)buf_s);
		if(reply != preply)
		    Xfree(preply);
		if (ret == NO_MORE_AUTH) {
		    if (!(_XimSetAuthReplyData(im,
				(XPointer)&buf[XIM_HEADER_SIZE], &len))) {
			_XimAuthNG(im);
			return False;
		    }
		    major_opcode = XIM_AUTH_REPLY;
		    wait_mode = CLIENT_WAIT2;
		} else if (ret == GOOD_AUTH) {
		    if (!(_XimSetAuthNextData(im,
				(XPointer)&buf[XIM_HEADER_SIZE], &len))) {
			_XimAuthNG(im);
			return False;
		    }
		    major_opcode = XIM_AUTH_NEXT;
		} else {	/* BAD_AUTH */
		    _XimAuthNG(im);
		    return False;
		}
	    } else {
		if(reply != preply)
		    Xfree(preply);
		_XimAuthNG(im);
		return False;
	    }
	} else {	/* CLIENT_WAIT2 */
	    if (major_opcode == XIM_CONNECT_REPLY) {
		break;
	    } else if (major_opcode == XIM_AUTH_SETUP) {
		if (!(_XimCheckAuthSetupData(im, (XPointer)buf_s))) {
		    _XimAuthNG(im);
		    return False;
		}
		if(reply != preply)
		    Xfree(preply);
		if (!(_XimSetAuthRequiredData(im,
				(XPointer)&buf[XIM_HEADER_SIZE], &len))) {
		    _XimAuthNG(im);
		    return False;
		}
		major_opcode = XIM_AUTH_REQUIRED;
	    } else if (major_opcode == XIM_AUTH_NEXT) {
		if (!(_XimCheckAuthNextData(im, (XPointer)buf_s))) {
		    _XimAuthNG(im);
		    return False;
		}
		if(reply != preply)
		    Xfree(preply);
		if (!(_XimSetAuthRequiredData(im,
				(XPointer)&buf[XIM_HEADER_SIZE], &len))) {
		    _XimAuthNG(im);
		    return False;
		}
		major_opcode = XIM_AUTH_REQUIRED;
	    } else if (major_opcode == XIM_AUTH_NG) {
		if(reply != preply)
		    Xfree(preply);
		return False;
	    } else {
		_XimAuthNG(im);
		if(reply != preply)
		    Xfree(preply);
		return False;
	    }
	}
    }

    if (!( buf_s[0] == im->private.proto.protocol_major_version
        && buf_s[1] == im->private.proto.protocol_minor_version)) {
	if(reply != preply)
	    Xfree(preply);
	return False;
    }
    if(reply != preply)
	Xfree(preply);
    MARK_SERVER_CONNECTED(im);

    _XimRegProtoIntrCallback(im, XIM_REGISTER_TRIGGERKEYS, 0,
				 _XimRegisterTriggerKeysCallback, (XPointer)im);
    return True;
}


_XimSaveICValues(ic, arg)
    Xic			 ic;
    XIMArg		*arg;
{
    register XIMArg	*p;
    register int	 n;
    XrmQuark		*quark_list;
    XrmQuark		*tmp;
    XrmQuark		 quark;
    int			 num_quark;
    XrmQuark		 pre_quark;
    XrmQuark		 sts_quark;
    XrmQuark		 separator;
    int			 idx;

    pre_quark = XrmStringToQuark(XNPreeditAttributes);
    sts_quark = XrmStringToQuark(XNStatusAttributes);
    separator = XrmStringToQuark(XNSeparatorofNestedList);

    if (quark_list = ic->private.proto.saved_icvalues) {
	num_quark = ic->private.proto.num_saved_icvalues;
	for (p = arg; p && p->name; p++) {
	    quark = XrmStringToQuark(p->name);
	    if ((quark == pre_quark) || (quark == sts_quark)) {
	        if (!_XimCheckICQuarkList(quark_list, num_quark, quark, &idx)) {
		    register XIMArg	*pp;
		    int			 nn;
		    XrmQuark		*q_list;

		    for (pp = (XIMArg *)p->value, nn = 0;
						pp && pp->name; pp++, nn++);
	            if (!(tmp = Xrealloc(quark_list,
				(sizeof(XrmQuark) * (num_quark + nn + 2))))) {
		        ic->private.proto.saved_icvalues = quark_list;
		        ic->private.proto.num_saved_icvalues = num_quark;
		        return False;
	            }
	            quark_list = tmp;
		    q_list = &quark_list[num_quark];
	            num_quark += nn + 2;
		    *q_list++ = quark;
		    for (pp = (XIMArg *)p->value;
					pp && pp->name; pp++, quark_list++) {
			*q_list = XrmStringToQuark(pp->name);
		    }
		    *q_list = separator;
		} else {
		    if (!_XimCheckNestedQuarkList(&quark_list, idx + 1,
				&num_quark, (XIMArg *)p->value, separator)) {
		        ic->private.proto.saved_icvalues = quark_list;
		        ic->private.proto.num_saved_icvalues = num_quark;
		        return False;
		    }
		}
	    } else {
	        if (_XimCheckICQuarkList(quark_list, num_quark, quark, &idx)) {
		    continue;
	        }
	        if (!(tmp = Xrealloc(quark_list,
				(sizeof(XrmQuark) * (num_quark + 1))))) {
		    ic->private.proto.saved_icvalues = quark_list;
		    ic->private.proto.num_saved_icvalues = num_quark;
		    return False;
	        }
	        quark_list = tmp;
	        quark_list[num_quark] = quark;
	        num_quark++;
	    }
	}
	ic->private.proto.saved_icvalues = quark_list;
	ic->private.proto.num_saved_icvalues = num_quark;
	return True;
    }

    for (p = arg, n = 0; p && p->name; p++, n++) {
	if ((!strcmp(p->name, XNPreeditAttributes))
	 || (!strcmp(p->name, XNStatusAttributes))) {
	    register XIMArg	*pp;
	    int			 nn;

	    for (pp = (XIMArg *)p->value, nn = 0; pp && pp->name; pp++, nn++);
	    n += nn + 1;
	}
    }

    if (!(quark_list = Xmalloc(sizeof(XrmQuark) * n))) {
	return False;
    }

    ic->private.proto.saved_icvalues = quark_list;
    ic->private.proto.num_saved_icvalues = n;
    for (p = arg; p && p->name; p++, quark_list++) {
	*quark_list = XrmStringToQuark(p->name);
	if ((*quark_list == pre_quark) || (*quark_list == sts_quark)) {
	    register XIMArg	*pp;

	    quark_list++;
	    for (pp = (XIMArg *)p->value; pp && pp->name; pp++, quark_list++) {
		*quark_list = XrmStringToQuark(pp->name);
	    }
	    *quark_list = separator;
	}
    }
    return True;
}


_XimDelayModeCreateIC(
    Xic			 ic,
    XIMArg		*values,
    XIMResourceList	 res,
    unsigned int	 num)
{
    Xim			 im = (Xim)ic->core.im;
    XimDefICValues	 ic_values;
    int			 len;
    XIMStyle		 input_style;

    bzero((char *)&ic_values, sizeof(XimDefICValues));
    _XimGetCurrentICValues(ic, &ic_values);
    if (!(_XimGetInputStyle(values, &input_style)))
	return False;

    _XimSetICMode(res, num, input_style);

    if (_XimSetICValueData(ic, (XPointer)&ic_values, res, num,
					values, XIM_CREATEIC, False)) {
	return False;
    }
    _XimSetCurrentICValues(ic, &ic_values);
    if (!_XimSetICDefaults(ic, (XPointer)&ic_values,
					XIM_SETICDEFAULTS, res, num)) {
	return False;
    }
    ic_values.filter_events = KeyPressMask;
    _XimSetCurrentICValues(ic, &ic_values);
    _XimRegisterFilter(ic);

    return True;
}


_XimDelayModeSetICValues(ic, arg)
    Xic			 ic;
    XIMArg		*arg;
{
    XimDefICValues	 ic_values;
    char		*name;

    _XimGetCurrentICValues(ic, &ic_values);
    name = _XimSetICValueData(ic, (XPointer)&ic_values,
			ic->private.proto.ic_resources,
			ic->private.proto.ic_num_resources,
			arg, XIM_SETICVALUES, False);
    _XimSetCurrentICValues(ic, &ic_values);
    return name;
}


_XimSetAuthReplyData(
    Xim		 im,
    XPointer	 buf,
    INT16	*len)
{
    /*
     * Not yet
     */
    *len = 0;
    return True;
}


_XimReconnectModeCreateIC(ic)
    Xic			 ic;
{
    Xim			 im = (Xim)ic->core.im;
    int			 len;
    XIMStyle		 input_style = ic->core.input_style;
    XIMResourceList	 res;
    unsigned int	 num;

    num = im->core.ic_num_resources;
    len = sizeof(XIMResource) * num;
    if (!(res = Xmalloc(len)))
	return False;
    (void)memcpy((char *)res, (char *)im->core.ic_resources, len);
    ic->private.proto.ic_resources     = res;
    ic->private.proto.ic_num_resources = num;

    _XimSetICMode(res, num, input_style);

    ic->core.filter_events = KeyPressMask;

    return True;
}


_XimProtoOpenIM(
    Xim		 im)
{
    _XimInitialResourceInfo();

    im->methods = &im_methods;

#ifdef XIM_CONNECTABLE
    _XimSetProtoResource(im);
#endif /* XIM_CONNECTABLE */

    if (_XimPreConnect(im)) {
	if (_XimConnection(im) && _XimOpen(im) && _XimEncodingNegotiation(im)) {
	    _XimRegisterServerFilter(im);
	    return True;
	}
	_XimShutdown(im);
#ifdef XIM_CONNECTABLE
    } else if (IS_DELAYBINDABLE(im)) {
	if (_XimDelayModeSetAttr(im))
	    return True;
#endif /* XIM_CONNECTABLE */
    }
    _XimProtoIMFree(im);
    return False;
}


_XimCheckNestedQuarkList(quark_list, idx, num_quark, arg, separator)
    XrmQuark		**quark_list;
    int			  idx;
    int			 *num_quark;
    XIMArg		 *arg;
    XrmQuark		  separator;
{
    XrmQuark		 *q_list = *quark_list;
    int			  n_quark = *num_quark;
    register XIMArg	 *p;
    XrmQuark		  quark;
    XrmQuark		 *tmp;
    register int	  i;

    for (p = arg; p && p->name; p++) {
	quark = XrmStringToQuark(p->name);
	if (_XimCheckNestQuarkList(&q_list[idx], n_quark - idx,
							quark, separator)) {
	    continue;
	}
	if (!(tmp = Xmalloc((sizeof(XrmQuark) * (n_quark + 1))))) {
	    *quark_list = q_list;
	    *num_quark = n_quark;
	    return False;
	}
	n_quark++;
	for (i = 0; i < idx; i++) {
	    tmp[i] = q_list[i];
	}
	tmp[i] = quark;
	for (i = idx  + 1; i < n_quark; i++) {
	    tmp[i] = q_list[i - 1];
	}
	q_list = tmp;
    }
    *quark_list = q_list;
    *num_quark = n_quark;
    return True;
}


_XimProtoGetIMValues(
    XIM			 xim,
    XIMArg		*arg)
{
    Xim			 im = (Xim)xim;
    register XIMArg	*p;
    register int	 n;
    CARD8		*buf;
    CARD16		*buf_s;
    INT16		 len;
    CARD32		 reply32[BUFSIZE/4];
    char		*reply = (char *)reply32;
    XPointer		 preply = NULL;
    int			 buf_size;
    int			 ret_code;
    char		*makeid_name;
    char		*decode_name;
    CARD16		*data = NULL;
    INT16		 data_len = 0;

#ifndef XIM_CONNECTABLE
    if (!IS_SERVER_CONNECTED(im))
	return arg->name;
#else
    if (!IS_SERVER_CONNECTED(im)) {
	if (IS_CONNECTABLE(im)) {
	    if (!_XimConnectServer(im)) {
	        return _XimDelayModeGetIMValues(im, arg);
	    }
        } else {
	    return arg->name;
        }
    }
#endif /* XIM_CONNECTABLE */

    for (n = 0, p = arg; p->name; p++)
	n++;

    if (!n)
	return (char *)NULL;

    buf_size =  sizeof(CARD16) * n;
    buf_size += XIM_HEADER_SIZE
	     + sizeof(CARD16)
	     + sizeof(INT16)
	     + XIM_PAD(buf_size);

    if (!(buf = Xcalloc(buf_size, 1)))
	return arg->name;
    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];

    makeid_name = _XimMakeIMAttrIDList(im, im->core.im_resources,
				im->core.im_num_resources, arg,
				&buf_s[2], &len, XIM_GETIMVALUES);

    if (len) {
	buf_s[0] = im->private.proto.imid;	/* imid */
	buf_s[1] = len;				/* length of im-attr-id */
	XIM_SET_PAD(&buf_s[2], len);		/* pad */
	len += sizeof(CARD16)			/* sizeof imid */
	     + sizeof(INT16);			/* sizeof length of attr */

	_XimSetHeader((XPointer)buf, XIM_GET_IM_VALUES, 0, &len);
	if (!(_XimWrite(im, len, (XPointer)buf))) {
	    Xfree(buf);
	    return arg->name;
	}
	_XimFlush(im);
	Xfree(buf);
    	buf_size = BUFSIZE;
    	ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
    						_XimGetIMValuesCheck, 0);
	if(ret_code == XIM_TRUE) {
	    preply = reply;
	} else if(ret_code == XIM_OVERFLOW) {
	    if(len <= 0) {
		preply = reply;
	    } else {
		buf_size = len;
		preply = Xmalloc(buf_size);
		ret_code = _XimRead(im, &len, preply, buf_size,
						_XimGetIMValuesCheck, 0);
		if(ret_code != XIM_TRUE) {
		    Xfree(preply);
		    return arg->name;
		}
	    }
	} else
	    return arg->name;
	buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
	if (*((CARD8 *)preply) == XIM_ERROR) {
	    _XimProcError(im, 0, (XPointer)&buf_s[3]);
	    if(reply != preply)
		Xfree(preply);
	    return arg->name;
	}
	data = &buf_s[2];
	data_len = buf_s[1];
    }
    decode_name = _XimDecodeIMATTRIBUTE(im, im->core.im_resources,
			im->core.im_num_resources, data, data_len,
			arg, XIM_GETIMVALUES);
    if (reply != preply)
	Xfree(preply);

    if (decode_name)
	return decode_name;
    else
	return makeid_name;
}


_XimSendSavedIMValues(
    Xim			 im)
{
    XimDefIMValues	 im_values;
    INT16		 len;
    CARD16		*buf_s;
    char		*tmp;
    CARD32		 tmp_buf32[BUFSIZE/4];
    char		*tmp_buf = (char *)tmp_buf32;
    char		*buf;
    int			 buf_size;
    char		*data;
    int			 data_len;
    int			 ret_len;
    int			 total;
    int			 idx;
    CARD32		 reply32[BUFSIZE/4];
    char		*reply = (char *)reply32;
    XPointer		 preply;
    int			 ret_code;

    _XimGetCurrentIMValues(im, &im_values);
    memset(tmp_buf, 0, sizeof(tmp_buf32));
    buf = tmp_buf;
    buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16);
    data_len = BUFSIZE - buf_size;
    total = 0;
    idx = 0;
    for (;;) {
	data = &buf[buf_size];
	if (!_XimEncodeSavedIMATTRIBUTE(im, im->core.im_resources,
		im->core.im_num_resources, &idx, data, data_len,
		&ret_len, (XPointer)&im_values, XIM_SETIMVALUES)) {
	    if (buf != tmp_buf)
		Xfree(buf);
	    return False;
	}

	total += ret_len;
	if (idx == -1) {
	    break;
	}

	buf_size += ret_len;
	if (buf == tmp_buf) {
	    if (!(tmp = Xcalloc(buf_size + data_len, 1))) {
		return False;
	    }
	    memcpy(tmp, buf, buf_size);
	    buf = tmp;
	} else {
	    if (!(tmp = Xrealloc(buf, (buf_size + data_len)))) {
		Xfree(buf);
		return False;
	    }
            memset(&tmp[buf_size], 0, data_len);
	    buf = tmp;
	}
    }

    if (!total)
	return True;

    buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
    buf_s[0] = im->private.proto.imid;
    buf_s[1] = (INT16)total;

    len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total);
    _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len);
    if (!(_XimWrite(im, len, (XPointer)buf))) {
	if (buf != tmp_buf)
	    Xfree(buf);
	return False;
    }
    _XimFlush(im);
    if (buf != tmp_buf)
	Xfree(buf);
    buf_size = BUFSIZE;
    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
    					 _XimSetIMValuesCheck, 0);
    if(ret_code == XIM_TRUE) {
	preply = reply;
    } else if(ret_code == XIM_OVERFLOW) {
	if(len <= 0) {
	    preply = reply;
	} else {
	    buf_size = (int)len;
	    preply = Xmalloc(buf_size);
	    ret_code = _XimRead(im, &len, reply, buf_size,
					_XimSetIMValuesCheck, 0);
    	    if(ret_code != XIM_TRUE) {
		Xfree(preply);
		return False;
	    }
	}
    } else
	return False;

    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
    if (*((CARD8 *)preply) == XIM_ERROR) {
	_XimProcError(im, 0, (XPointer)&buf_s[3]);
    	if(reply != preply)
	    Xfree(preply);
	return False;
    }
    if(reply != preply)
	Xfree(preply);

    return True;
}


BrokenSyncWithServer(XIC xic)
{
    CARD32 dummy;
    XGetICValues(xic, XNFilterEvents, &dummy, NULL);
}


_XimOpenCheck(
    Xim		 im,
    INT16	 len,
    XPointer	 data,
    XPointer	 arg)
{
    CARD8	 major_opcode = *((CARD8 *)data);
    CARD8	 minor_opcode = *((CARD8 *)data + 1);

    if ((major_opcode == XIM_OPEN_REPLY)
     && (minor_opcode == 0))
	return True;
    if ((major_opcode == XIM_ERROR)
     && (minor_opcode == 0))
	return True;
    return False;
}


int sftp_reply_data(sftp_client_message msg, const void *data, int len) {
  ssh_buffer out;

  out = ssh_buffer_new();
  if (out == NULL) {
    return -1;
  }

  if (ssh_buffer_add_u32(out, msg->id) < 0 ||
      ssh_buffer_add_u32(out, ntohl(len)) < 0 ||
      ssh_buffer_add_data(out, data, len) < 0 ||
      sftp_packet_write(msg->sftp, SSH_FXP_DATA, out) < 0) {
    SSH_BUFFER_FREE(out);
    return -1;
  }
  SSH_BUFFER_FREE(out);

  return 0;
}


int ssh_buffer_get_u32(struct ssh_buffer_struct *buffer, uint32_t *data){
    return ssh_buffer_get_data(buffer,data,sizeof(uint32_t));
}


static int ocfs2_expand_nonsparse_inode(struct inode *inode,
					struct buffer_head *di_bh,
					loff_t pos, unsigned len,
					struct ocfs2_write_ctxt *wc)
{
	int ret;
	loff_t newsize = pos + len;

	BUG_ON(ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)));

	if (newsize <= i_size_read(inode))
		return 0;

	ret = ocfs2_extend_no_holes(inode, di_bh, newsize, pos);
	if (ret)
		mlog_errno(ret);

	wc->w_first_new_cpos =
		ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));

	return ret;
}


static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
				     struct buffer_head *bh_result, int create)
{
	int ret;
	u64 p_blkno, inode_blocks, contig_blocks;
	unsigned int ext_flags;
	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
	unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;

	/* This function won't even be called if the request isn't all
	 * nicely aligned and of the right size, so there's no need
	 * for us to check any of that. */

	inode_blocks = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));

	/* This figures out the size of the next contiguous block, and
	 * our logical offset */
	ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno,
					  &contig_blocks, &ext_flags);
	if (ret) {
		mlog(ML_ERROR, "get_blocks() failed iblock=%llu\n",
		     (unsigned long long)iblock);
		ret = -EIO;
		goto bail;
	}

	/* We should already CoW the refcounted extent in case of create. */
	BUG_ON(create && (ext_flags & OCFS2_EXT_REFCOUNTED));

	/*
	 * get_more_blocks() expects us to describe a hole by clearing
	 * the mapped bit on bh_result().
	 *
	 * Consider an unwritten extent as a hole.
	 */
	if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN))
		map_bh(bh_result, inode->i_sb, p_blkno);
	else
		clear_buffer_mapped(bh_result);

	/* make sure we don't map more than max_blocks blocks here as
	   that's all the kernel will handle at this point. */
	if (max_blocks < contig_blocks)
		contig_blocks = max_blocks;
	bh_result->b_size = contig_blocks << blocksize_bits;
bail:
	return ret;
}


prepare_repo_download_zck_target(LrHandle *handle,
                                 LrYumRepoMdRecord *record,
                                 char **path,
                                 int *fd,
                                 GSList **checksums,
                                 GSList **targets,
                                 GError **err)
{
    *path = lr_pathconcat(handle->destdir, record->location_href, NULL);
    *fd = open(*path, O_CREAT|O_RDWR, 0666);
    if (*fd < 0) {
        g_debug("%s: Cannot create/open %s (%s)",
                __func__, *path, g_strerror(errno));
        g_set_error(err, LR_YUM_ERROR, LRE_IO,
                    "Cannot create/open %s: %s", *path, g_strerror(errno));
        lr_free(*path);
        g_slist_free_full(*targets, (GDestroyNotify) lr_downloadtarget_free);
        return FALSE;
    }

    if (handle->checks & LR_CHECK_CHECKSUM) {
        // Select proper checksum type only if checksum check is enabled
        LrDownloadTargetChecksum *checksum;
        checksum = lr_downloadtargetchecksum_new(
                       lr_checksum_type(record->header_checksum_type),
                       record->header_checksum);
        *checksums = g_slist_prepend(*checksums, checksum);
    }
    return TRUE;
}


lr_yum_repomd_record_enabled(LrHandle *handle, const char *type, GSList* records)
{
    // Blacklist check
    if (handle->yumblist) {
        int x = 0;
        while (handle->yumblist[x]) {
            if (!strcmp(handle->yumblist[x], type))
                return FALSE;
            x++;
        }
    }

    // Whitelist check
    if (handle->yumdlist) {
        int x = 0;
        while (handle->yumdlist[x]) {
            if (!strcmp(handle->yumdlist[x], type))
                return TRUE;
            x++;
        }
        // Substitution check
        if (handle->yumslist) {
            for (GSList *elem = handle->yumslist; elem; elem = g_slist_next(elem)) {
                LrVar* subs = elem->data;
                if (!g_strcmp0(subs->val, type)) {
                    char *orig = subs->var;
                    for (guint i = 0; handle->yumdlist[i]; i++) {
                        if (!g_strcmp0(orig, handle->yumdlist[i]) &&
                            !g_slist_find_custom(records, orig, (GCompareFunc) compare_records))
                            return TRUE;
                    }
                    return FALSE;
                }
            }
        }
        return FALSE;
    }
    return TRUE;
}


lr_copy_metalink_content(LrHandle *handle,
                         LrYumRepo *repo,
                         GError **err)
{
    int fd;
    int rc;

    if (handle->metalink_fd != -1) {
        char *ml_file_path = lr_pathconcat(handle->destdir,
                                           "metalink.xml", NULL);
        fd = open(ml_file_path, O_CREAT|O_TRUNC|O_RDWR, 0666);
        if (fd < 0) {
            g_debug("%s: Cannot create: %s", __func__, ml_file_path);
            g_set_error(err, LR_YUM_ERROR, LRE_IO,
                        "Cannot create %s: %s", ml_file_path, g_strerror(errno));
            lr_free(ml_file_path);
            return FALSE;
        }
        rc = lr_copy_content(handle->metalink_fd, fd);
        close(fd);
        if (rc != 0) {
            g_debug("%s: Cannot copy content of metalink file", __func__);
            g_set_error(err, LR_YUM_ERROR, LRE_IO,
                        "Cannot copy content of metalink file %s: %s",
                        ml_file_path, g_strerror(errno));
            lr_free(ml_file_path);
            return FALSE;
        }
        repo->metalink = ml_file_path;
    }

    return TRUE;
}


static int h2_push_diary_find(h2_push_diary *diary, apr_uint64_t hash)
{
    if (diary) {
        h2_push_diary_entry *e;
        int i;

        /* search from the end, where the last accessed digests are */
        for (i = diary->entries->nelts-1; i >= 0; --i) {
            e = &APR_ARRAY_IDX(diary->entries, i, h2_push_diary_entry);
            if (e->hash == hash) {
                return i;
            }
        }
    }
    return -1;
}


static h2_push_diary *diary_create(apr_pool_t *p, h2_push_digest_type dtype,
                                   int N)
{
    h2_push_diary *diary = NULL;

    if (N > 0) {
        diary = apr_pcalloc(p, sizeof(*diary));

        diary->NMax        = ceil_power_of_2(N);
        diary->N           = diary->NMax;
        /* the mask we use in value comparison depends on where we got
         * the values from. If we calculate them ourselves, we can use
         * the full 64 bits.
         * If we set the diary via a compressed golomb set, we have less
         * relevant bits and need to use a smaller mask. */
        diary->mask_bits   = 64;
        /* grows by doubling, start with a power of 2 */
        diary->entries     = apr_array_make(p, 16, sizeof(h2_push_diary_entry));

        switch (dtype) {
#ifdef H2_OPENSSL
            case H2_PUSH_DIGEST_SHA256:
                diary->dtype       = H2_PUSH_DIGEST_SHA256;
                diary->dcalc       = calc_sha256_hash;
                break;
#endif /* ifdef H2_OPENSSL */
            default:
                diary->dtype       = H2_PUSH_DIGEST_APR_HASH;
                diary->dcalc       = calc_apr_hash;
                break;
        }
    }

    return diary;
}


static unsigned int val_apr_hash(const char *str)
{
    apr_ssize_t len = (apr_ssize_t)strlen(str);
    return apr_hashfunc_default(str, &len);
}


static int netns_pids(int argc, char **argv)
{
	const char *name;
	char net_path[PATH_MAX];
	int netns;
	struct stat netst;
	DIR *dir;
	struct dirent *entry;

	if (argc < 1) {
		fprintf(stderr, "No netns name specified\n");
		return -1;
	}
	if (argc > 1) {
		fprintf(stderr, "extra arguments specified\n");
		return -1;
	}

	name = argv[0];
	snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
	netns = open(net_path, O_RDONLY);
	if (netns < 0) {
		fprintf(stderr, "Cannot open network namespace: %s\n",
			strerror(errno));
		return -1;
	}
	if (fstat(netns, &netst) < 0) {
		fprintf(stderr, "Stat of netns failed: %s\n",
			strerror(errno));
		return -1;
	}
	dir = opendir("/proc/");
	if (!dir) {
		fprintf(stderr, "Open of /proc failed: %s\n",
			strerror(errno));
		return -1;
	}
	while ((entry = readdir(dir))) {
		char pid_net_path[PATH_MAX];
		struct stat st;

		if (!is_pid(entry->d_name))
			continue;
		snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%s/ns/net",
			entry->d_name);
		if (stat(pid_net_path, &st) != 0)
			continue;
		if ((st.st_dev == netst.st_dev) &&
		    (st.st_ino == netst.st_ino)) {
			printf("%s\n", entry->d_name);
		}
	}
	closedir(dir);
	return 0;

}


static int is_pid(const char *str)
{
	int ch;

	for (; (ch = *str); str++) {
		if (!isdigit(ch))
			return 0;
	}
	return 1;
}


static int usage(void)
{
	fprintf(stderr, "Usage: ip netns list\n");
	fprintf(stderr, "       ip netns add NAME\n");
	fprintf(stderr, "       ip netns attach NAME PID\n");
	fprintf(stderr, "       ip netns set NAME NETNSID\n");
	fprintf(stderr, "       ip [-all] netns delete [NAME]\n");
	fprintf(stderr, "       ip netns identify [PID]\n");
	fprintf(stderr, "       ip netns pids NAME\n");
	fprintf(stderr, "       ip [-all] netns exec [NAME] cmd ...\n");
	fprintf(stderr, "       ip netns monitor\n");
	fprintf(stderr, "       ip netns list-id\n");
	fprintf(stderr, "NETNSID := auto | POSITIVE-INT\n");
	exit(-1);
}


static int netns_add(int argc, char **argv, bool create)
{
	/* This function creates a new network namespace and
	 * a new mount namespace and bind them into a well known
	 * location in the filesystem based on the name provided.
	 *
	 * If create is true, a new namespace will be created,
	 * otherwise an existing one will be attached to the file.
	 *
	 * The mount namespace is created so that any necessary
	 * userspace tweaks like remounting /sys, or bind mounting
	 * a new /etc/resolv.conf can be shared between users.
	 */
	char netns_path[PATH_MAX], proc_path[PATH_MAX];
	const char *name;
	pid_t pid;
	int fd;
	int made_netns_run_dir_mount = 0;

	if (create) {
		if (argc < 1) {
			fprintf(stderr, "No netns name specified\n");
			return -1;
		}
	} else {
		if (argc < 2) {
			fprintf(stderr, "No netns name and PID specified\n");
			return -1;
		}

		if (get_s32(&pid, argv[1], 0) || !pid) {
			fprintf(stderr, "Invalid PID: %s\n", argv[1]);
			return -1;
		}
	}
	name = argv[0];

	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);

	if (create_netns_dir())
		return -1;

	/* Make it possible for network namespace mounts to propagate between
	 * mount namespaces.  This makes it likely that a unmounting a network
	 * namespace file in one namespace will unmount the network namespace
	 * file in all namespaces allowing the network namespace to be freed
	 * sooner.
	 */
	while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
		/* Fail unless we need to make the mount point */
		if (errno != EINVAL || made_netns_run_dir_mount) {
			fprintf(stderr, "mount --make-shared %s failed: %s\n",
				NETNS_RUN_DIR, strerror(errno));
			return -1;
		}

		/* Upgrade NETNS_RUN_DIR to a mount point */
		if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND | MS_REC, NULL)) {
			fprintf(stderr, "mount --bind %s %s failed: %s\n",
				NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
			return -1;
		}
		made_netns_run_dir_mount = 1;
	}

	/* Create the filesystem state */
	fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
	if (fd < 0) {
		fprintf(stderr, "Cannot create namespace file \"%s\": %s\n",
			netns_path, strerror(errno));
		return -1;
	}
	close(fd);

	if (create) {
		if (unshare(CLONE_NEWNET) < 0) {
			fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n",
				name, strerror(errno));
			goto out_delete;
		}

		strcpy(proc_path, "/proc/self/ns/net");
	} else {
		snprintf(proc_path, sizeof(proc_path), "/proc/%d/ns/net", pid);
	}

	/* Bind the netns last so I can watch for it */
	if (mount(proc_path, netns_path, "none", MS_BIND, NULL) < 0) {
		fprintf(stderr, "Bind %s -> %s failed: %s\n",
			proc_path, netns_path, strerror(errno));
		goto out_delete;
	}
	return 0;
out_delete:
	if (create) {
		netns_delete(argc, argv);
	} else if (unlink(netns_path) < 0) {
		fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
			netns_path, strerror(errno));
	}
	return -1;
}


static void destroy_channel(Encoder *encoder, Channel *channel)
{
    QuicUsrContext *usr = encoder->usr;
    if (channel->correlate_row) {
        usr->free(usr, channel->correlate_row - 1);
    }
    free_family_stat(usr, &channel->family_stat_8bpc);
    free_family_stat(usr, &channel->family_stat_5bpc);
}


SPICE_CONSTRUCTOR_FUNC(quic_global_init)
{
    family_init(&family_8bpc, 8, DEFmaxclen);
    family_init(&family_5bpc, 5, DEFmaxclen);
}


static void correlate_init(QuicFamily *family, int bpc)
{
    const unsigned int pixelbitmask = bppmask[bpc];
    unsigned long int s;

    //spice_assert(bpc <= 8);

    for (s = 0; s <= pixelbitmask; s++) {
        if (s & 0x01) {
            family->xlatL2U[s] = pixelbitmask - (s >> 1);
        } else {
            family->xlatL2U[s] = (s >> 1);
        }
    }
}


static void uncompress_rgba(Encoder *encoder, uint8_t *buf, int stride)
{
    unsigned int row;
    uint8_t *prev;

    encoder->channels[0].correlate_row[-1] = 0;
    encoder->channels[1].correlate_row[-1] = 0;
    encoder->channels[2].correlate_row[-1] = 0;
    quic_rgb32_uncompress_row0(encoder, (rgb32_pixel_t *)buf, encoder->width);

    encoder->channels[3].correlate_row[-1] = 0;
    quic_four_uncompress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(buf + 3),
                              encoder->width);

    encoder->rows_completed++;
    for (row = 1; row < encoder->height; row++) {
        prev = buf;
        buf += stride;

        encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0];
        encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0];
        encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0];
        quic_rgb32_uncompress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)buf,
                                  encoder->width);

        encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0];
        quic_four_uncompress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3),
                                 (four_bytes_t *)(buf + 3), encoder->width);

        encoder->rows_completed++;
    }
}


static void FNAME_DECL(compress_row)(const PIXEL * const prev_row,
                                     const PIXEL * const cur_row,
                                     unsigned int width)

{
    DECLARE_STATE_VARIABLES;
    const unsigned int bpc_mask = BPC_MASK;
    unsigned int pos = 0;

    while ((DEFwmimax > (int)state->wmidx) && (state->wmileft <= width)) {
        if (state->wmileft) {
            FNAME_CALL(compress_row_seg)(pos, prev_row, cur_row,
                                         pos + state->wmileft, bppmask[state->wmidx],
                                         bpc_mask);
            width -= state->wmileft;
            pos += state->wmileft;
        }

        state->wmidx++;
        set_wm_trigger(state);
        state->wmileft = DEFwminext;
    }

    if (width) {
        FNAME_CALL(compress_row_seg)(pos, prev_row, cur_row, pos + width,
                                     bppmask[state->wmidx], bpc_mask);
        if (DEFwmimax > (int)state->wmidx) {
            state->wmileft -= width;
        }
    }

    spice_assert((int)state->wmidx <= DEFwmimax);
    spice_assert(state->wmidx <= 32);
    spice_assert(DEFwminext > 0);
}


static inline unsigned int FNAME(golomb_code_len)(const BYTE n, const unsigned int l)
{
    return VNAME(family).golomb_code_len[n][l];
}


nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *supported)
{
	struct accessmap	*map;
	struct svc_export	*export;
	struct dentry		*dentry;
	u32			query, result = 0, sresult = 0;
	__be32			error;

	error = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
	if (error)
		goto out;

	export = fhp->fh_export;
	dentry = fhp->fh_dentry;

	if (d_is_reg(dentry))
		map = nfs3_regaccess;
	else if (d_is_dir(dentry))
		map = nfs3_diraccess;
	else
		map = nfs3_anyaccess;

	query = *access;
	for  (; map->access; map++) {
		if (map->access & query) {
			__be32 err2;

			sresult |= map->access;

			err2 = nfsd_permission(rqstp, export, dentry, map->how);
			switch (err2) {
			case nfs_ok:
				result |= map->access;
				break;

			/* the following error codes just mean the access was not allowed,
			 * rather than an error occurred */
			case nfserr_rofs:
			case nfserr_acces:
			case nfserr_perm:
				/* simply don't "or" in the access bit. */
				break;
			default:
				error = err2;
				goto out;
			}
		}
	}
	*access = result;
	if (supported)
		*supported = sresult;

 out:
	return error;
}


int nfsd4_is_junction(struct dentry *dentry)
{
	struct inode *inode = d_inode(dentry);

	if (inode == NULL)
		return 0;
	if (inode->i_mode & S_IXUGO)
		return 0;
	if (!(inode->i_mode & S_ISVTX))
		return 0;
	if (vfs_getxattr(dentry, NFSD_JUNCTION_XATTR_NAME, NULL, 0) <= 0)
		return 0;
	return 1;
}


SProcXkbSetGeometry(ClientPtr client)
{
    REQUEST(xkbSetGeometryReq);

    swaps(&stuff->length);
    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
    swaps(&stuff->deviceSpec);
    swapl(&stuff->name);
    swaps(&stuff->widthMM);
    swaps(&stuff->heightMM);
    swaps(&stuff->nProperties);
    swaps(&stuff->nColors);
    swaps(&stuff->nDoodads);
    swaps(&stuff->nKeyAliases);
    return ProcXkbSetGeometry(client);
}


SProcXkbListComponents(ClientPtr client)
{
    REQUEST(xkbListComponentsReq);

    swaps(&stuff->length);
    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
    swaps(&stuff->deviceSpec);
    swaps(&stuff->maxNames);
    return ProcXkbListComponents(client);
}


SProcXkbUseExtension(ClientPtr client)
{
    REQUEST(xkbUseExtensionReq);

    swaps(&stuff->length);
    REQUEST_SIZE_MATCH(xkbUseExtensionReq);
    swaps(&stuff->wantedMajor);
    swaps(&stuff->wantedMinor);
    return ProcXkbUseExtension(client);
}


SProcXkbSetDeviceInfo(ClientPtr client)
{
    REQUEST(xkbSetDeviceInfoReq);

    swaps(&stuff->length);
    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
    swaps(&stuff->deviceSpec);
    swaps(&stuff->change);
    swaps(&stuff->nDeviceLedFBs);
    return ProcXkbSetDeviceInfo(client);
}


SProcXkbGetState(ClientPtr client)
{
    REQUEST(xkbGetStateReq);

    swaps(&stuff->length);
    REQUEST_SIZE_MATCH(xkbGetStateReq);
    swaps(&stuff->deviceSpec);
    return ProcXkbGetState(client);
}


RecordFindClientOnContext(RecordContextPtr pContext,
                          XID clientspec, int *pposition)
{
    RecordClientsAndProtocolPtr pRCAP;

    for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) {
        int i;

        for (i = 0; i < pRCAP->numClients; i++) {
            if (pRCAP->pClientIDs[i] == clientspec) {
                if (pposition)
                    *pposition = i;
                return pRCAP;
            }
        }
    }
    return NULL;
}                               /* RecordFindClientOnContext */


RecordADeviceEvent(CallbackListPtr *pcbl, void *nulldata, void *calldata)
{
    DeviceEventInfoRec *pei = (DeviceEventInfoRec *) calldata;
    RecordContextPtr pContext;
    RecordClientsAndProtocolPtr pRCAP;
    int eci;                    /* enabled context index */

    for (eci = 0; eci < numEnabledContexts; eci++) {
        pContext = ppAllContexts[eci];
        for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) {
            if (pRCAP->pDeviceEventSet) {
                int count;
                xEvent *xi_events = NULL;

                /* TODO check return values */
                if (IsMaster(pei->device)) {
                    xEvent *core_events;

                    EventToCore(pei->event, &core_events, &count);
                    RecordSendProtocolEvents(pRCAP, pContext, core_events,
                                             count);
                    free(core_events);
                }

                EventToXI(pei->event, &xi_events, &count);
                RecordSendProtocolEvents(pRCAP, pContext, xi_events, count);
                free(xi_events);
            }                   /* end this RCAP selects device events */
        }                       /* end for each RCAP on this context */
    }                           /* end for each enabled context */
}


RecordAClientStateChange(CallbackListPtr *pcbl, void *nulldata,
                         void *calldata)
{
    NewClientInfoRec *pci = (NewClientInfoRec *) calldata;
    int i;
    ClientPtr pClient = pci->client;
    RecordContextPtr *ppAllContextsCopy = NULL;
    int numContextsCopy = 0;

    switch (pClient->clientState) {
    case ClientStateRunning:   /* new client */
        for (i = 0; i < numContexts; i++) {
            RecordClientsAndProtocolPtr pRCAP;
            RecordContextPtr pContext = ppAllContexts[i];

            if ((pRCAP = RecordFindClientOnContext(pContext,
                                                   XRecordFutureClients, NULL)))
            {
                RecordAddClientToRCAP(pRCAP, pClient->clientAsMask);
                if (pContext->pRecordingClient && pRCAP->clientStarted)
                    RecordConnectionSetupInfo(pContext, pci);
            }
        }
        break;

    case ClientStateGone:
    case ClientStateRetained:  /* client disconnected */

        /* RecordDisableContext modifies contents of ppAllContexts. */
        if (!(numContextsCopy = numContexts))
            break;
        ppAllContextsCopy = xallocarray(numContextsCopy,
                                        sizeof(RecordContextPtr));
        assert(ppAllContextsCopy);
        memcpy(ppAllContextsCopy, ppAllContexts,
               numContextsCopy * sizeof(RecordContextPtr));

        for (i = 0; i < numContextsCopy; i++) {
            RecordClientsAndProtocolPtr pRCAP;
            RecordContextPtr pContext = ppAllContextsCopy[i];
            int pos;

            if (pContext->pRecordingClient == pClient)
                RecordDisableContext(pContext);
            if ((pRCAP = RecordFindClientOnContext(pContext,
                                                   pClient->clientAsMask,
                                                   &pos))) {
                if (pContext->pRecordingClient && pRCAP->clientDied)
                    RecordAProtocolElement(pContext, pClient,
                                           XRecordClientDied, NULL, 0, 0, 0);
                RecordDeleteClientFromRCAP(pRCAP, pos);
            }
        }

        free(ppAllContextsCopy);
        break;

    default:
        break;
    }                           /* end switch on client state */
}                               /* RecordAClientStateChange */


RecordSwapRanges(xRecordRange * pRanges, int nRanges)
{
    int i;

    for (i = 0; i < nRanges; i++, pRanges++) {
        swaps(&pRanges->extRequestsMinorFirst);
        swaps(&pRanges->extRequestsMinorLast);
        swaps(&pRanges->extRepliesMinorFirst);
        swaps(&pRanges->extRepliesMinorLast);
    }
}                               /* RecordSwapRanges */


dns_message_gettimeadjust(dns_message_t *msg) {
	REQUIRE(DNS_MESSAGE_VALID(msg));
	return (msg->timeadjust);
}


dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
	REQUIRE(DNS_MESSAGE_VALID(msg));
	REQUIRE(space <= msg->reserved);

	msg->reserved -= space;
}


getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
	     unsigned int options)
{
	isc_region_t r;
	unsigned int count;
	dns_name_t *name;
	dns_name_t *name2;
	dns_offsets_t *offsets;
	dns_rdataset_t *rdataset;
	dns_rdatalist_t *rdatalist;
	isc_result_t result;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	dns_namelist_t *section;
	bool free_name;
	bool best_effort;
	bool seen_problem;

	section = &msg->sections[DNS_SECTION_QUESTION];

	best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0);
	seen_problem = false;

	name = NULL;
	rdataset = NULL;
	rdatalist = NULL;

	for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
		name = isc_mempool_get(msg->namepool);
		if (name == NULL)
			return (ISC_R_NOMEMORY);
		free_name = true;

		offsets = newoffsets(msg);
		if (offsets == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
		dns_name_init(name, *offsets);

		/*
		 * Parse the name out of this packet.
		 */
		isc_buffer_remainingregion(source, &r);
		isc_buffer_setactive(source, r.length);
		result = getname(name, source, msg, dctx);
		if (result != ISC_R_SUCCESS)
			goto cleanup;

		/*
		 * Run through the section, looking to see if this name
		 * is already there.  If it is found, put back the allocated
		 * name since we no longer need it, and set our name pointer
		 * to point to the name we found.
		 */
		result = findname(&name2, name, section);

		/*
		 * If it is the first name in the section, accept it.
		 *
		 * If it is not, but is not the same as the name already
		 * in the question section, append to the section.  Note that
		 * here in the question section this is illegal, so return
		 * FORMERR.  In the future, check the opcode to see if
		 * this should be legal or not.  In either case we no longer
		 * need this name pointer.
		 */
		if (result != ISC_R_SUCCESS) {
			if (!ISC_LIST_EMPTY(*section))
				DO_ERROR(DNS_R_FORMERR);
			ISC_LIST_APPEND(*section, name, link);
			free_name = false;
		} else {
			isc_mempool_put(msg->namepool, name);
			name = name2;
			name2 = NULL;
			free_name = false;
		}

		/*
		 * Get type and class.
		 */
		isc_buffer_remainingregion(source, &r);
		if (r.length < 4) {
			result = ISC_R_UNEXPECTEDEND;
			goto cleanup;
		}
		rdtype = isc_buffer_getuint16(source);
		rdclass = isc_buffer_getuint16(source);

		/*
		 * If this class is different than the one we already read,
		 * this is an error.
		 */
		if (msg->rdclass_set == 0) {
			msg->rdclass = rdclass;
			msg->rdclass_set = 1;
		} else if (msg->rdclass != rdclass)
			DO_ERROR(DNS_R_FORMERR);

		/*
		 * Is this a TKEY query?
		 */
		if (rdtype == dns_rdatatype_tkey)
			msg->tkey = 1;

		/*
		 * Can't ask the same question twice.
		 */
		result = dns_message_find(name, rdclass, rdtype, 0, NULL);
		if (result == ISC_R_SUCCESS)
			DO_ERROR(DNS_R_FORMERR);

		/*
		 * Allocate a new rdatalist.
		 */
		rdatalist = newrdatalist(msg);
		if (rdatalist == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
		rdataset =  isc_mempool_get(msg->rdspool);
		if (rdataset == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}

		/*
		 * Convert rdatalist to rdataset, and attach the latter to
		 * the name.
		 */
		rdatalist->type = rdtype;
		rdatalist->rdclass = rdclass;

		dns_rdataset_init(rdataset);
		result = dns_rdatalist_tordataset(rdatalist, rdataset);
		if (result != ISC_R_SUCCESS)
			goto cleanup;

		rdataset->attributes |= DNS_RDATASETATTR_QUESTION;

		ISC_LIST_APPEND(name->list, rdataset, link);
		rdataset = NULL;
	}

	if (seen_problem)
		return (DNS_R_RECOVERABLE);
	return (ISC_R_SUCCESS);

 cleanup:
	if (rdataset != NULL) {
		INSIST(!dns_rdataset_isassociated(rdataset));
		isc_mempool_put(msg->rdspool, rdataset);
	}
#if 0
	if (rdatalist != NULL)
		isc_mempool_put(msg->rdlpool, rdatalist);
#endif
	if (free_name)
		isc_mempool_put(msg->namepool, name);

	return (result);
}


dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
		     dns_rdatatype_t covers, dns_rdataset_t **rdataset)
{
	dns_rdataset_t *curr;

	REQUIRE(name != NULL);
	REQUIRE(rdataset == NULL || *rdataset == NULL);

	for (curr = ISC_LIST_TAIL(name->list);
	     curr != NULL;
	     curr = ISC_LIST_PREV(curr, link)) {
		if (curr->type == type && curr->covers == covers) {
			if (ISC_UNLIKELY(rdataset != NULL))
				*rdataset = curr;
			return (ISC_R_SUCCESS);
		}
	}

	return (ISC_R_NOTFOUND);
}


dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
	isc_result_t result;

	/*
	 * Set the TSIG key for 'msg'
	 */

	REQUIRE(DNS_MESSAGE_VALID(msg));

	if (key == NULL && msg->tsigkey != NULL) {
		if (msg->sig_reserved != 0) {
			dns_message_renderrelease(msg, msg->sig_reserved);
			msg->sig_reserved = 0;
		}
		dns_tsigkey_detach(&msg->tsigkey);
	}
	if (key != NULL) {
		REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
		dns_tsigkey_attach(key, &msg->tsigkey);
		if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
			msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
			result = dns_message_renderreserve(msg,
							   msg->sig_reserved);
			if (result != ISC_R_SUCCESS) {
				dns_tsigkey_detach(&msg->tsigkey);
				msg->sig_reserved = 0;
				return (result);
			}
		}
	}
	return (ISC_R_SUCCESS);
}


dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
			 const void *order_arg)
{
	REQUIRE(DNS_MESSAGE_VALID(msg));
	msg->order = order;
	msg->order_arg = order_arg;
}


dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {

	/*
	 * Get the TSIG record and owner for 'msg'.
	 */

	REQUIRE(DNS_MESSAGE_VALID(msg));
	REQUIRE(owner == NULL || *owner == NULL);

	if (owner != NULL)
		*owner = msg->tsigname;
	return (msg->tsig);
}


maybe_clear_ad(dns_message_t *msg, dns_section_t sectionid) {
	if (msg->counts[sectionid] == 0 &&
	    (sectionid == DNS_SECTION_ANSWER ||
	     (sectionid == DNS_SECTION_AUTHORITY &&
	      msg->counts[DNS_SECTION_ANSWER] == 0)))
		msg->flags &= ~DNS_MESSAGEFLAG_AD;
}


dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
	REQUIRE(DNS_MESSAGE_VALID(msg));
	REQUIRE(item != NULL && *item != NULL);

	releaserdatalist(msg, *item);
	*item = NULL;
}