ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf)
{
	size_t size;
	char *b32;
	if(ldns_rdf_size(rdf) == 0)
		return LDNS_STATUS_OK;
        /* remove -1 for the b32-hash-len octet */
	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
        /* add one for the end nul for the string */
	b32 = LDNS_XMALLOC(char, size + 1);
	if(!b32) return LDNS_STATUS_MEM_ERR;
	size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
		ldns_rdf_size(rdf) - 1, b32, size+1);
	if (size > 0) {
		ldns_buffer_printf(output, "%s", b32);
	}
	LDNS_FREE(b32);
	return ldns_buffer_status(output);
}


ldns_rr_label_count(ldns_rr *rr)
{
	if (!rr) {
		return 0;
	}
	return ldns_dname_label_count(
			ldns_rr_owner(rr));
}


ldns_native2rdf_int16_data(size_t size, uint8_t *data)
{
	uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
        ldns_rdf* rdf;
	if (!rdf_data) {
		return NULL;
	}
	ldns_write_uint16(rdf_data, size);
	memcpy(rdf_data + 2, data, size);
	rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
        if(!rdf)
                LDNS_FREE(rdf_data);
        return rdf;
}


ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
{
	return ldns_pkt2buffer_str_fmt(output, ldns_output_format_default, pkt);
}


ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
{
	/* Note: this code is duplicated in higher.c in
	 * ldns_nsec_type_check() function
	 */
	uint8_t window_block_nr;
	uint8_t bitmap_length;
	uint16_t type;
	uint16_t pos = 0;
	uint16_t bit_pos;
	uint8_t *data = ldns_rdf_data(rdf);
	const ldns_rr_descriptor *descriptor;

	while((size_t)(pos + 2) < ldns_rdf_size(rdf)) {
		window_block_nr = data[pos];
		bitmap_length = data[pos + 1];
		pos += 2;
		if (ldns_rdf_size(rdf) < pos + bitmap_length) {
			return LDNS_STATUS_WIRE_RDATA_ERR;
		}
		for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
			if (ldns_get_bit(&data[pos], bit_pos)) {
				type = 256 * (uint16_t) window_block_nr + bit_pos;
				descriptor = ldns_rr_descript(type);

				if (descriptor && descriptor->_name) {
					ldns_buffer_printf(output, "%s ",
							descriptor->_name);
				} else {
					ldns_buffer_printf(output, "TYPE%u ", type);
				}
			}
		}

		pos += (uint16_t) bitmap_length;
	}

	return ldns_buffer_status(output);
}


ldns_str2rdf_multi_str(ldns_rdf **rd, const char *str)
{
	uint8_t *data, *dp, ch;

	/* Worst case space requirement. We'll realloc to actual size later. */
	dp = data = LDNS_XMALLOC(uint8_t, strlen(str) + strlen(str) / 255 + 1);
	if (! data) {
		return LDNS_STATUS_MEM_ERR;
	}

	/* Fill data with length byte (255) followed by 255 chars, repeatedly */
	*dp++ = 255;
	while (parse_char(&ch, &str)) {
		*dp++ = ch;
		if ((dp - data) % 256 == 0) {
			*dp++ = 255;
		}
		if (dp - data > LDNS_MAX_RDFLEN) {
			LDNS_FREE(data);
			return LDNS_STATUS_INVALID_STR;
		}
	}
	if (! str) {
		return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
	}
	/* Fix last length byte */
	data[(dp - data) / 256 * 256] = (dp - data) % 256 - 1;

	/* Lose the overmeasure */
	data = LDNS_XREALLOC(data, uint8_t, dp - data);
	if (! data) {
		return LDNS_STATUS_MEM_ERR;
	}

	/* Create rdf */
	*rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR,  dp - data, data);
	if (! *rd) {
		LDNS_FREE(data);
		return LDNS_STATUS_MEM_ERR;
	}
	return LDNS_STATUS_OK;
}


ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf)
{
	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
	ldns_lookup_table *lt;

 	lt = ldns_lookup_by_id(ldns_rr_classes, (int) data);
	if (lt) {
		ldns_buffer_printf(output, "\t%s", lt->name);
	} else {
		ldns_buffer_printf(output, "\tCLASS%d", data);
	}
	return ldns_buffer_status(output);
}


ldns_rdf2buffer_str_tag(ldns_buffer *output, const ldns_rdf *rdf)
{
	size_t nchars;
	const uint8_t* chars;
	char ch;
	if (ldns_rdf_size(rdf) < 2) {
		return LDNS_STATUS_WIRE_RDATA_ERR;
	}
	nchars = ldns_rdf_data(rdf)[0];
	if (nchars >= ldns_rdf_size(rdf) || /* should be rdf_size - 1 */
			nchars < 1) {
		return LDNS_STATUS_WIRE_RDATA_ERR;
	}
	chars = ldns_rdf_data(rdf) + 1;
	while (nchars > 0) {
		ch = *chars++;
		if (! isalnum(ch)) {
			return LDNS_STATUS_WIRE_RDATA_ERR;
		}
		ldns_buffer_printf(output, "%c", ch);
		nchars--;
	}
	return ldns_buffer_status(output);
}


ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
                             uint32_t default_ttl, ldns_rdf *origin,
		             ldns_rdf **prev, bool question)
{
	ldns_rr *new;
	const ldns_rr_descriptor *desc;
	ldns_rr_type rr_type;
	ldns_buffer *rr_buf = NULL;
	ldns_buffer *rd_buf = NULL;
	uint32_t ttl_val;
	char  *owner = NULL;
	char  *ttl = NULL;
	ldns_rr_class clas_val;
	char  *clas = NULL;
	char  *type = NULL;
	char  *rdata = NULL;
	char  *rd = NULL;
	char  *	b64 = NULL;
	size_t rd_strlen;
	const char *delimiters;
	ssize_t c;
	ldns_rdf *owner_dname;
        const char* endptr;
        int was_unknown_rr_format = 0;
	ldns_status status = LDNS_STATUS_OK;

	/* used for types with unknown number of rdatas */
	bool done;
	bool quoted;

	ldns_rdf *r = NULL;
	uint16_t r_cnt;
	uint16_t r_min;
	uint16_t r_max;
        size_t pre_data_pos;

	new = ldns_rr_new();

	owner = LDNS_XMALLOC(char, LDNS_MAX_DOMAINLEN + 1);
	ttl = LDNS_XMALLOC(char, LDNS_TTL_DATALEN);
	clas = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);
	rdata = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN + 1);
	rr_buf = LDNS_MALLOC(ldns_buffer);
	rd_buf = LDNS_MALLOC(ldns_buffer);
	rd = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
	b64 = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
	if (!new || !owner || !ttl || !clas || !rdata || !rr_buf || !rd_buf || !rd || !b64 ) {
		status = LDNS_STATUS_MEM_ERR;
		LDNS_FREE(rr_buf);
		goto ldnserror;
	}

	ldns_buffer_new_frm_data(rr_buf, (char*)str, strlen(str));

	/* split the rr in its parts -1 signals trouble */
	if (ldns_bget_token(rr_buf, owner, "\t\n ", LDNS_MAX_DOMAINLEN) == -1) {
		status = LDNS_STATUS_SYNTAX_ERR;
		ldns_buffer_free(rr_buf);
		goto ldnserror;
	}

	if (ldns_bget_token(rr_buf, ttl, "\t\n ", LDNS_TTL_DATALEN) == -1) {
		status = LDNS_STATUS_SYNTAX_TTL_ERR;
		ldns_buffer_free(rr_buf);
		goto ldnserror;
	}
	ttl_val = (uint32_t) ldns_str2period(ttl, &endptr);

	if (strlen(ttl) > 0 && !isdigit((int) ttl[0])) {
		/* ah, it's not there or something */
		if (default_ttl == 0) {
			ttl_val = LDNS_DEFAULT_TTL;
		} else {
			ttl_val = default_ttl;
		}
		/* we not ASSUMING the TTL is missing and that
		 * the rest of the RR is still there. That is
		 * CLASS TYPE RDATA
		 * so ttl value we read is actually the class
		 */
		clas_val = ldns_get_rr_class_by_name(ttl);
		/* class can be left out too, assume IN, current
		 * token must be type
		 */
		if (clas_val == 0) {
			clas_val = LDNS_RR_CLASS_IN;
			type = LDNS_XMALLOC(char, strlen(ttl) + 1);
			if(!type) {
				status = LDNS_STATUS_MEM_ERR;
				ldns_buffer_free(rr_buf);
				goto ldnserror;
			}
			strncpy(type, ttl, strlen(ttl) + 1);
		}
	} else {
		if (ldns_bget_token(rr_buf, clas, "\t\n ", LDNS_SYNTAX_DATALEN) == -1) {
			status = LDNS_STATUS_SYNTAX_CLASS_ERR;
			ldns_buffer_free(rr_buf);
			goto ldnserror;
		}
		clas_val = ldns_get_rr_class_by_name(clas);
		/* class can be left out too, assume IN, current
		 * token must be type
		 */
		if (clas_val == 0) {
			clas_val = LDNS_RR_CLASS_IN;
			type = LDNS_XMALLOC(char, strlen(clas) + 1);
			if(!type) {
				status = LDNS_STATUS_MEM_ERR;
				ldns_buffer_free(rr_buf);
				goto ldnserror;
			}
			strncpy(type, clas, strlen(clas) + 1);
		}
	}
	/* the rest should still be waiting for us */

	if (!type) {
		type = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);
		if(!type) {
			status = LDNS_STATUS_MEM_ERR;
			ldns_buffer_free(rr_buf);
			goto ldnserror;
		}
		if (ldns_bget_token(rr_buf, type, "\t\n ", LDNS_SYNTAX_DATALEN) == -1) {
			status = LDNS_STATUS_SYNTAX_TYPE_ERR;
			ldns_buffer_free(rr_buf);
			goto ldnserror;
		}
	}

	if (ldns_bget_token(rr_buf, rdata, "\0", LDNS_MAX_PACKETLEN) == -1) {
		/* apparently we are done, and it's only a question RR
		 * so do not set status and go to ldnserror here
		*/
	}

	ldns_buffer_new_frm_data(rd_buf, rdata, strlen(rdata));

	if (strlen(owner) <= 1 && strncmp(owner, "@", 1) == 0) {
		if (origin) {
			ldns_rr_set_owner(new, ldns_rdf_clone(origin));
		} else if (prev && *prev) {
			ldns_rr_set_owner(new, ldns_rdf_clone(*prev));
		} else {
			/* default to root */
			ldns_rr_set_owner(new, ldns_dname_new_frm_str("."));
		}

		/* @ also overrides prev */
		if (prev) {
			ldns_rdf_deep_free(*prev);
			*prev = ldns_rdf_clone(ldns_rr_owner(new));
			if (!*prev) {
				status = LDNS_STATUS_MEM_ERR;
				ldns_buffer_free(rr_buf);
				goto ldnserror;
			}
		}
	} else {
		if (strlen(owner) == 0) {
			/* no ownername was given, try prev, if that fails
			 * origin, else default to root */
			if (prev && *prev) {
				ldns_rr_set_owner(new, ldns_rdf_clone(*prev));
			} else if (origin) {
				ldns_rr_set_owner(new, ldns_rdf_clone(origin));
			} else {
				ldns_rr_set_owner(new, ldns_dname_new_frm_str("."));
			}
			if(!ldns_rr_owner(new)) {
				status = LDNS_STATUS_MEM_ERR;
				ldns_buffer_free(rr_buf);
				goto ldnserror;
			}
		} else {
			owner_dname = ldns_dname_new_frm_str(owner);
			if (!owner_dname) {
				status = LDNS_STATUS_SYNTAX_ERR;
				ldns_buffer_free(rr_buf);
				goto ldnserror;
			}

			ldns_rr_set_owner(new, owner_dname);
			if (!ldns_dname_str_absolute(owner) && origin) {
				if(ldns_dname_cat(ldns_rr_owner(new),
							origin) != LDNS_STATUS_OK) {
					status = LDNS_STATUS_SYNTAX_ERR;
					ldns_buffer_free(rr_buf);
					goto ldnserror;
				}
			}
			if (prev) {
				ldns_rdf_deep_free(*prev);
				*prev = ldns_rdf_clone(ldns_rr_owner(new));
				if(!*prev) {
					status = LDNS_STATUS_MEM_ERR;
					ldns_buffer_free(rr_buf);
					goto ldnserror;
				}
			}
		}
	}
	LDNS_FREE(owner);
	owner = NULL;

	ldns_rr_set_question(new, question);

	ldns_rr_set_ttl(new, ttl_val);
	LDNS_FREE(ttl);
	ttl = NULL;

	ldns_rr_set_class(new, clas_val);
	LDNS_FREE(clas);
	clas = NULL;

	rr_type = ldns_get_rr_type_by_name(type);
	LDNS_FREE(type);
	type = NULL;

	desc = ldns_rr_descript((uint16_t)rr_type);
	ldns_rr_set_type(new, rr_type);
	if (desc) {
		/* only the rdata remains */
		r_max = ldns_rr_descriptor_maximum(desc);
		r_min = ldns_rr_descriptor_minimum(desc);
	} else {
		r_min = 0;
		r_max = 1;
	}

	/* depending on the rr_type we need to extract
	 * the rdata differently, e.g. NSEC/NSEC3 */
	switch(rr_type) {
		default:
			done = false;

			for (r_cnt = 0; !done && r_cnt < r_max; r_cnt++) {
				quoted = false;
				/* if type = B64, the field may contain spaces */
				if (ldns_rr_descriptor_field_type(desc,
					    r_cnt) == LDNS_RDF_TYPE_B64 ||
				    ldns_rr_descriptor_field_type(desc,
					    r_cnt) == LDNS_RDF_TYPE_HEX ||
				    ldns_rr_descriptor_field_type(desc,
					    r_cnt) == LDNS_RDF_TYPE_LOC ||
				    ldns_rr_descriptor_field_type(desc,
					    r_cnt) == LDNS_RDF_TYPE_WKS ||
				    ldns_rr_descriptor_field_type(desc,
					    r_cnt) == LDNS_RDF_TYPE_IPSECKEY ||
				    ldns_rr_descriptor_field_type(desc,
					    r_cnt) == LDNS_RDF_TYPE_NSEC) {
					delimiters = "\n\t";
				} else {
					delimiters = "\n\t ";
				}

				if (ldns_rdf_type_maybe_quoted(
					    ldns_rr_descriptor_field_type(
						desc, r_cnt)) &&
					    ldns_buffer_remaining(rd_buf) > 0){

					/* skip spaces */
					while (*(ldns_buffer_current(rd_buf)) == ' ') {
						ldns_buffer_skip(rd_buf, 1);
					}

					if (*(ldns_buffer_current(rd_buf)) == '\"') {
						delimiters = "\"\0";
						ldns_buffer_skip(rd_buf, 1);
						quoted = true;
					}
				}

				/* because number of fields can be variable, we can't
				   rely on _maximum() only */
				/* skip spaces */
				while (ldns_buffer_position(rd_buf) < ldns_buffer_limit(rd_buf) &&
					*(ldns_buffer_current(rd_buf)) == ' ' && !quoted
				      ) {
					ldns_buffer_skip(rd_buf, 1);
				}

				pre_data_pos = ldns_buffer_position(rd_buf);
				if ((c = ldns_bget_token(rd_buf, rd, delimiters,
							LDNS_MAX_RDFLEN)) != -1) {
					/* hmmz, rfc3597 specifies that any type can be represented with
					 * \# method, which can contain spaces...
					 * it does specify size though...
					 */
					rd_strlen = strlen(rd);

					/* unknown RR data */
					if (strncmp(rd, "\\#", 2) == 0 && !quoted && (rd_strlen == 2 || rd[2]==' ')) {
                                        	uint16_t hex_data_size;
                                                char *hex_data_str;
                                                uint16_t cur_hex_data_size;

                                                was_unknown_rr_format = 1;
                                                /* go back to before \# and skip it while setting delimiters better */
                                                ldns_buffer_set_position(rd_buf, pre_data_pos);
					        delimiters = "\n\t ";
                                                (void)ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN);
                                                /* read rdata octet length */
						c = ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN);
						if (c == -1) {
							/* something goes very wrong here */
                                                        LDNS_FREE(rd);
                                                        LDNS_FREE(b64);
                                                        ldns_buffer_free(rd_buf);
                                                        ldns_buffer_free(rr_buf);
                                                        LDNS_FREE(rdata);
                                                        ldns_rr_free(new);
							return LDNS_STATUS_SYNTAX_RDATA_ERR;
						}
						hex_data_size = (uint16_t) atoi(rd);
						/* copy the hex chars into hex str (which is 2 chars per byte) */
						hex_data_str = LDNS_XMALLOC(char, 2 * hex_data_size + 1);
						if (!hex_data_str) {
							/* malloc error */
                                                        LDNS_FREE(rd);
                                                        LDNS_FREE(b64);
                                                        ldns_buffer_free(rd_buf);
                                                        ldns_buffer_free(rr_buf);
                                                        LDNS_FREE(rdata);
                                                        ldns_rr_free(new);
							return LDNS_STATUS_SYNTAX_RDATA_ERR;
						}
						cur_hex_data_size = 0;
						while(cur_hex_data_size < 2 * hex_data_size) {
							c = ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN);
							if (c != -1) {
								rd_strlen = strlen(rd);
							}
							if (c == -1 || (size_t)cur_hex_data_size + rd_strlen > 2 * (size_t)hex_data_size) {
								LDNS_FREE(hex_data_str);
								LDNS_FREE(rd);
								LDNS_FREE(b64);
								ldns_buffer_free(rd_buf);
								ldns_buffer_free(rr_buf);
								LDNS_FREE(rdata);
								ldns_rr_free(new);
								return LDNS_STATUS_SYNTAX_RDATA_ERR;
							}
							strncpy(hex_data_str + cur_hex_data_size, rd, rd_strlen);
							cur_hex_data_size += rd_strlen;
						}
						hex_data_str[cur_hex_data_size] = '\0';

						/* correct the rdf type */
						/* if *we* know the type, interpret it as wireformat */
						if (desc) {
							size_t hex_pos = 0;
							uint8_t *hex_data = LDNS_XMALLOC(uint8_t, hex_data_size + 2);
                                                        ldns_status s;
                                                        if(!hex_data) {
                                                                LDNS_FREE(hex_data_str);
                                                                LDNS_FREE(rd);
                                                                LDNS_FREE(b64);
                                                                ldns_buffer_free(rd_buf);
                                                                ldns_buffer_free(rr_buf);
                                                                LDNS_FREE(rdata);
                                                                ldns_rr_free(new);
                                                                return LDNS_STATUS_MEM_ERR;
                                                        }
							ldns_write_uint16(hex_data, hex_data_size);
							ldns_hexstring_to_data(hex_data + 2, hex_data_str);
							s = ldns_wire2rdf(new, hex_data,
							                 hex_data_size+2, &hex_pos);
                                                        if(s != LDNS_STATUS_OK) {
                                                                LDNS_FREE(hex_data_str);
                                                                LDNS_FREE(rd);
                                                                LDNS_FREE(b64);
                                                                ldns_buffer_free(rd_buf);
                                                                ldns_buffer_free(rr_buf);
                                                                LDNS_FREE(rdata);
                                                                ldns_rr_free(new);
								LDNS_FREE(hex_data);
                                                                return s;
                                                        }
							LDNS_FREE(hex_data);
						} else {
							r = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX, hex_data_str);
                                                        if(!r) {
                                                                LDNS_FREE(hex_data_str);
                                                                LDNS_FREE(rd);
                                                                LDNS_FREE(b64);
                                                                ldns_buffer_free(rd_buf);
                                                                ldns_buffer_free(rr_buf);
                                                                LDNS_FREE(rdata);
                                                                ldns_rr_free(new);
                                                                return LDNS_STATUS_MEM_ERR;
                                                        }
							ldns_rdf_set_type(r, LDNS_RDF_TYPE_UNKNOWN);
							if(!ldns_rr_push_rdf(new, r)) {
                                                                LDNS_FREE(hex_data_str);
                                                                LDNS_FREE(rd);
                                                                LDNS_FREE(b64);
                                                                ldns_buffer_free(rd_buf);
                                                                ldns_buffer_free(rr_buf);
                                                                LDNS_FREE(rdata);
                                                                ldns_rr_free(new);
                                                                return LDNS_STATUS_MEM_ERR;
                                                        }
						}
						LDNS_FREE(hex_data_str);
					} else {
						/* Normal RR */
						switch(ldns_rr_descriptor_field_type(desc, r_cnt)) {
						case LDNS_RDF_TYPE_HEX:
						case LDNS_RDF_TYPE_B64:
							/* can have spaces, and will always be the last
							 * record of the rrdata. Read in the rest */
							if ((c = ldns_bget_token(rd_buf,
												b64,
												"\n",
												LDNS_MAX_RDFLEN))
							    != -1) {
								rd = strncat(rd,
										   b64,
										   LDNS_MAX_RDFLEN
										   - strlen(rd) - 1);
							}
							r = ldns_rdf_new_frm_str(
									ldns_rr_descriptor_field_type(desc, r_cnt),
									rd);
							break;
						case LDNS_RDF_TYPE_DNAME:
							r = ldns_rdf_new_frm_str(
									ldns_rr_descriptor_field_type(desc, r_cnt),
									rd);

							/* check if the origin should be used or concatenated */
							if (r && ldns_rdf_size(r) > 1 && ldns_rdf_data(r)[0] == 1
								&& ldns_rdf_data(r)[1] == '@') {
								ldns_rdf_deep_free(r);
								if (origin) {
									r = ldns_rdf_clone(origin);
								} else {
								     /* if this is the SOA, use its own owner name */
									if (rr_type == LDNS_RR_TYPE_SOA) {
										r = ldns_rdf_clone(ldns_rr_owner(new));
									} else {
										r = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, ".");
									}
								}
							} else if (r && rd_strlen >= 1 && !ldns_dname_str_absolute(rd) && origin) {
								if (ldns_dname_cat(r, origin) != LDNS_STATUS_OK) {
							                LDNS_FREE(rd);
							                LDNS_FREE(b64);
							                ldns_buffer_free(rd_buf);
							                ldns_buffer_free(rr_buf);
							                LDNS_FREE(rdata);
							                ldns_rr_free(new);
									return LDNS_STATUS_ERR;
								}
							}
							break;
						default:
							r = ldns_rdf_new_frm_str(
									ldns_rr_descriptor_field_type(desc, r_cnt),
									rd);
							break;
						}
						if (r) {
							ldns_rr_push_rdf(new, r);
						} else {
							LDNS_FREE(rd);
							LDNS_FREE(b64);
							ldns_buffer_free(rd_buf);
							ldns_buffer_free(rr_buf);
							LDNS_FREE(rdata);
							ldns_rr_free(new);
							return LDNS_STATUS_SYNTAX_RDATA_ERR;
						}
					}
					if (quoted) {
						if (ldns_buffer_available(rd_buf, 1)) {
							ldns_buffer_skip(rd_buf, 1);
						} else {
							done = true;
						}
					}
				} else {
					done = true;
				}
			}
	}
	LDNS_FREE(rd);
	LDNS_FREE(b64);
	ldns_buffer_free(rd_buf);
	ldns_buffer_free(rr_buf);
	LDNS_FREE(rdata);

	if (!question && desc && !was_unknown_rr_format && ldns_rr_rd_count(new) < r_min) {
		ldns_rr_free(new);
		return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
	}

	if (newrr) {
		*newrr = new;
	} else {
		/* Maybe the caller just wanted to see if it would parse? */
		ldns_rr_free(new);
	}
	return LDNS_STATUS_OK;

ldnserror:
	LDNS_FREE(type);
	LDNS_FREE(owner);
	LDNS_FREE(ttl);
	LDNS_FREE(clas);
	LDNS_FREE(rdata);
	LDNS_FREE(rd);
	LDNS_FREE(rd_buf);
	LDNS_FREE(b64);
	ldns_rr_free(new);
    return status;
}


ldns_str2rdf_str(ldns_rdf **rd, const char *str)
{
	uint8_t *data, *dp, ch;

	/* Worst case space requirement. We'll realloc to actual size later. */
	dp = data = LDNS_XMALLOC(uint8_t, strlen(str));
	if (! data) {
		return LDNS_STATUS_MEM_ERR;
	}

	/* Fill data (up to 255 characters) */
	while (parse_char(&ch, &str)) {
		if (dp - data >= 255) {
			LDNS_FREE(data);
			return LDNS_STATUS_INVALID_STR;
		}
		*++dp = ch;
	}
	if (! str) {
		return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
	}
	/* Fix last length byte */
	data[0] = (dp - data) - 1;

	/* Lose the overmeasure */
	data = LDNS_XREALLOC(data, uint8_t, dp - data);
	if (! data) {
		return LDNS_STATUS_MEM_ERR;
	}

	/* Create rdf */
	*rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR,  dp - data, data);
	if (! *rd) {
		LDNS_FREE(data);
		return LDNS_STATUS_MEM_ERR;
	}
	return LDNS_STATUS_OK;
}


ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
{
	/* protocol, followed by bitmap of services */
	struct protoent *protocol;
	char *proto_name = NULL;
	uint8_t protocol_nr;
	struct servent *service;
	uint16_t current_service;

        if(ldns_rdf_size(rdf) < 1) {
                return LDNS_STATUS_WIRE_RDATA_ERR;
        }
	protocol_nr = ldns_rdf_data(rdf)[0];
	protocol = getprotobynumber((int) protocol_nr);
	if (protocol && (protocol->p_name != NULL)) {
		proto_name = protocol->p_name;
		ldns_buffer_printf(output, "%s ", protocol->p_name);
	} else {
		ldns_buffer_printf(output, "%u ", protocol_nr);
	}

#ifdef HAVE_ENDPROTOENT
	endprotoent();
#endif

	for (current_service = 0;
	     current_service < ldns_rdf_size(rdf) * 7; current_service++) {
		if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) {
			service = getservbyport((int) htons(current_service),
			                        proto_name);
			if (service && service->s_name) {
				ldns_buffer_printf(output, "%s ", service->s_name);
			} else {
				ldns_buffer_printf(output, "%u ", current_service);
			}
#ifdef HAVE_ENDSERVENT
			endservent();
#endif
		}
	}
	return ldns_buffer_status(output);
}


ldns_b32_ext2dname(const ldns_rdf *rdf)
{
	size_t size;
	char *b32;
	ldns_rdf *out;
	if(ldns_rdf_size(rdf) == 0)
		return NULL;
        /* remove -1 for the b32-hash-len octet */
	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
        /* add one for the end nul for the string */
	b32 = LDNS_XMALLOC(char, size + 2);
	if (b32) {
		if (ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
				ldns_rdf_size(rdf) - 1, b32, size+1) > 0) {
			b32[size] = '.';
			b32[size+1] = '\0';
			if (ldns_str2rdf_dname(&out, b32) == LDNS_STATUS_OK) {
				LDNS_FREE(b32);
				return out;
			}
		}
		LDNS_FREE(b32);
	}
	return NULL;
}


int get_xattr(const char *fname, stat_x *sxp)
{
	sxp->xattr = new(item_list);
	*sxp->xattr = empty_xattr;

	if (S_ISREG(sxp->st.st_mode) || S_ISDIR(sxp->st.st_mode)) {
		/* Everyone supports this. */
	} else if (S_ISLNK(sxp->st.st_mode)) {
#ifndef NO_SYMLINK_XATTRS
		if (!preserve_links)
#endif
			return 0;
	} else if (IS_SPECIAL(sxp->st.st_mode)) {
#ifndef NO_SPECIAL_XATTRS
		if (!preserve_specials)
#endif
			return 0;
	} else if (IS_DEVICE(sxp->st.st_mode)) {
#ifndef NO_DEVICE_XATTRS
		if (!preserve_devices)
#endif
			return 0;
	} else if (IS_MISSING_FILE(sxp->st))
		return 0;

	if (rsync_xal_get(fname, sxp->xattr) < 0) {
		free_xattr(sxp);
		return -1;
	}
	return 0;
}


int send_xattr(int f, stat_x *sxp)
{
	int ndx = find_matching_xattr(sxp->xattr);

	/* Send 0 (-1 + 1) to indicate that literal xattr data follows. */
	write_varint(f, ndx + 1);

	if (ndx < 0) {
		rsync_xa *rxa;
		int count = sxp->xattr->count;
		write_varint(f, count);
		for (rxa = sxp->xattr->items; count--; rxa++) {
			size_t name_len = rxa->name_len;
			const char *name = rxa->name;
			/* Strip the rsync prefix from disguised namespaces. */
			if (name_len > RPRE_LEN
#ifdef HAVE_LINUX_XATTRS
			 && am_root < 0
#endif
			 && name[RPRE_LEN] != '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
				name += RPRE_LEN;
				name_len -= RPRE_LEN;
			}
#ifndef HAVE_LINUX_XATTRS
			else {
				/* Put everything else in the user namespace. */
				name_len += UPRE_LEN;
			}
#endif
			write_varint(f, name_len);
			write_varint(f, rxa->datum_len);
#ifndef HAVE_LINUX_XATTRS
			if (name_len > rxa->name_len) {
				write_buf(f, USER_PREFIX, UPRE_LEN);
				name_len -= UPRE_LEN;
			}
#endif
			write_buf(f, name, name_len);
			if (rxa->datum_len > MAX_FULL_DATUM)
				write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
			else
				write_bigbuf(f, rxa->datum, rxa->datum_len);
		}
		ndx = rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */
	}

	return ndx;
}


int del_def_xattr_acl(const char *fname)
{
	return sys_lremovexattr(fname, XDEF_ACL_ATTR);
}


static int rsync_xal_get(const char *fname, item_list *xalp)
{
	ssize_t list_len, name_len;
	size_t datum_len, name_offset;
	char *name, *ptr;
#ifdef HAVE_LINUX_XATTRS
	int user_only = am_sender ? 0 : !am_root;
#endif
	rsync_xa *rxa;
	int count;

	/* This puts the name list into the "namebuf" buffer. */
	if ((list_len = get_xattr_names(fname)) < 0)
		return -1;

	for (name = namebuf; list_len > 0; name += name_len) {
		name_len = strlen(name) + 1;
		list_len -= name_len;

		if (saw_xattr_filter) {
			if (name_is_excluded(name, NAME_IS_XATTR, ALL_FILTERS))
				continue;
		}
#ifdef HAVE_LINUX_XATTRS
		/* Choose between ignoring the system namespace or (non-root) ignoring any non-user namespace. */
		else if (user_only ? !HAS_PREFIX(name, USER_PREFIX) : HAS_PREFIX(name, SYSTEM_PREFIX))
			continue;
#endif

		/* No rsync.%FOO attributes are copied w/o 2 -X options. */
		if (name_len > RPRE_LEN && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
			if ((am_sender && preserve_xattrs < 2)
			 || (am_root < 0
			  && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
			   || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
				continue;
		}

		datum_len = name_len; /* Pass extra size to get_xattr_data() */
		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
			return -1;

		if (datum_len > MAX_FULL_DATUM) {
			/* For large datums, we store a flag and a checksum. */
			name_offset = 1 + MAX_DIGEST_LEN;
			sum_init(-1, checksum_seed);
			sum_update(ptr, datum_len);
			free(ptr);

			if (!(ptr = new_array(char, name_offset + name_len)))
				out_of_memory("rsync_xal_get");
			*ptr = XSTATE_ABBREV;
			sum_end(ptr + 1);
		} else
			name_offset = datum_len;

		rxa = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
		rxa->name = ptr + name_offset;
		memcpy(rxa->name, name, name_len);
		rxa->datum = ptr;
		rxa->name_len = name_len;
		rxa->datum_len = datum_len;
	}
	count = xalp->count;
	rxa = xalp->items;
	if (count > 1)
		qsort(rxa, count, sizeof (rsync_xa), rsync_xal_compare_names);
	for (rxa += count-1; count; count--, rxa--)
		rxa->num = count;
	return 0;
}


int copy_xattrs(const char *source, const char *dest)
{
	ssize_t list_len, name_len;
	size_t datum_len;
	char *name, *ptr;
#ifdef HAVE_LINUX_XATTRS
	int user_only = am_sender ? 0 : am_root <= 0;
#endif

	/* This puts the name list into the "namebuf" buffer. */
	if ((list_len = get_xattr_names(source)) < 0)
		return -1;

	for (name = namebuf; list_len > 0; name += name_len) {
		name_len = strlen(name) + 1;
		list_len -= name_len;

		if (saw_xattr_filter) {
			if (name_is_excluded(name, NAME_IS_XATTR, ALL_FILTERS))
				continue;
		}
#ifdef HAVE_LINUX_XATTRS
		/* Choose between ignoring the system namespace or (non-root) ignoring any non-user namespace. */
		else if (user_only ? !HAS_PREFIX(name, USER_PREFIX) : HAS_PREFIX(name, SYSTEM_PREFIX))
			continue;
#endif

		datum_len = 0;
		if (!(ptr = get_xattr_data(source, name, &datum_len, 0)))
			return -1;
		if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
			int save_errno = errno ? errno : EINVAL;
			rsyserr(FERROR_XFER, errno,
				"copy_xattrs: lsetxattr(%s,\"%s\") failed",
				full_fname(dest), name);
			errno = save_errno;
			return -1;
		}
		free(ptr);
	}

	return 0;
}


static void add_pbf_warning(Scanner *s, char *error, char *sptr, char *cptr)
{
	s->errors->warning_count++;
	s->errors->warning_messages = timelib_realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
	s->errors->warning_messages[s->errors->warning_count - 1].position = cptr - sptr;
	s->errors->warning_messages[s->errors->warning_count - 1].character = *cptr;
	s->errors->warning_messages[s->errors->warning_count - 1].message = timelib_strdup(error);
}


static timelib_sll timelib_lookup_relative_text(char **ptr, int *behavior)
{
	char *word;
	char *begin = *ptr, *end;
	timelib_sll  value = 0;
	const timelib_lookup_table *tp;

	while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
		++*ptr;
	}
	end = *ptr;
	word = timelib_calloc(1, end - begin + 1);
	memcpy(word, begin, end - begin);

	for (tp = timelib_reltext_lookup; tp->name; tp++) {
		if (strcasecmp(word, tp->name) == 0) {
			value = tp->value;
			*behavior = tp->type;
		}
	}

	timelib_free(word);
	return value;
}


static timelib_sll timelib_get_relative_text(char **ptr, int *behavior)
{
	while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '/') {
		++*ptr;
	}
	return timelib_lookup_relative_text(ptr, behavior);
}


static void timelib_skip_day_suffix(char **ptr)
{
	if (isspace(**ptr)) {
		return;
	}
	if (!strncasecmp(*ptr, "nd", 2) || !strncasecmp(*ptr, "rd", 2) ||!strncasecmp(*ptr, "st", 2) || !strncasecmp(*ptr, "th", 2)) {
		*ptr += 2;
	}
}


const SyscallFilterSet *syscall_filter_set_find(const char *name) {
        unsigned i;

        if (isempty(name) || name[0] != '@')
                return NULL;

        for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++)
                if (streq(syscall_filter_sets[i].name, name))
                        return syscall_filter_sets + i;

        return NULL;
}


static void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
				   const u8 *data, unsigned int len)
{
	struct drbg_state *drbg = crypto_rng_ctx(tfm);

	mutex_lock(&drbg->drbg_mutex);
	drbg_string_fill(&drbg->test_data, data, len);
	mutex_unlock(&drbg->drbg_mutex);
}


static int drbg_kcapi_seed(struct crypto_rng *tfm,
			   const u8 *seed, unsigned int slen)
{
	struct drbg_state *drbg = crypto_rng_ctx(tfm);
	struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
	bool pr = false;
	struct drbg_string string;
	struct drbg_string *seed_string = NULL;
	int coreref = 0;

	drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
			      &pr);
	if (0 < slen) {
		drbg_string_fill(&string, seed, slen);
		seed_string = &string;
	}

	return drbg_instantiate(drbg, seed_string, coreref, pr);
}


static int drbg_init_hash_kernel(struct drbg_state *drbg)
{
	struct sdesc *sdesc;
	struct crypto_shash *tfm;

	tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
	if (IS_ERR(tfm)) {
		pr_info("DRBG: could not allocate digest TFM handle\n");
		return PTR_ERR(tfm);
	}
	BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
	sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
			GFP_KERNEL);
	if (!sdesc) {
		crypto_free_shash(tfm);
		return -ENOMEM;
	}

	sdesc->shash.tfm = tfm;
	sdesc->shash.flags = 0;
	drbg->priv_data = sdesc;
	return 0;
}


int checkClientOutputBufferLimits(client *c) {
    int soft = 0, hard = 0, class;
    unsigned long used_mem = getClientOutputBufferMemoryUsage(c);

    class = getClientType(c);
    /* For the purpose of output buffer limiting, masters are handled
     * like normal clients. */
    if (class == CLIENT_TYPE_MASTER) class = CLIENT_TYPE_NORMAL;

    if (server.client_obuf_limits[class].hard_limit_bytes &&
        used_mem >= server.client_obuf_limits[class].hard_limit_bytes)
        hard = 1;
    if (server.client_obuf_limits[class].soft_limit_bytes &&
        used_mem >= server.client_obuf_limits[class].soft_limit_bytes)
        soft = 1;

    /* We need to check if the soft limit is reached continuously for the
     * specified amount of seconds. */
    if (soft) {
        if (c->obuf_soft_limit_reached_time == 0) {
            c->obuf_soft_limit_reached_time = server.unixtime;
            soft = 0; /* First time we see the soft limit reached */
        } else {
            time_t elapsed = server.unixtime - c->obuf_soft_limit_reached_time;

            if (elapsed <=
                server.client_obuf_limits[class].soft_limit_seconds) {
                soft = 0; /* The client still did not reached the max number of
                             seconds for the soft limit to be considered
                             reached. */
            }
        }
    } else {
        c->obuf_soft_limit_reached_time = 0;
    }
    return soft || hard;
}


int clientHasPendingReplies(client *c) {
    return c->bufpos || listLength(c->reply);
}


unsigned long getClientOutputBufferMemoryUsage(client *c) {
    unsigned long list_item_size = sizeof(listNode)+sizeof(robj);

    return c->reply_bytes + (list_item_size*listLength(c->reply));
}


void copyClientOutputBuffer(client *dst, client *src) {
    listRelease(dst->reply);
    dst->reply = listDup(src->reply);
    memcpy(dst->buf,src->buf,src->bufpos);
    dst->bufpos = src->bufpos;
    dst->reply_bytes = src->reply_bytes;
}


void rewriteClientCommandArgument(client *c, int i, robj *newval) {
    robj *oldval;

    if (i >= c->argc) {
        c->argv = zrealloc(c->argv,sizeof(robj*)*(i+1));
        c->argc = i+1;
        c->argv[i] = NULL;
    }
    oldval = c->argv[i];
    c->argv[i] = newval;
    incrRefCount(newval);
    if (oldval) decrRefCount(oldval);

    /* If this is the command name make sure to fix c->cmd. */
    if (i == 0) {
        c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr);
        serverAssertWithInfo(c,NULL,c->cmd != NULL);
    }
}


char *getClientTypeName(int class) {
    switch(class) {
    case CLIENT_TYPE_NORMAL: return "normal";
    case CLIENT_TYPE_SLAVE:  return "slave";
    case CLIENT_TYPE_PUBSUB: return "pubsub";
    case CLIENT_TYPE_MASTER: return "master";
    default:                       return NULL;
    }
}


void addReplyLongLong(client *c, long long ll) {
    if (ll == 0)
        addReply(c,shared.czero);
    else if (ll == 1)
        addReply(c,shared.cone);
    else
        addReplyLongLongWithPrefix(c,ll,':');
}


void disconnectSlaves(void) {
    while (listLength(server.slaves)) {
        listNode *ln = listFirst(server.slaves);
        freeClient((client*)ln->value);
    }
}


void addReplyStatus(client *c, const char *status) {
    addReplyStatusLength(c,status,strlen(status));
}


int main(int argc, char **argv)
{
	char c;

	int i = unpack_bz2_stream(0, 1);
	if (i < 0)
		fprintf(stderr, "%s\n", bunzip_errors[-i]);
	else if (read(STDIN_FILENO, &c, 1))
		fprintf(stderr, "Trailing garbage ignored\n");
	return -i;
}


int sum_end(char *sum)
{
	switch (cursum_type) {
	  case CSUM_MD5:
		md5_result(&md, (uchar *)sum);
		break;
	  case CSUM_MD4:
	  case CSUM_MD4_OLD:
		mdfour_update(&md, (uchar *)md.buffer, sumresidue);
		mdfour_result(&md, (uchar *)sum);
		break;
	  case CSUM_MD4_BUSTED:
	  case CSUM_MD4_ARCHAIC:
		if (sumresidue)
			mdfour_update(&md, (uchar *)md.buffer, sumresidue);
		mdfour_result(&md, (uchar *)sum);
		break;
	  case CSUM_NONE:
		*sum = '\0';
		break;
	}

	return csum_len_for_type(cursum_type);
}


int parse_csum_name(const char *name, int len)
{
	if (len < 0 && name)
		len = strlen(name);

	if (!name || (len == 4 && strncasecmp(name, "auto", 4) == 0)) {
		if (protocol_version >= 30)
			return CSUM_MD5;
		if (protocol_version >= 27)
			return CSUM_MD4_OLD;
		if (protocol_version >= 21)
			return CSUM_MD4_BUSTED;
		return CSUM_MD4_ARCHAIC;
	}
	if (len == 3 && strncasecmp(name, "md4", 3) == 0)
		return CSUM_MD4;
	if (len == 3 && strncasecmp(name, "md5", 3) == 0)
		return CSUM_MD5;
	if (len == 4 && strncasecmp(name, "none", 4) == 0)
		return CSUM_NONE;

	rprintf(FERROR, "unknown checksum name: %s\n", name);
	exit_cleanup(RERR_UNSUPPORTED);
}


char *auth_server(int f_in, int f_out, int module, const char *host,
		  const char *addr, const char *leader)
{
	char *users = lp_auth_users(module);
	char challenge[MAX_DIGEST_LEN*2];
	char line[BIGPATHBUFLEN];
	char **auth_uid_groups = NULL;
	int auth_uid_groups_cnt = -1;
	const char *err = NULL;
	int group_match = -1;
	char *tok, *pass;
	char opt_ch = '\0';

	/* if no auth list then allow anyone in! */
	if (!users || !*users)
		return "";

	if (protocol_version < 21) { /* Don't allow a weak checksum for the password. */
		rprintf(FERROR, "ERROR: protocol version is too old!\n");
		exit_cleanup(RERR_PROTOCOL);
	}

	gen_challenge(addr, challenge);

	io_printf(f_out, "%s%s\n", leader, challenge);

	if (!read_line_old(f_in, line, sizeof line, 0)
	 || (pass = strchr(line, ' ')) == NULL) {
		rprintf(FLOG, "auth failed on module %s from %s (%s): "
			"invalid challenge response\n",
			lp_name(module), host, addr);
		return NULL;
	}
	*pass++ = '\0';

	if (!(users = strdup(users)))
		out_of_memory("auth_server");

	for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
		char *opts;
		/* See if the user appended :deny, :ro, or :rw. */
		if ((opts = strchr(tok, ':')) != NULL) {
			*opts++ = '\0';
			opt_ch = isUpper(opts) ? toLower(opts) : *opts;
			if (opt_ch == 'r') { /* handle ro and rw */
				opt_ch = isUpper(opts+1) ? toLower(opts+1) : opts[1];
				if (opt_ch == 'o')
					opt_ch = 'r';
				else if (opt_ch != 'w')
					opt_ch = '\0';
			} else if (opt_ch != 'd') /* if it's not deny, ignore it */
				opt_ch = '\0';
		} else
			opt_ch = '\0';
		if (*tok != '@') {
			/* Match the username */
			if (wildmatch(tok, line))
				break;
		} else {
#ifdef HAVE_GETGROUPLIST
			int j;
			/* See if authorizing user is a real user, and if so, see
			 * if it is in a group that matches tok+1 wildmat. */
			if (auth_uid_groups_cnt < 0) {
				item_list gid_list = EMPTY_ITEM_LIST;
				uid_t auth_uid;
				if (!user_to_uid(line, &auth_uid, False)
				 || getallgroups(auth_uid, &gid_list) != NULL)
					auth_uid_groups_cnt = 0;
				else {
					gid_t *gid_array = gid_list.items;
					auth_uid_groups_cnt = gid_list.count;
					if ((auth_uid_groups = new_array(char *, auth_uid_groups_cnt)) == NULL)
						out_of_memory("auth_server");
					for (j = 0; j < auth_uid_groups_cnt; j++)
						auth_uid_groups[j] = gid_to_group(gid_array[j]);
				}
			}
			for (j = 0; j < auth_uid_groups_cnt; j++) {
				if (auth_uid_groups[j] && wildmatch(tok+1, auth_uid_groups[j])) {
					group_match = j;
					break;
				}
			}
			if (group_match >= 0)
				break;
#else
			rprintf(FLOG, "your computer doesn't support getgrouplist(), so no @group authorization is possible.\n");
#endif
		}
	}

	free(users);

	if (!tok)
		err = "no matching rule";
	else if (opt_ch == 'd')
		err = "denied by rule";
	else {
		char *group = group_match >= 0 ? auth_uid_groups[group_match] : NULL;
		err = check_secret(module, line, group, challenge, pass);
	}

	memset(challenge, 0, sizeof challenge);
	memset(pass, 0, strlen(pass));

	if (auth_uid_groups) {
		int j;
		for (j = 0; j < auth_uid_groups_cnt; j++) {
			if (auth_uid_groups[j])
				free(auth_uid_groups[j]);
		}
		free(auth_uid_groups);
	}

	if (err) {
		rprintf(FLOG, "auth failed on module %s from %s (%s) for %s: %s\n",
			lp_name(module), host, addr, line, err);
		return NULL;
	}

	if (opt_ch == 'r')
		read_only = 1;
	else if (opt_ch == 'w')
		read_only = 0;

	return strdup(line);
}


static bool encrypt_des(const unsigned char *in, unsigned char *out,
                        const unsigned char *key_56)
{
  const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
  PK11SlotInfo *slot = NULL;
  char key[8];                                /* expanded 64 bit key */
  SECItem key_item;
  PK11SymKey *symkey = NULL;
  SECItem *param = NULL;
  PK11Context *ctx = NULL;
  int out_len;                                /* not used, required by NSS */
  bool rv = FALSE;

  /* use internal slot for DES encryption (requires NSS to be initialized) */
  slot = PK11_GetInternalKeySlot();
  if(!slot)
    return FALSE;

  /* Expand the 56-bit key to 64-bits */
  extend_key_56_to_64(key_56, key);

  /* Set the key parity to odd */
  Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));

  /* Import the key */
  key_item.data = (unsigned char *)key;
  key_item.len = sizeof(key);
  symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
                             &key_item, NULL);
  if(!symkey)
    goto fail;

  /* Create the DES encryption context */
  param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
  if(!param)
    goto fail;
  ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
  if(!ctx)
    goto fail;

  /* Perform the encryption */
  if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
                                 (unsigned char *)in, /* inbuflen */ 8)
      && SECSuccess == PK11_Finalize(ctx))
    rv = /* all OK */ TRUE;

fail:
  /* cleanup */
  if(ctx)
    PK11_DestroyContext(ctx, PR_TRUE);
  if(symkey)
    PK11_FreeSymKey(symkey);
  if(param)
    SECITEM_FreeItem(param, PR_TRUE);
  PK11_FreeSlot(slot);
  return rv;
}


MessageCompressorManager::MessageCompressorManager(MessageCompressorRegistry* factory)
    : _registry{factory} {}


TEST(MessageCompressorManager, FullNormalCompression) {
    auto registry = buildRegistry();
    MessageCompressorManager clientManager(&registry);
    MessageCompressorManager serverManager(&registry);

    BSONObjBuilder clientOutput;
    clientManager.clientBegin(&clientOutput);
    auto clientObj = clientOutput.done();
    checkNegotiationResult(clientObj, {"noop"});

    BSONObjBuilder serverOutput;
    serverManager.serverNegotiate(clientObj, &serverOutput);
    auto serverObj = serverOutput.done();
    checkNegotiationResult(serverObj, {"noop"});

    clientManager.clientFinish(serverObj);
}


TEST(MessageCompressorManager, MessageSizeTooLarge) {
    auto registry = buildRegistry();
    MessageCompressorManager compManager(&registry);

    auto badMessageBuffer = SharedBuffer::allocate(128);
    MsgData::View badMessage(badMessageBuffer.get());
    badMessage.setId(1);
    badMessage.setResponseToMsgId(0);
    badMessage.setOperation(dbCompressed);
    badMessage.setLen(128);

    DataRangeCursor cursor(badMessage.data(), badMessage.data() + badMessage.dataLen());
    uassertStatusOK(cursor.writeAndAdvance<LittleEndian<int32_t>>(dbQuery));
    uassertStatusOK(cursor.writeAndAdvance<LittleEndian<int32_t>>(MaxMessageSizeBytes + 1));
    uassertStatusOK(
        cursor.writeAndAdvance<LittleEndian<uint8_t>>(registry.getCompressor("noop")->getId()));

    auto status = compManager.decompressMessage(Message(badMessageBuffer)).getStatus();
    ASSERT_NOT_OK(status);
}


SnappySourceSinkException(Status status) : DBException(status.reason(), status.code()) {}


    CompressionHeader(int32_t _opcode, int32_t _size, uint8_t _id)
        : originalOpCode{_opcode}, uncompressedSize{_size}, compressorId{_id} {}


    char* GetAppendBufferVariable(size_t minSize,
                                  size_t desiredSizeHint,
                                  char* scratch,
                                  size_t scratchSize,
                                  size_t* allocatedSize) {
        if (desiredSizeHint > _cursor.length() || minSize > _cursor.length()) {
            _scratch.resize(desiredSizeHint);
            *allocatedSize = _scratch.size();
            return _scratch.data();
        }

        *allocatedSize = _cursor.length();
        return const_cast<char*>(_cursor.data());
    }


static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
					void (*release)(struct dvb_frontend *fe))
{
	if (release) {
		release(fe);
#ifdef CONFIG_MEDIA_ATTACH
		dvb_detach(release);
#endif
	}
}


int dvb_frontend_resume(struct dvb_frontend *fe)
{
	struct dvb_frontend_private *fepriv = fe->frontend_priv;
	int ret = 0;

	dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
			fe->id);

	fe->exit = DVB_FE_DEVICE_RESUME;
	if (fe->ops.init)
		ret = fe->ops.init(fe);

	if (fe->ops.tuner_ops.resume)
		ret = fe->ops.tuner_ops.resume(fe);
	else if (fe->ops.tuner_ops.init)
		ret = fe->ops.tuner_ops.init(fe);

	if (fe->ops.set_tone && fepriv->tone != -1)
		fe->ops.set_tone(fe, fepriv->tone);
	if (fe->ops.set_voltage && fepriv->voltage != -1)
		fe->ops.set_voltage(fe, fepriv->voltage);

	fe->exit = DVB_FE_NO_EXIT;
	fepriv->state = FESTATE_RETUNE;
	dvb_frontend_wakeup(fe);

	return ret;
}


static int emulate_delivery_system(struct dvb_frontend *fe, u32 delsys)
{
	int i;
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;

	c->delivery_system = delsys;

	/*
	 * If the call is for ISDB-T, put it into full-seg, auto mode, TV
	 */
	if (c->delivery_system == SYS_ISDBT) {
		dev_dbg(fe->dvb->device,
			"%s: Using defaults for SYS_ISDBT\n",
			__func__);

		if (!c->bandwidth_hz)
			c->bandwidth_hz = 6000000;

		c->isdbt_partial_reception = 0;
		c->isdbt_sb_mode = 0;
		c->isdbt_sb_subchannel = 0;
		c->isdbt_sb_segment_idx = 0;
		c->isdbt_sb_segment_count = 0;
		c->isdbt_layer_enabled = 7;
		for (i = 0; i < 3; i++) {
			c->layer[i].fec = FEC_AUTO;
			c->layer[i].modulation = QAM_AUTO;
			c->layer[i].interleaving = 0;
			c->layer[i].segment_count = 0;
		}
	}
	dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
		__func__, c->delivery_system);

	return 0;
}


int dvb_unregister_frontend(struct dvb_frontend* fe)
{
	struct dvb_frontend_private *fepriv = fe->frontend_priv;
	dev_dbg(fe->dvb->device, "%s:\n", __func__);

	mutex_lock(&frontend_mutex);
	dvb_frontend_stop(fe);
	dvb_remove_device(fepriv->dvbdev);

	/* fe is invalid now */
	mutex_unlock(&frontend_mutex);
	dvb_frontend_put(fe);
	return 0;
}


static int dtv_property_cache_sync(struct dvb_frontend *fe,
				   struct dtv_frontend_properties *c,
				   const struct dvb_frontend_parameters *p)
{
	c->frequency = p->frequency;
	c->inversion = p->inversion;

	switch (dvbv3_type(c->delivery_system)) {
	case DVBV3_QPSK:
		dev_dbg(fe->dvb->device, "%s: Preparing QPSK req\n", __func__);
		c->symbol_rate = p->u.qpsk.symbol_rate;
		c->fec_inner = p->u.qpsk.fec_inner;
		break;
	case DVBV3_QAM:
		dev_dbg(fe->dvb->device, "%s: Preparing QAM req\n", __func__);
		c->symbol_rate = p->u.qam.symbol_rate;
		c->fec_inner = p->u.qam.fec_inner;
		c->modulation = p->u.qam.modulation;
		break;
	case DVBV3_OFDM:
		dev_dbg(fe->dvb->device, "%s: Preparing OFDM req\n", __func__);

		switch (p->u.ofdm.bandwidth) {
		case BANDWIDTH_10_MHZ:
			c->bandwidth_hz = 10000000;
			break;
		case BANDWIDTH_8_MHZ:
			c->bandwidth_hz = 8000000;
			break;
		case BANDWIDTH_7_MHZ:
			c->bandwidth_hz = 7000000;
			break;
		case BANDWIDTH_6_MHZ:
			c->bandwidth_hz = 6000000;
			break;
		case BANDWIDTH_5_MHZ:
			c->bandwidth_hz = 5000000;
			break;
		case BANDWIDTH_1_712_MHZ:
			c->bandwidth_hz = 1712000;
			break;
		case BANDWIDTH_AUTO:
			c->bandwidth_hz = 0;
		}

		c->code_rate_HP = p->u.ofdm.code_rate_HP;
		c->code_rate_LP = p->u.ofdm.code_rate_LP;
		c->modulation = p->u.ofdm.constellation;
		c->transmission_mode = p->u.ofdm.transmission_mode;
		c->guard_interval = p->u.ofdm.guard_interval;
		c->hierarchy = p->u.ofdm.hierarchy_information;
		break;
	case DVBV3_ATSC:
		dev_dbg(fe->dvb->device, "%s: Preparing ATSC req\n", __func__);
		c->modulation = p->u.vsb.modulation;
		if (c->delivery_system == SYS_ATSCMH)
			break;
		if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
			c->delivery_system = SYS_ATSC;
		else
			c->delivery_system = SYS_DVBC_ANNEX_B;
		break;
	case DVBV3_UNKNOWN:
		dev_err(fe->dvb->device,
				"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
				__func__, c->delivery_system);
		return -EINVAL;
	}

	return 0;
}


void free_transhuge_page(struct page *page)
{
	struct pglist_data *pgdata = NODE_DATA(page_to_nid(page));
	unsigned long flags;

	spin_lock_irqsave(&pgdata->split_queue_lock, flags);
	if (!list_empty(page_deferred_list(page))) {
		pgdata->split_queue_len--;
		list_del(page_deferred_list(page));
	}
	spin_unlock_irqrestore(&pgdata->split_queue_lock, flags);
	free_compound_page(page);
}


static ssize_t enabled_show(struct kobject *kobj,
			    struct kobj_attribute *attr, char *buf)
{
	if (test_bit(TRANSPARENT_HUGEPAGE_FLAG, &transparent_hugepage_flags))
		return sprintf(buf, "[always] madvise never\n");
	else if (test_bit(TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG, &transparent_hugepage_flags))
		return sprintf(buf, "always [madvise] never\n");
	else
		return sprintf(buf, "always madvise [never]\n");
}


int total_mapcount(struct page *page)
{
	int i, compound, ret;

	VM_BUG_ON_PAGE(PageTail(page), page);

	if (likely(!PageCompound(page)))
		return atomic_read(&page->_mapcount) + 1;

	compound = compound_mapcount(page);
	if (PageHuge(page))
		return compound;
	ret = compound;
	for (i = 0; i < HPAGE_PMD_NR; i++)
		ret += atomic_read(&page[i]._mapcount) + 1;
	/* File pages has compound_mapcount included in _mapcount */
	if (!PageAnon(page))
		return ret - compound * HPAGE_PMD_NR;
	if (PageDoubleMap(page))
		ret -= HPAGE_PMD_NR;
	return ret;
}


static ssize_t debug_cow_show(struct kobject *kobj,
				struct kobj_attribute *attr, char *buf)
{
	return single_hugepage_flag_show(kobj, attr, buf,
				TRANSPARENT_HUGEPAGE_DEBUG_COW_FLAG);
}


static void insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
		pud_t *pud, pfn_t pfn, pgprot_t prot, bool write)
{
	struct mm_struct *mm = vma->vm_mm;
	pud_t entry;
	spinlock_t *ptl;

	ptl = pud_lock(mm, pud);
	entry = pud_mkhuge(pfn_t_pud(pfn, prot));
	if (pfn_t_devmap(pfn))
		entry = pud_mkdevmap(entry);
	if (write) {
		entry = pud_mkyoung(pud_mkdirty(entry));
		entry = maybe_pud_mkwrite(entry, vma);
	}
	set_pud_at(mm, addr, pud, entry);
	update_mmu_cache_pud(vma, addr, pud);
	spin_unlock(ptl);
}


static void touch_pmd(struct vm_area_struct *vma, unsigned long addr,
		pmd_t *pmd, int flags)
{
	pmd_t _pmd;

	_pmd = pmd_mkyoung(*pmd);
	if (flags & FOLL_WRITE)
		_pmd = pmd_mkdirty(_pmd);
	if (pmdp_set_access_flags(vma, addr & HPAGE_PMD_MASK,
				pmd, _pmd, flags & FOLL_WRITE))
		update_mmu_cache_pmd(vma, addr, pmd);
}


static unsigned long shrink_huge_zero_page_scan(struct shrinker *shrink,
				       struct shrink_control *sc)
{
	if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) {
		struct page *zero_page = xchg(&huge_zero_page, NULL);
		BUG_ON(zero_page == NULL);
		__free_pages(zero_page, compound_order(zero_page));
		return HPAGE_PMD_NR;
	}

	return 0;
}


unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,
		loff_t off, unsigned long flags, unsigned long size)
{
	unsigned long addr;
	loff_t off_end = off + len;
	loff_t off_align = round_up(off, size);
	unsigned long len_pad;

	if (off_end <= off_align || (off_end - off_align) < size)
		return 0;

	len_pad = len + size;
	if (len_pad < len || (off + len_pad) < off)
		return 0;

	addr = current->mm->get_unmapped_area(filp, 0, len_pad,
					      off >> PAGE_SHIFT, flags);
	if (IS_ERR_VALUE(addr))
		return 0;

	addr += (off - addr) & (size - 1);
	return addr;
}


void prep_transhuge_page(struct page *page)
{
	/*
	 * we use page->mapping and page->indexlru in second tail page
	 * as list_head: assuming THP order >= 2
	 */

	INIT_LIST_HEAD(page_deferred_list(page));
	set_compound_page_dtor(page, TRANSHUGE_PAGE_DTOR);
}


static int nbd_co_send_reply(NBDRequestData *req, NBDReply *reply, int len,
                             Error **errp)
{
    NBDClient *client = req->client;
    int ret;

    g_assert(qemu_in_coroutine());

    trace_nbd_co_send_reply(reply->handle, reply->error, len);

    qemu_co_mutex_lock(&client->send_lock);
    client->send_coroutine = qemu_coroutine_self();

    if (!len) {
        ret = nbd_send_reply(client->ioc, reply, errp);
    } else {
        qio_channel_set_cork(client->ioc, true);
        ret = nbd_send_reply(client->ioc, reply, errp);
        if (ret == 0) {
            ret = nbd_write(client->ioc, req->data, len, errp);
            if (ret < 0) {
                ret = -EIO;
            }
        }
        qio_channel_set_cork(client->ioc, false);
    }

    client->send_coroutine = NULL;
    qemu_co_mutex_unlock(&client->send_lock);
    return ret;
}


add_host_info_for_log(gstring * g)
{
if (sender_fullhost)
  {
  if (LOGGING(dnssec) && sender_host_dnssec)	/*XXX sender_helo_dnssec? */
    g = string_catn(g, US" DS", 3);
  g = string_append(g, 2, US" H=", sender_fullhost);
  if (LOGGING(incoming_interface) && interface_address != NULL)
    {
    g = string_cat(g,
      string_sprintf(" I=[%s]:%d", interface_address, interface_port));
    }
  }
if (tcp_in_fastopen && !tcp_in_fastopen_logged)
  {
  g = string_catn(g, US" TFO", 4);
  tcp_in_fastopen_logged = TRUE;
  }
if (sender_ident)
  g = string_append(g, 2, US" U=", sender_ident);
if (received_protocol)
  g = string_append(g, 2, US" P=", received_protocol);
return g;
}


receive_add_recipient(uschar *recipient, int pno)
{
if (recipients_count >= recipients_list_max)
  {
  recipient_item *oldlist = recipients_list;
  int oldmax = recipients_list_max;
  recipients_list_max = recipients_list_max? 2*recipients_list_max : 50;
  recipients_list = store_get(recipients_list_max * sizeof(recipient_item));
  if (oldlist != NULL)
    memcpy(recipients_list, oldlist, oldmax * sizeof(recipient_item));
  }

recipients_list[recipients_count].address = recipient;
recipients_list[recipients_count].pno = pno;
#ifdef EXPERIMENTAL_BRIGHTMAIL
recipients_list[recipients_count].bmi_optin = bmi_current_optin;
/* reset optin string pointer for next recipient */
bmi_current_optin = NULL;
#endif
recipients_list[recipients_count].orcpt = NULL;
recipients_list[recipients_count].dsn_flags = 0;
recipients_list[recipients_count++].errors_to = NULL;
}


give_local_error(int errcode, uschar *text1, uschar *text2, int error_rc,
  FILE *f, header_line *hptr)
{
if (error_handling == ERRORS_SENDER)
  {
  error_block eblock;
  eblock.next = NULL;
  eblock.text1 = text1;
  eblock.text2 = US"";
  if (!moan_to_sender(errcode, &eblock, hptr, f, FALSE))
    error_rc = EXIT_FAILURE;
  }
else
  fprintf(stderr, "exim: %s%s\n", text2, text1);  /* Sic */
(void)fclose(f);
exim_exit(error_rc, US"");
}


static int call_disconnect_if_dead(struct connectdata *conn,
                                      void *param)
{
  struct Curl_easy* data = (struct Curl_easy*)param;
  disconnect_if_dead(conn, data);
  return 0; /* continue iteration */
}


static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
{
  struct curl_llist_element *curr = pipeline->head;
  if(curr) {
    return (struct Curl_easy *) curr->ptr;
  }

  return NULL;
}


find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
                                      struct connectbundle *bundle)
{
  struct curl_llist_element *curr;
  timediff_t highscore = -1;
  timediff_t score;
  struct curltime now;
  struct connectdata *conn_candidate = NULL;
  struct connectdata *conn;

  (void)data;

  now = Curl_now();

  curr = bundle->conn_list.head;
  while(curr) {
    conn = curr->ptr;

    if(!conn->inuse) {
      /* Set higher score for the age passed since the connection was used */
      score = Curl_timediff(now, conn->now);

      if(score > highscore) {
        highscore = score;
        conn_candidate = conn;
      }
    }
    curr = curr->next;
  }

  return conn_candidate;
}


void uprobe_copy_process(struct task_struct *t, unsigned long flags)
{
	struct uprobe_task *utask = current->utask;
	struct mm_struct *mm = current->mm;
	struct xol_area *area;

	t->utask = NULL;

	if (!utask || !utask->return_instances)
		return;

	if (mm == t->mm && !(flags & CLONE_VFORK))
		return;

	if (dup_utask(t, utask))
		return uprobe_warn(t, "dup ret instances");

	/* The task can fork() after dup_xol_work() fails */
	area = mm->uprobes_state.xol_area;
	if (!area)
		return uprobe_warn(t, "dup xol area");

	if (mm == t->mm)
		return;

	t->utask->dup_xol_addr = area->vaddr;
	init_task_work(&t->utask->dup_xol_work, dup_xol_work);
	task_work_add(t, &t->utask->dup_xol_work, true);
}


void uprobe_start_dup_mmap(void)
{
	percpu_down_read(&dup_mmap_sem);
}


static unsigned long get_trampoline_vaddr(void)
{
	struct xol_area *area;
	unsigned long trampoline_vaddr = -1;

	area = current->mm->uprobes_state.xol_area;
	smp_read_barrier_depends();
	if (area)
		trampoline_vaddr = area->vaddr;

	return trampoline_vaddr;
}


unsigned long uprobe_get_trap_addr(struct pt_regs *regs)
{
	struct uprobe_task *utask = current->utask;

	if (unlikely(utask && utask->active_uprobe))
		return utask->vaddr;

	return instruction_pointer(regs);
}


static unsigned long xol_take_insn_slot(struct xol_area *area)
{
	unsigned long slot_addr;
	int slot_nr;

	do {
		slot_nr = find_first_zero_bit(area->bitmap, UINSNS_PER_PAGE);
		if (slot_nr < UINSNS_PER_PAGE) {
			if (!test_and_set_bit(slot_nr, area->bitmap))
				break;

			slot_nr = UINSNS_PER_PAGE;
			continue;
		}
		wait_event(area->wq, (atomic_read(&area->slot_count) < UINSNS_PER_PAGE));
	} while (slot_nr >= UINSNS_PER_PAGE);

	slot_addr = area->vaddr + (slot_nr * UPROBE_XOL_SLOT_BYTES);
	atomic_inc(&area->slot_count);

	return slot_addr;
}


static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc)
{
	struct uprobe_consumer **con;
	bool ret = false;

	down_write(&uprobe->consumer_rwsem);
	for (con = &uprobe->consumers; *con; con = &(*con)->next) {
		if (*con == uc) {
			*con = uc->next;
			ret = true;
			break;
		}
	}
	up_write(&uprobe->consumer_rwsem);

	return ret;
}


bool __weak arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
					struct pt_regs *regs)
{
	return true;
}


static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
				struct mm_struct *mm, unsigned long vaddr)
{
	int ret = 0;

	if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
		return ret;

	/* TODO: move this into _register, until then we abuse this sem. */
	down_write(&uprobe->consumer_rwsem);
	if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
		goto out;

	ret = copy_insn(uprobe, file);
	if (ret)
		goto out;

	ret = -ENOTSUPP;
	if (is_trap_insn((uprobe_opcode_t *)&uprobe->arch.insn))
		goto out;

	ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
	if (ret)
		goto out;

	/* uprobe_write_opcode() assumes we don't cross page boundary */
	BUG_ON((uprobe->offset & ~PAGE_MASK) +
			UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);

	smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
	set_bit(UPROBE_COPY_INSN, &uprobe->flags);

 out:
	up_write(&uprobe->consumer_rwsem);

	return ret;
}


static int __uprobe_register(struct uprobe *uprobe, struct uprobe_consumer *uc)
{
	consumer_add(uprobe, uc);
	return register_for_each_vma(uprobe, uc);
}


void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
				  void *src, unsigned long len)
{
	/* Initialize the slot */
	copy_to_page(page, vaddr, src, len);

	/*
	 * We probably need flush_icache_user_range() but it needs vma.
	 * This should work on most of architectures by default. If
	 * architecture needs to do something different it can define
	 * its own version of the function.
	 */
	flush_dcache_page(page);
}


string_replace(PyStringObject *self, PyObject *args)
{
    Py_ssize_t count = -1;
    PyObject *from, *to;
    const char *from_s, *to_s;
    Py_ssize_t from_len, to_len;

    if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
        return NULL;

    if (PyString_Check(from)) {
        from_s = PyString_AS_STRING(from);
        from_len = PyString_GET_SIZE(from);
    }
#ifdef Py_USING_UNICODE
    if (PyUnicode_Check(from))
        return PyUnicode_Replace((PyObject *)self,
                                 from, to, count);
#endif
    else if (PyObject_AsCharBuffer(from, &from_s, &from_len))
        return NULL;

    if (PyString_Check(to)) {
        to_s = PyString_AS_STRING(to);
        to_len = PyString_GET_SIZE(to);
    }
#ifdef Py_USING_UNICODE
    else if (PyUnicode_Check(to))
        return PyUnicode_Replace((PyObject *)self,
                                 from, to, count);
#endif
    else if (PyObject_AsCharBuffer(to, &to_s, &to_len))
        return NULL;

    return (PyObject *)replace((PyStringObject *) self,
                               from_s, from_len,
                               to_s, to_len, count);
}


PyString_Size(register PyObject *op)
{
    if (!PyString_Check(op))
        return string_getsize(op);
    return Py_SIZE(op);
}


PyString_Repr(PyObject *obj, int smartquotes)
{
    register PyStringObject* op = (PyStringObject*) obj;
    size_t newsize;
    PyObject *v;
    if (Py_SIZE(op) > (PY_SSIZE_T_MAX - 2)/4) {
        PyErr_SetString(PyExc_OverflowError,
            "string is too large to make repr");
        return NULL;
    }
    newsize = 2 + 4*Py_SIZE(op);
    v = PyString_FromStringAndSize((char *)NULL, newsize);
    if (v == NULL) {
        return NULL;
    }
    else {
        register Py_ssize_t i;
        register char c;
        register char *p;
        int quote;

        /* figure out which quote to use; single is preferred */
        quote = '\'';
        if (smartquotes &&
            memchr(op->ob_sval, '\'', Py_SIZE(op)) &&
            !memchr(op->ob_sval, '"', Py_SIZE(op)))
            quote = '"';

        p = PyString_AS_STRING(v);
        *p++ = quote;
        for (i = 0; i < Py_SIZE(op); i++) {
            /* There's at least enough room for a hex escape
               and a closing quote. */
            assert(newsize - (p - PyString_AS_STRING(v)) >= 5);
            c = op->ob_sval[i];
            if (c == quote || c == '\\')
                *p++ = '\\', *p++ = c;
            else if (c == '\t')
                *p++ = '\\', *p++ = 't';
            else if (c == '\n')
                *p++ = '\\', *p++ = 'n';
            else if (c == '\r')
                *p++ = '\\', *p++ = 'r';
            else if (c < ' ' || c >= 0x7f) {
                /* For performance, we don't want to call
                   PyOS_snprintf here (extra layers of
                   function call). */
                sprintf(p, "\\x%02x", c & 0xff);
                p += 4;
            }
            else
                *p++ = c;
        }
        assert(newsize - (p - PyString_AS_STRING(v)) >= 1);
        *p++ = quote;
        *p = '\0';
        if (_PyString_Resize(&v, (p - PyString_AS_STRING(v))))
            return NULL;
        return v;
    }
}


string_splitlines(PyStringObject *self, PyObject *args)
{
    int keepends = 0;

    if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends))
        return NULL;

    return stringlib_splitlines(
        (PyObject*) self, PyString_AS_STRING(self), PyString_GET_SIZE(self),
        keepends
    );
}


string_contains(PyObject *str_obj, PyObject *sub_obj)
{
    if (!PyString_CheckExact(sub_obj)) {
#ifdef Py_USING_UNICODE
        if (PyUnicode_Check(sub_obj))
            return PyUnicode_Contains(str_obj, sub_obj);
#endif
        if (!PyString_Check(sub_obj)) {
            PyErr_Format(PyExc_TypeError,
                "'in <string>' requires string as left operand, "
                "not %.200s", Py_TYPE(sub_obj)->tp_name);
            return -1;
        }
    }

    return stringlib_contains_obj(str_obj, sub_obj);
}


_PyString_Join(PyObject *sep, PyObject *x)
{
    assert(sep != NULL && PyString_Check(sep));
    assert(x != NULL);
    return string_join((PyStringObject *)sep, x);
}


string_buffer_getreadbuf(PyStringObject *self, Py_ssize_t index, const void **ptr)
{
    if ( index != 0 ) {
        PyErr_SetString(PyExc_SystemError,
                        "accessing non-existent string segment");
        return -1;
    }
    *ptr = (void *)self->ob_sval;
    return Py_SIZE(self);
}


string_rindex(PyStringObject *self, PyObject *args)
{
    Py_ssize_t result = string_find_internal(self, args, -1);
    if (result == -2)
        return NULL;
    if (result == -1) {
        PyErr_SetString(PyExc_ValueError,
                        "substring not found");
        return NULL;
    }
    return PyInt_FromSsize_t(result);
}


string_buffer_getsegcount(PyStringObject *self, Py_ssize_t *lenp)
{
    if ( lenp )
        *lenp = Py_SIZE(self);
    return 1;
}


string_richcompare(PyStringObject *a, PyStringObject *b, int op)
{
    int c;
    Py_ssize_t len_a, len_b;
    Py_ssize_t min_len;
    PyObject *result;

    /* Make sure both arguments are strings. */
    if (!(PyString_Check(a) && PyString_Check(b))) {
        result = Py_NotImplemented;
        goto out;
    }
    if (a == b) {
        switch (op) {
        case Py_EQ:case Py_LE:case Py_GE:
            result = Py_True;
            goto out;
        case Py_NE:case Py_LT:case Py_GT:
            result = Py_False;
            goto out;
        }
    }
    if (op == Py_EQ) {
        /* Supporting Py_NE here as well does not save
           much time, since Py_NE is rarely used.  */
        if (Py_SIZE(a) == Py_SIZE(b)
            && (a->ob_sval[0] == b->ob_sval[0]
            && memcmp(a->ob_sval, b->ob_sval, Py_SIZE(a)) == 0)) {
            result = Py_True;
        } else {
            result = Py_False;
        }
        goto out;
    }
    len_a = Py_SIZE(a); len_b = Py_SIZE(b);
    min_len = (len_a < len_b) ? len_a : len_b;
    if (min_len > 0) {
        c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
        if (c==0)
            c = memcmp(a->ob_sval, b->ob_sval, min_len);
    } else
        c = 0;
    if (c == 0)
        c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
    switch (op) {
    case Py_LT: c = c <  0; break;
    case Py_LE: c = c <= 0; break;
    case Py_EQ: assert(0);  break; /* unreachable */
    case Py_NE: c = c != 0; break;
    case Py_GT: c = c >  0; break;
    case Py_GE: c = c >= 0; break;
    default:
        result = Py_NotImplemented;
        goto out;
    }
    result = c ? Py_True : Py_False;
  out:
    Py_INCREF(result);
    return result;
}


string_encode(PyStringObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = {"encoding", "errors", 0};
    char *encoding = NULL;
    char *errors = NULL;
    PyObject *v;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:encode",
                                     kwlist, &encoding, &errors))
        return NULL;
    v = PyString_AsEncodedObject((PyObject *)self, encoding, errors);
    if (v == NULL)
        goto onError;
    if (!PyString_Check(v) && !PyUnicode_Check(v)) {
        PyErr_Format(PyExc_TypeError,
                     "encoder did not return a string/unicode object "
                     "(type=%.400s)",
                     Py_TYPE(v)->tp_name);
        Py_DECREF(v);
        return NULL;
    }
    return v;

 onError:
    return NULL;
}


string_ljust(PyStringObject *self, PyObject *args)
{
    Py_ssize_t width;
    char fillchar = ' ';

    if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))
        return NULL;

    if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
        Py_INCREF(self);
        return (PyObject*) self;
    }

    return pad(self, 0, width - PyString_GET_SIZE(self), fillchar);
}


striter_reduce(striterobject *it)
{
    if (it->it_seq != NULL) {
        return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
                             it->it_seq, it->it_index);
    } else {
        PyObject *u = PyUnicode_FromUnicode(NULL, 0);
        if (u == NULL)
            return NULL;
        return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), u);
    }
}


replace_substring(PyBytesObject *self,
                  const char *from_s, Py_ssize_t from_len,
                  const char *to_s, Py_ssize_t to_len,
                  Py_ssize_t maxcount) {
    char *self_s, *result_s;
    char *start, *next, *end;
    Py_ssize_t self_len, result_len;
    Py_ssize_t count, offset;
    PyBytesObject *result;

    self_s = PyBytes_AS_STRING(self);
    self_len = PyBytes_GET_SIZE(self);

    count = stringlib_count(self_s, self_len,
                            from_s, from_len,
                            maxcount);

    if (count == 0) {
        /* no matches, return unchanged */
        return return_self(self);
    }

    /* Check for overflow */
    /*    result_len = self_len + count * (to_len-from_len) */
    assert(count > 0);
    if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) {
        PyErr_SetString(PyExc_OverflowError,
                        "replacement bytes are too long");
        return NULL;
    }
    result_len = self_len + count * (to_len-from_len);

    if ( (result = (PyBytesObject *)
          PyBytes_FromStringAndSize(NULL, result_len)) == NULL)
        return NULL;
    result_s = PyBytes_AS_STRING(result);

    start = self_s;
    end = self_s + self_len;
    while (count-- > 0) {
        offset = stringlib_find(start, end-start,
                                from_s, from_len,
                                0);
        if (offset == -1)
            break;
        next = start+offset;
        if (next == start) {
            /* replace with the 'to' */
            Py_MEMCPY(result_s, to_s, to_len);
            result_s += to_len;
            start += from_len;
        } else {
            /* copy the unchanged old then the 'to' */
            Py_MEMCPY(result_s, start, next-start);
            result_s += (next-start);
            Py_MEMCPY(result_s, to_s, to_len);
            result_s += to_len;
            start = next+from_len;
        }
    }
    /* Copy the remainder of the remaining string */
    Py_MEMCPY(result_s, start, end-start);

    return result;
}


striter_setstate(striterobject *it, PyObject *state)
{
    Py_ssize_t index = PyLong_AsSsize_t(state);
    if (index == -1 && PyErr_Occurred())
        return NULL;
    if (it->it_seq != NULL) {
        if (index < 0)
            index = 0;
        else if (index > PyBytes_GET_SIZE(it->it_seq))
            index = PyBytes_GET_SIZE(it->it_seq); /* iterator exhausted */
        it->it_index = index;
    }
    Py_RETURN_NONE;
}


replace_substring_in_place(PyBytesObject *self,
                           const char *from_s, Py_ssize_t from_len,
                           const char *to_s, Py_ssize_t to_len,
                           Py_ssize_t maxcount)
{
    char *result_s, *start, *end;
    char *self_s;
    Py_ssize_t self_len, offset;
    PyBytesObject *result;

    /* The result string will be the same size */

    self_s = PyBytes_AS_STRING(self);
    self_len = PyBytes_GET_SIZE(self);

    offset = stringlib_find(self_s, self_len,
                            from_s, from_len,
                            0);
    if (offset == -1) {
        /* No matches; return the original string */
        return return_self(self);
    }

    /* Need to make a new string */
    result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, self_len);
    if (result == NULL)
        return NULL;
    result_s = PyBytes_AS_STRING(result);
    Py_MEMCPY(result_s, self_s, self_len);

    /* change everything in-place, starting with this one */
    start =  result_s + offset;
    Py_MEMCPY(start, to_s, from_len);
    start += from_len;
    end = result_s + self_len;

    while ( --maxcount > 0) {
        offset = stringlib_find(start, end-start,
                                from_s, from_len,
                                0);
        if (offset==-1)
            break;
        Py_MEMCPY(start+offset, to_s, from_len);
        start += offset+from_len;
    }

    return result;
}


bytes_rfind(PyBytesObject *self, PyObject *args)
{
    Py_ssize_t result = bytes_find_internal(self, args, -1);
    if (result == -2)
        return NULL;
    return PyLong_FromSsize_t(result);
}


bytes_repr(PyObject *op)
{
    return PyBytes_Repr(op, 1);
}


bytes_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    PyObject *tmp, *pnew;
    Py_ssize_t n;

    assert(PyType_IsSubtype(type, &PyBytes_Type));
    tmp = bytes_new(&PyBytes_Type, args, kwds);
    if (tmp == NULL)
        return NULL;
    assert(PyBytes_Check(tmp));
    n = PyBytes_GET_SIZE(tmp);
    pnew = type->tp_alloc(type, n);
    if (pnew != NULL) {
        Py_MEMCPY(PyBytes_AS_STRING(pnew),
                  PyBytes_AS_STRING(tmp), n+1);
        ((PyBytesObject *)pnew)->ob_shash =
            ((PyBytesObject *)tmp)->ob_shash;
    }
    Py_DECREF(tmp);
    return pnew;
}


dvi_document_render (EvDocument      *document,
		     EvRenderContext *rc)
{
	cairo_surface_t *surface;
	cairo_surface_t *rotated_surface;
	DviDocument *dvi_document = DVI_DOCUMENT(document);
	gdouble xscale, yscale;
	gint required_width, required_height;
	gint proposed_width, proposed_height;
	gint xmargin = 0, ymargin = 0;

	/* We should protect our context since it's not
	 * thread safe. The work to the future -
	 * let context render page independently
	 */
	g_mutex_lock (&dvi_context_mutex);

	mdvi_setpage (dvi_document->context, rc->page->index);

	ev_render_context_compute_scales (rc, dvi_document->base_width, dvi_document->base_height,
					  &xscale, &yscale);
	mdvi_set_shrink (dvi_document->context,
			 (int)((dvi_document->params->hshrink - 1) / xscale) + 1,
			 (int)((dvi_document->params->vshrink - 1) / yscale) + 1);

	ev_render_context_compute_scaled_size (rc, dvi_document->base_width, dvi_document->base_height,
					       &required_width, &required_height);
	proposed_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv;
	proposed_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv;

	if (required_width >= proposed_width)
	    xmargin = (required_width - proposed_width) / 2;
	if (required_height >= proposed_height)
	    ymargin = (required_height - proposed_height) / 2;

	mdvi_cairo_device_set_margins (&dvi_document->context->device, xmargin, ymargin);
	mdvi_cairo_device_set_scale (&dvi_document->context->device, xscale, yscale);
	mdvi_cairo_device_render (dvi_document->context);
	surface = mdvi_cairo_device_get_surface (&dvi_document->context->device);

	g_mutex_unlock (&dvi_context_mutex);

	rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
								     required_width,
								     required_height,
								     rc->rotation);
	cairo_surface_destroy (surface);

	return rotated_surface;
}


dvi_document_file_exporter_iface_init (EvFileExporterInterface *iface)
{
        iface->begin = dvi_document_file_exporter_begin;
        iface->do_page = dvi_document_file_exporter_do_page;
        iface->end = dvi_document_file_exporter_end;
	iface->get_capabilities = dvi_document_file_exporter_get_capabilities;
}


static int we_want_redo(int desired_ndx)
{
	static int redo_ndx = -1;

	while (redo_ndx < desired_ndx) {
		if (redo_ndx >= 0)
			no_batched_update(redo_ndx, True);
		if ((redo_ndx = flist_ndx_pop(&batch_redo_list)) < 0)
			return 0;
	}

	if (redo_ndx == desired_ndx) {
		redo_ndx = -1;
		return 1;
	}

	return 0;
}


static void no_batched_update(int ndx, BOOL is_redo)
{
	struct file_list *flist = flist_for_ndx(ndx, "no_batched_update");
	struct file_struct *file = flist->files[ndx - flist->ndx_start];

	rprintf(FERROR_XFER, "(No batched update for%s \"%s\")\n",
		is_redo ? " resend of" : "", f_name(file, NULL));

	if (inc_recurse && !dry_run)
		send_msg_int(MSG_NO_SEND, ndx);
}


int get_tmpname(char *fnametmp, const char *fname, BOOL make_unique)
{
	int maxname, length = 0;
	const char *f;
	char *suf;

	if (tmpdir) {
		/* Note: this can't overflow, so the return value is safe */
		length = strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
		fnametmp[length++] = '/';
	}

	if ((f = strrchr(fname, '/')) != NULL) {
		++f;
		if (!tmpdir) {
			length = f - fname;
			/* copy up to and including the slash */
			strlcpy(fnametmp, fname, length + 1);
		}
	} else
		f = fname;

	if (!tmpdir) { /* using a tmpdir avoids the leading dot on our temp names */
		if (*f == '.') /* avoid an extra leading dot for OS X's sake */
			f++;
		fnametmp[length++] = '.';
	}

	/* The maxname value is bufsize, and includes space for the '\0'.
	 * NAME_MAX needs an extra -1 for the name's leading dot. */
	maxname = MIN(MAXPATHLEN - length - TMPNAME_SUFFIX_LEN,
		      NAME_MAX - 1 - TMPNAME_SUFFIX_LEN);

	if (maxname < 0) {
		rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
		fnametmp[0] = '\0';
		return 0;
	}

	if (maxname) {
		int added = strlcpy(fnametmp + length, f, maxname);
		if (added >= maxname)
			added = maxname - 1;
		suf = fnametmp + length + added;

		/* Trim any dangling high-bit chars if the first-trimmed char (if any) is
		 * also a high-bit char, just in case we cut into a multi-byte sequence.
		 * We are guaranteed to stop because of the leading '.' we added. */
		if ((int)f[added] & 0x80) {
			while ((int)suf[-1] & 0x80)
				suf--;
		}
		/* trim one trailing dot before our suffix's dot */
		if (suf[-1] == '.')
			suf--;
	} else
		suf = fnametmp + length - 1; /* overwrite the leading dot with suffix's dot */

	if (make_unique) {
		static unsigned counter_limit;
		unsigned counter;

		if (!counter_limit) {
			counter_limit = (unsigned)getpid() + MAX_UNIQUE_LOOP;
			if (counter_limit > MAX_UNIQUE_NUMBER || counter_limit < MAX_UNIQUE_LOOP)
				counter_limit = MAX_UNIQUE_LOOP;
		}
		counter = counter_limit - MAX_UNIQUE_LOOP;

		/* This doesn't have to be very good because we don't need
		 * to worry about someone trying to guess the values:  all
		 * a conflict will do is cause a device, special file, hard
		 * link, or symlink to fail to be created.  Also: avoid
		 * using mktemp() due to gcc's annoying warning. */
		while (1) {
			snprintf(suf, TMPNAME_SUFFIX_LEN+1, ".%d", counter);
			if (access(fnametmp, 0) < 0)
				break;
			if (++counter >= counter_limit)
				return 0;
		}
	} else
		memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1);

	return 1;
}


static int
xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt,
			    xmlXPathStepOpPtr op,
			    int *maxPos)
{

    xmlXPathStepOpPtr exprOp;

    /*
    * BIG NOTE: This is not intended for XPATH_OP_FILTER yet!
    */

    /*
    * If not -1, then ch1 will point to:
    * 1) For predicates (XPATH_OP_PREDICATE):
    *    - an inner predicate operator
    * 2) For filters (XPATH_OP_FILTER):
    *    - an inner filter operater OR
    *    - an expression selecting the node set.
    *      E.g. "key('a', 'b')" or "(//foo | //bar)".
    */
    if ((op->op != XPATH_OP_PREDICATE) && (op->op != XPATH_OP_FILTER))
	return(0);

    if (op->ch2 != -1) {
	exprOp = &ctxt->comp->steps[op->ch2];
    } else
	return(0);

    if ((exprOp != NULL) &&
	(exprOp->op == XPATH_OP_VALUE) &&
	(exprOp->value4 != NULL) &&
	(((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER))
    {
        double floatval = ((xmlXPathObjectPtr) exprOp->value4)->floatval;

	/*
	* We have a "[n]" predicate here.
	* TODO: Unfortunately this simplistic test here is not
	* able to detect a position() predicate in compound
	* expressions like "[@attr = 'a" and position() = 1],
	* and even not the usage of position() in
	* "[position() = 1]"; thus - obviously - a position-range,
	* like it "[position() < 5]", is also not detected.
	* Maybe we could rewrite the AST to ease the optimization.
	*/

        if ((floatval > INT_MIN) && (floatval < INT_MAX)) {
	    *maxPos = (int) floatval;
            if (floatval == (double) *maxPos)
                return(1);
        }
    }


 */
static void
xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
    xmlChar *name;
    xmlChar *prefix;
    int nbargs = 0;
    int sort = 1;

    name = xmlXPathParseQName(ctxt, &prefix);
    if (name == NULL) {
	xmlFree(prefix);
	XP_ERROR(XPATH_EXPR_ERROR);
    }
    SKIP_BLANKS;
#ifdef DEBUG_EXPR
    if (prefix == NULL)
	xmlGenericError(xmlGenericErrorContext, "Calling function %s\n",
			name);
    else
	xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n",
			prefix, name);
#endif

    if (CUR != '(') {
	xmlFree(name);
	xmlFree(prefix);
	XP_ERROR(XPATH_EXPR_ERROR);
    }
    NEXT;
    SKIP_BLANKS;

    /*
    * Optimization for count(): we don't need the node-set to be sorted.
    */
    if ((prefix == NULL) && (name[0] == 'c') &&
	xmlStrEqual(name, BAD_CAST "count"))
    {
	sort = 0;
    }
    ctxt->comp->last = -1;
    if (CUR != ')') {
	while (CUR != 0) {
	    int op1 = ctxt->comp->last;
	    ctxt->comp->last = -1;
	    xmlXPathCompileExpr(ctxt, sort);
	    if (ctxt->error != XPATH_EXPRESSION_OK) {
		xmlFree(name);
		xmlFree(prefix);
		return;
	    }
	    PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
	    nbargs++;
	    if (CUR == ')') break;
	    if (CUR != ',') {
		xmlFree(name);
		xmlFree(prefix);
		XP_ERROR(XPATH_EXPR_ERROR);
	    }
	    NEXT;
	    SKIP_BLANKS;
	}
    }
    PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0,
	           name, prefix);
    NEXT;


 */
static xmlNodePtr
xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
                              xmlNodePtr cur)
{
    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
    if (cur == NULL) {
        cur = ctxt->context->node;
        if (cur == NULL)
            return (NULL);
        if (cur->type == XML_ATTRIBUTE_NODE) {
            cur = cur->parent;
        } else if (cur->type == XML_NAMESPACE_DECL) {
            xmlNsPtr ns = (xmlNsPtr) cur;

            if ((ns->next == NULL) ||
                (ns->next->type == XML_NAMESPACE_DECL))
                return (NULL);
            cur = (xmlNodePtr) ns->next;
        }
        ctxt->ancestor = cur->parent;
    }
    if (cur->type == XML_NAMESPACE_DECL)
        return(NULL);
    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
	cur = cur->prev;
    while (cur->prev == NULL) {
        cur = cur->parent;
        if (cur == NULL)
            return (NULL);
        if (cur == ctxt->context->doc->children)
            return (NULL);
        if (cur != ctxt->ancestor)
            return (cur);
        ctxt->ancestor = cur->parent;
    }
    cur = cur->prev;
    while (cur->last != NULL)
        cur = cur->last;


 */
void
xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
    double f;

    CHECK_ARITY(1);
    CAST_TO_NUMBER;
    CHECK_TYPE(XPATH_NUMBER);

    f = ctxt->value->floatval;

    /* Test for zero to keep negative zero unchanged. */
    if ((xmlXPathIsNaN(f)) || (f == 0.0))
	return;

    if ((f >= -0.5) && (f < 0.0)) {
        /* Negative zero. */
        ctxt->value->floatval = xmlXPathNZERO;
    }
    else {
        double rounded = floor(f);
        if (f - rounded >= 0.5)
            rounded += 1.0;
        ctxt->value->floatval = rounded;


static int userfaultfd_release(struct inode *inode, struct file *file)
{
	struct userfaultfd_ctx *ctx = file->private_data;
	struct mm_struct *mm = ctx->mm;
	struct vm_area_struct *vma, *prev;
	/* len == 0 means wake all */
	struct userfaultfd_wake_range range = { .len = 0, };
	unsigned long new_flags;

	WRITE_ONCE(ctx->released, true);

	if (!mmget_not_zero(mm))
		goto wakeup;

	/*
	 * Flush page faults out of all CPUs. NOTE: all page faults
	 * must be retried without returning VM_FAULT_SIGBUS if
	 * userfaultfd_ctx_get() succeeds but vma->vma_userfault_ctx
	 * changes while handle_userfault released the mmap_sem. So
	 * it's critical that released is set to true (above), before
	 * taking the mmap_sem for writing.
	 */
	down_write(&mm->mmap_sem);
	prev = NULL;
	for (vma = mm->mmap; vma; vma = vma->vm_next) {
		cond_resched();
		BUG_ON(!!vma->vm_userfaultfd_ctx.ctx ^
		       !!(vma->vm_flags & (VM_UFFD_MISSING | VM_UFFD_WP)));
		if (vma->vm_userfaultfd_ctx.ctx != ctx) {
			prev = vma;
			continue;
		}
		new_flags = vma->vm_flags & ~(VM_UFFD_MISSING | VM_UFFD_WP);
		prev = vma_merge(mm, prev, vma->vm_start, vma->vm_end,
				 new_flags, vma->anon_vma,
				 vma->vm_file, vma->vm_pgoff,
				 vma_policy(vma),
				 NULL_VM_UFFD_CTX);
		if (prev)
			vma = prev;
		else
			prev = vma;
		vma->vm_flags = new_flags;
		vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
	}
	up_write(&mm->mmap_sem);
	mmput(mm);
wakeup:
	/*
	 * After no new page faults can wait on this fault_*wqh, flush
	 * the last page faults that may have been already waiting on
	 * the fault_*wqh.
	 */
	spin_lock(&ctx->fault_pending_wqh.lock);
	__wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL, &range);
	__wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, &range);
	spin_unlock(&ctx->fault_pending_wqh.lock);

	/* Flush pending events that may still wait on event_wqh */
	wake_up_all(&ctx->event_wqh);

	wake_up_poll(&ctx->fd_wqh, POLLHUP);
	userfaultfd_ctx_put(ctx);
	return 0;
}


_tiff_error_handler (const char *mod,
		     const char *fmt,
		     va_list     ap)
{
	if (G_UNLIKELY (_tiff_error))
		return;

	_tiff_error = g_strdup_vprintf (fmt, ap);
}


_read_png (png_structp png_ptr,
	   png_bytep data,
	   png_size_t len)
{
	GInputStream *stream;

	stream = png_get_io_ptr (png_ptr);
	g_input_stream_read (stream, data, len, NULL, NULL);
}


xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
{
	const struct xt_osf_info *info = p->matchinfo;
	const struct iphdr *ip = ip_hdr(skb);
	const struct tcphdr *tcp;
	struct tcphdr _tcph;
	int fmatch = FMATCH_WRONG, fcount = 0;
	unsigned int optsize = 0, check_WSS = 0;
	u16 window, totlen, mss = 0;
	bool df;
	const unsigned char *optp = NULL, *_optp = NULL;
	unsigned char opts[MAX_IPOPTLEN];
	const struct xt_osf_finger *kf;
	const struct xt_osf_user_finger *f;
	struct net *net = xt_net(p);

	if (!info)
		return false;

	tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), &_tcph);
	if (!tcp)
		return false;

	if (!tcp->syn)
		return false;

	totlen = ntohs(ip->tot_len);
	df = ntohs(ip->frag_off) & IP_DF;
	window = ntohs(tcp->window);

	if (tcp->doff * 4 > sizeof(struct tcphdr)) {
		optsize = tcp->doff * 4 - sizeof(struct tcphdr);

		_optp = optp = skb_header_pointer(skb, ip_hdrlen(skb) +
				sizeof(struct tcphdr), optsize, opts);
	}

	list_for_each_entry_rcu(kf, &xt_osf_fingers[df], finger_entry) {
		int foptsize, optnum;

		f = &kf->finger;

		if (!(info->flags & XT_OSF_LOG) && strcmp(info->genre, f->genre))
			continue;

		optp = _optp;
		fmatch = FMATCH_WRONG;

		if (totlen != f->ss || !xt_osf_ttl(skb, info, f->ttl))
			continue;

		/*
		 * Should not happen if userspace parser was written correctly.
		 */
		if (f->wss.wc >= OSF_WSS_MAX)
			continue;

		/* Check options */

		foptsize = 0;
		for (optnum = 0; optnum < f->opt_num; ++optnum)
			foptsize += f->opt[optnum].length;

		if (foptsize > MAX_IPOPTLEN ||
		    optsize > MAX_IPOPTLEN ||
		    optsize != foptsize)
			continue;

		check_WSS = f->wss.wc;

		for (optnum = 0; optnum < f->opt_num; ++optnum) {
			if (f->opt[optnum].kind == (*optp)) {
				__u32 len = f->opt[optnum].length;
				const __u8 *optend = optp + len;

				fmatch = FMATCH_OK;

				switch (*optp) {
				case OSFOPT_MSS:
					mss = optp[3];
					mss <<= 8;
					mss |= optp[2];

					mss = ntohs((__force __be16)mss);
					break;
				case OSFOPT_TS:
					break;
				}

				optp = optend;
			} else
				fmatch = FMATCH_OPT_WRONG;

			if (fmatch != FMATCH_OK)
				break;
		}

		if (fmatch != FMATCH_OPT_WRONG) {
			fmatch = FMATCH_WRONG;

			switch (check_WSS) {
			case OSF_WSS_PLAIN:
				if (f->wss.val == 0 || window == f->wss.val)
					fmatch = FMATCH_OK;
				break;
			case OSF_WSS_MSS:
				/*
				 * Some smart modems decrease mangle MSS to
				 * SMART_MSS_2, so we check standard, decreased
				 * and the one provided in the fingerprint MSS
				 * values.
				 */
#define SMART_MSS_1	1460
#define SMART_MSS_2	1448
				if (window == f->wss.val * mss ||
				    window == f->wss.val * SMART_MSS_1 ||
				    window == f->wss.val * SMART_MSS_2)
					fmatch = FMATCH_OK;
				break;
			case OSF_WSS_MTU:
				if (window == f->wss.val * (mss + 40) ||
				    window == f->wss.val * (SMART_MSS_1 + 40) ||
				    window == f->wss.val * (SMART_MSS_2 + 40))
					fmatch = FMATCH_OK;
				break;
			case OSF_WSS_MODULO:
				if ((window % f->wss.val) == 0)
					fmatch = FMATCH_OK;
				break;
			}
		}

		if (fmatch != FMATCH_OK)
			continue;

		fcount++;

		if (info->flags & XT_OSF_LOG)
			nf_log_packet(net, xt_family(p), xt_hooknum(p), skb,
				      xt_in(p), xt_out(p), NULL,
				      "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n",
				      f->genre, f->version, f->subtype,
				      &ip->saddr, ntohs(tcp->source),
				      &ip->daddr, ntohs(tcp->dest),
				      f->ttl - ip->ttl);

		if ((info->flags & XT_OSF_LOG) &&
		    info->loglevel == XT_OSF_LOGLEVEL_FIRST)
			break;
	}

	if (!fcount && (info->flags & XT_OSF_LOG))
		nf_log_packet(net, xt_family(p), xt_hooknum(p), skb, xt_in(p),
			      xt_out(p), NULL,
			"Remote OS is not known: %pI4:%u -> %pI4:%u\n",
				&ip->saddr, ntohs(tcp->source),
				&ip->daddr, ntohs(tcp->dest));

	if (fcount)
		fmatch = FMATCH_OK;

	return fmatch == FMATCH_OK;
}


int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
		 unsigned int group, int report, gfp_t flags)
{
	int err = 0;

	if (group) {
		int exclude_portid = 0;

		if (report) {
			refcount_inc(&skb->users);
			exclude_portid = portid;
		}

		/* errors reported via destination sk->sk_err, but propagate
		 * delivery errors if NETLINK_BROADCAST_ERROR flag is set */
		err = nlmsg_multicast(sk, skb, exclude_portid, group, flags);
	}

	if (report) {
		int err2;

		err2 = nlmsg_unicast(sk, skb, portid);
		if (!err || err == -ESRCH)
			err = err2;
	}

	return err;
}


int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
			 const struct nlmsghdr *nlh,
			 struct netlink_dump_control *control)
{
	struct netlink_callback *cb;
	struct sock *sk;
	struct netlink_sock *nlk;
	int ret;

	refcount_inc(&skb->users);

	sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid);
	if (sk == NULL) {
		ret = -ECONNREFUSED;
		goto error_free;
	}

	nlk = nlk_sk(sk);
	mutex_lock(nlk->cb_mutex);
	/* A dump is in progress... */
	if (nlk->cb_running) {
		ret = -EBUSY;
		goto error_unlock;
	}
	/* add reference of module which cb->dump belongs to */
	if (!try_module_get(control->module)) {
		ret = -EPROTONOSUPPORT;
		goto error_unlock;
	}

	cb = &nlk->cb;
	memset(cb, 0, sizeof(*cb));
	cb->start = control->start;
	cb->dump = control->dump;
	cb->done = control->done;
	cb->nlh = nlh;
	cb->data = control->data;
	cb->module = control->module;
	cb->min_dump_alloc = control->min_dump_alloc;
	cb->skb = skb;

	if (cb->start) {
		ret = cb->start(cb);
		if (ret)
			goto error_unlock;
	}

	nlk->cb_running = true;
	nlk->dump_done_errno = INT_MAX;

	mutex_unlock(nlk->cb_mutex);

	ret = netlink_dump(sk);

	sock_put(sk);

	if (ret)
		return ret;

	/* We successfully started a dump, by returning -EINTR we
	 * signal not to send ACK even if it was requested.
	 */
	return -EINTR;

error_unlock:
	sock_put(sk);
	mutex_unlock(nlk->cb_mutex);
error_free:
	kfree_skb(skb);
	return ret;
}


static int netlink_bind(struct socket *sock, struct sockaddr *addr,
			int addr_len)
{
	struct sock *sk = sock->sk;
	struct net *net = sock_net(sk);
	struct netlink_sock *nlk = nlk_sk(sk);
	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
	int err = 0;
	long unsigned int groups = nladdr->nl_groups;
	bool bound;

	if (addr_len < sizeof(struct sockaddr_nl))
		return -EINVAL;

	if (nladdr->nl_family != AF_NETLINK)
		return -EINVAL;

	/* Only superuser is allowed to listen multicasts */
	if (groups) {
		if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV))
			return -EPERM;
		err = netlink_realloc_groups(sk);
		if (err)
			return err;
	}

	bound = nlk->bound;
	if (bound) {
		/* Ensure nlk->portid is up-to-date. */
		smp_rmb();

		if (nladdr->nl_pid != nlk->portid)
			return -EINVAL;
	}

	netlink_lock_table();
	if (nlk->netlink_bind && groups) {
		int group;

		for (group = 0; group < nlk->ngroups; group++) {
			if (!test_bit(group, &groups))
				continue;
			err = nlk->netlink_bind(net, group + 1);
			if (!err)
				continue;
			netlink_undo_bind(group, groups, sk);
			goto unlock;
		}
	}

	/* No need for barriers here as we return to user-space without
	 * using any of the bound attributes.
	 */
	if (!bound) {
		err = nladdr->nl_pid ?
			netlink_insert(sk, nladdr->nl_pid) :
			netlink_autobind(sock);
		if (err) {
			netlink_undo_bind(nlk->ngroups, groups, sk);
			goto unlock;
		}
	}

	if (!groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
		goto unlock;
	netlink_unlock_table();

	netlink_table_grab();
	netlink_update_subscriptions(sk, nlk->subscriptions +
					 hweight32(groups) -
					 hweight32(nlk->groups[0]));
	nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | groups;
	netlink_update_listeners(sk);
	netlink_table_ungrab();

	return 0;

unlock:
	netlink_unlock_table();
	return err;
}


static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
			     struct sk_buff *skb, const struct nlmsghdr *nlh,
			     const struct nlattr * const tb[],
			     struct netlink_ext_ack *extack)
{
	char *helper_name = NULL;
	struct nf_conntrack_helper *cur;
	struct nf_conntrack_tuple tuple;
	bool tuple_set = false, found = false;
	struct nfnl_cthelper *nlcth, *n;
	int j = 0, ret;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	if (tb[NFCTH_NAME])
		helper_name = nla_data(tb[NFCTH_NAME]);

	if (tb[NFCTH_TUPLE]) {
		ret = nfnl_cthelper_parse_tuple(&tuple, tb[NFCTH_TUPLE]);
		if (ret < 0)
			return ret;

		tuple_set = true;
	}

	ret = -ENOENT;
	list_for_each_entry_safe(nlcth, n, &nfnl_cthelper_list, list) {
		cur = &nlcth->helper;
		j++;

		if (helper_name &&
		    strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN))
			continue;

		if (tuple_set &&
		    (tuple.src.l3num != cur->tuple.src.l3num ||
		     tuple.dst.protonum != cur->tuple.dst.protonum))
			continue;

		if (refcount_dec_if_one(&cur->refcnt)) {
			found = true;
			nf_conntrack_helper_unregister(cur);
			kfree(cur->expect_policy);

			list_del(&nlcth->list);
			kfree(nlcth);
		} else {
			ret = -EBUSY;
		}
	}

	/* Make sure we return success if we flush and there is no helpers */
	return (found || j == 0) ? 0 : ret;
}


static int nfnl_cthelper_update_policy_all(struct nlattr *tb[],
					   struct nf_conntrack_helper *helper)
{
	struct nf_conntrack_expect_policy new_policy[helper->expect_class_max + 1];
	struct nf_conntrack_expect_policy *policy;
	int i, err;

	/* Check first that all policy attributes are well-formed, so we don't
	 * leave things in inconsistent state on errors.
	 */
	for (i = 0; i < helper->expect_class_max + 1; i++) {

		if (!tb[NFCTH_POLICY_SET + i])
			return -EINVAL;

		err = nfnl_cthelper_update_policy_one(&helper->expect_policy[i],
						      &new_policy[i],
						      tb[NFCTH_POLICY_SET + i]);
		if (err < 0)
			return err;
	}
	/* Now we can safely update them. */
	for (i = 0; i < helper->expect_class_max + 1; i++) {
		policy = (struct nf_conntrack_expect_policy *)
				&helper->expect_policy[i];
		policy->max_expected = new_policy->max_expected;
		policy->timeout	= new_policy->timeout;
	}

	return 0;
}


static MagickBooleanType IsXPM(const unsigned char *magick,const size_t length)
{
  if (length < 9)
    return(MagickFalse);
  if (LocaleNCompare((char *) magick+1,"* XPM *",7) == 0)
    return(MagickTrue);
  return(MagickFalse);
}


static MagickBooleanType ApplyPSDLayerOpacity(Image *image,Quantum opacity,
  MagickBooleanType revert,ExceptionInfo *exception)
{
  MagickBooleanType
    status;

  ssize_t
    y;

  if (image->debug != MagickFalse)
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
      "  applying layer opacity %.20g", (double) opacity);
  if (opacity == OpaqueAlpha)
    return(MagickTrue);
  image->alpha_trait=BlendPixelTrait;
  status=MagickTrue;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(status) \
  magick_number_threads(image,image,image->rows,1)
#endif
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    register Quantum
      *magick_restrict q;

    register ssize_t
      x;

    if (status == MagickFalse)
      continue;
    q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
    if (q == (Quantum *) NULL)
      {
        status=MagickFalse;
        continue;
      }
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      if (revert == MagickFalse)
        SetPixelAlpha(image,(Quantum) (QuantumScale*(GetPixelAlpha(image,q))*
          opacity),q);
      else if (opacity > 0)
        SetPixelAlpha(image,(Quantum) (QuantumRange*(GetPixelAlpha(image,q)/
          (MagickRealType) opacity)),q);
      q+=GetPixelChannels(image);
    }
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
      status=MagickFalse;
  }

  return(status);
}


handle_method_call (GDBusConnection       *connection,
                    const gchar           *sender,
                    const gchar           *object_path,
                    const gchar           *interface_name,
                    const gchar           *method_name,
                    GVariant              *parameters,
                    GDBusMethodInvocation *invocation,
                    gpointer               user_data)
{
  A11yBusLauncher *app = user_data;

  if (g_strcmp0 (method_name, "GetAddress") == 0)
    {
      ensure_a11y_bus (app);
      if (app->a11y_bus_pid > 0)
        g_dbus_method_invocation_return_value (invocation,
                                               g_variant_new ("(s)", app->a11y_bus_address));
      else
        g_dbus_method_invocation_return_dbus_error (invocation,
                                                    "org.a11y.Bus.Error",
                                                    app->a11y_launch_error_message);
    }
}


setup_bus_child (gpointer data)
{
  A11yBusLauncher *app = data;
  (void) app;

  close (app->pipefd[0]);
  dup2 (app->pipefd[1], 3);
  close (app->pipefd[1]);

  /* On Linux, tell the bus process to exit if this process goes away */
#ifdef __linux
#include <sys/prctl.h>
  prctl (PR_SET_PDEATHSIG, 15);
#endif
}