Ejemplo n.º 1
0
void
pqt_getfmtinfo(const PGconn *conn, PGtypeFormatInfo *info)
{
	const char *value;

	memset(info, 0, sizeof(PGtypeFormatInfo));

	if ((value = PQparameterStatus(conn, "DateStyle")))
		pqt_strcpy(info->datestyle, sizeof(info->datestyle), value);

	if ((value = PQparameterStatus(conn, "integer_datetimes")))
		info->integer_datetimes = strcmp(value, "on")==0 ? TRUE : FALSE;

	info->sversion = PQserverVersion(conn);
	info->pversion = PQprotocolVersion(conn);
}
Ejemplo n.º 2
0
static int
get_inet2(PGtypeArgs *args, int is_cidr)
{
	DECLVALUE(args);
	unsigned short family;
	PGinet *inet = va_arg(args->ap, PGinet *);

	CHKGETVALS(args, inet);

	if (args->format == TEXTFMT)
	{
		int r;
		char *p;
		char ipstr[80];
		struct addrinfo *ai = NULL;
		struct addrinfo hints;

		pqt_strcpy(ipstr, sizeof(ipstr), value);
		if ((p = strrchr(ipstr, '/')))
		{
			*p = 0;
			inet->mask = atoi(p+1);
		}
		else
		{
			inet->mask = 32;
		}

		inet->is_cidr = is_cidr;

		/* suppress hostname lookups */
		memset(&hints, 0, sizeof(hints));
		hints.ai_flags = AI_NUMERICHOST;

		/* Without this, windows chokes with WSAHOST_NOT_FOUND */
#ifdef PQT_WIN32
		hints.ai_family = AF_INET;
#endif

		if ((r = getaddrinfo(ipstr, NULL, &hints, &ai)) || !ai)
		{
			if(r == EAI_BADFLAGS)
			{
				hints.ai_flags = 0;
				r = getaddrinfo(ipstr, NULL, &hints, &ai);
			}
			/* Another WSAHOST_NOT_FOUND work around, but for IPv6 */
#if defined(PQT_WIN32) && defined(AF_INET6)
			else if(r == WSAHOST_NOT_FOUND)
			{
				hints.ai_flags = 0;
				hints.ai_family = AF_INET6;
				r = getaddrinfo(ipstr, NULL, &hints, &ai);
			}
#endif

			if(r)
				RERR_STR2INT(args);
		}

		inet->sa_buf_len = (int) ai->ai_addrlen;
		memcpy(inet->sa_buf, ai->ai_addr, inet->sa_buf_len);

		/* Some platforms, lika AIX 4.3, do not zero this structure properly.
     * The family and port are dirty, so set the first 4 bytes to 0 and
     * then re-set the family.  I saw "0x1002" as the first 2 bytes of
     * this structure (dumb getaddrinfo), it should be "0x0002" for AF_INET.
     */
		memset(inet->sa_buf, 0, 4);
		((struct sockaddr *)inet->sa_buf)->sa_family = ai->ai_addr->sa_family;

		/* Uninitialized memory, postgres inet/cidr types don't store this.
     * Make sure its set to 0.  Another AIX problem (maybe other platforms).
		 */
#ifdef AF_INET6
		if (ai->ai_addr->sa_family == AF_INET6)
			((struct sockaddr_in6 *)inet->sa_buf)->sin6_flowinfo = 0;
#endif

		freeaddrinfo(ai);
		return 0;
	}

	family = (unsigned short) *value++;
	if (family == PGSQL_AF_INET)
	{
		struct sockaddr_in *sa = (struct sockaddr_in *) inet->sa_buf;
		sa->sin_family = AF_INET;
		inet->mask = (unsigned char) *value++;
		inet->is_cidr = *value++;
		memcpy(&sa->sin_addr, value + 1, *value);
		inet->sa_buf_len = (int) sizeof(struct sockaddr_in);
	}
#ifdef AF_INET6
	else if (family == PGSQL_AF_INET6)
	{
		struct sockaddr_in6 *sa = (struct sockaddr_in6 *) inet->sa_buf;
		sa->sin6_family = AF_INET6;
		inet->mask = (unsigned char) *value++;
		inet->is_cidr = *value++;
		memcpy(&sa->sin6_addr, value + 1, *value);
		inet->sa_buf_len = (int) sizeof(struct sockaddr_in6);
	}
#endif
	else
	{
		return args->errorf(args, "Unknown inet address family %d", family);
	}

	return 0;
}
Ejemplo n.º 3
0
Archivo: error.c Proyecto: beanhome/dev
static void
vseterror(const char *format, va_list ap, int append)
{
	int n;
	int curlen = 0;
	int size;
	va_list ap2;
	char *msg = NULL;
	pqterr_t *err = geterr();

	if (!err)
		return;

	if (append)
		curlen = (int) strlen(err->msg);
	else
		*err->msg = 0;

	va_copy(ap2, ap);
	n = pqt_vsnprintf(err->msg + curlen, sizeof(err->msg) - curlen, format, ap2);
	va_end(ap2);

	if (n > -1)
		return;

	/* pqterr_t msg buffer is too small for the complete message.  We have
	 * use a temporary buffer to get a successful sprintf so we can
	 * pqt_strcpy() the result; which truncates to fit.
	 */
	size = (int) sizeof(err->msg) * 2;
	if (!(msg = (char *) malloc(size)))
		return;

  while (1)
	{
		char *p;

		va_copy(ap2, ap);
		n = pqt_vsnprintf(msg + curlen, size - curlen, format, ap2);
		va_end(ap2);

		/* success */
		if (n > -1)
			break;

		/* need more space */
		n = size * 2;
		if (!(p = pqt_realloc(msg, n)))
		{
			/* we're here because sprintf failed, don't trust buffer contents */
			*msg = 0;
			break;
		}

		msg = p;
		size = n;
	}

	pqt_strcpy(err->msg, sizeof(err->msg), msg);
	free(msg);
}
Ejemplo n.º 4
0
static int registerSubClass(PGtypeData *connData, const char *type_name,
	PGtypeProc typput, PGtypeProc typget)
{
	char *s;
	PGtypeHandler *h_sub;
	PGtypeHandler *h_base;
	char sub_typschema[PQT_MAXIDLEN + 1];
	char sub_typname[PQT_MAXIDLEN + 1];
	char base_typschema[PQT_MAXIDLEN + 1];
	char base_typname[PQT_MAXIDLEN + 1];
	char sub_fqtn[200];
	char base_fqtn[200];

	if (!(s = parseType(type_name, sub_typschema, sub_typname, 1)))
		return FALSE;

	if (*s != '=')
	{
		PQseterror("Missing inheritence operator '=': %s", type_name);
		return FALSE;
	}

	if (!parseType(s + 1, base_typschema, base_typname, 1))
		return FALSE;

	/* lookup the base handler */
	h_base = pqt_gethandler(connData->typhandlers, connData->typhcnt,
		base_typschema, base_typname);

	if (!h_base)
	{
		PQseterror("typname '%s' does not exist, '%s' cannot sub-class it",
			pqt_fqtn(base_fqtn, sizeof(base_fqtn), base_typschema, base_typname),
			pqt_fqtn(sub_fqtn, sizeof(sub_fqtn), sub_typschema, sub_typname));
		return FALSE;
	}

	/* cannot sub-class a record type */
	if (h_base->typoid == RECORDOID)
	{
		PQseterror("Cannot sub-class pg_catalog.record '%s'",
			pqt_fqtn(sub_fqtn, sizeof(sub_fqtn), sub_typschema, sub_typname));
		return FALSE;
	}

	if (!expandHandlers(connData))
		return FALSE;

	h_sub = &connData->typhandlers[connData->typhcnt];
	memset(h_sub, 0, sizeof(PGtypeHandler));

	h_sub->id = connData->typhcnt + countof(pg_handlers);
	h_sub->typlen = h_base->typlen;
	h_sub->typoid = h_base->typoid;
	h_sub->typoid_array = h_base->typoid_array;
	h_sub->typput = typput;
	h_sub->typget = typget;
	h_sub->base_id = h_base->id;

	pqt_strcpy(h_sub->typschema,
		sizeof(h_sub->typschema), sub_typschema);

	pqt_strcpy(h_sub->typname,
		sizeof(h_sub->typname), sub_typname);

	connData->typhcnt++;
	return TRUE;
}
Ejemplo n.º 5
0
int
PQregisterResult(PGconn *conn, int which, PGregisterType *types,
	int count, PGresult *res)
{
	int i;
	PGtypeData *connData;
	char typname[PQT_MAXIDLEN + 1];
	char typschema[PQT_MAXIDLEN + 1];
	/* inherit typput and typget from record type */
	PGtypeHandler *h_rec = pqt_gethandler(NULL, 0, "pg_catalog", "record");

	PQseterror(NULL);

	if (!conn)
	{
		PQseterror("PGconn cannot be NULL");
		return FALSE;
	}

	if (!res)
	{
		PQseterror("PGresult cannot be NULL");
		return FALSE;
	}

	if (which == PQT_SUBCLASS)
	{
		PQseterror("Cannot call PQregisterResult for a subclass registration.");
		return FALSE;
	}

	if (!(connData = (PGtypeData *) PQinstanceData(conn, pqt_eventproc)))
	{
		PQseterror("PGconn is missing event data");
		return FALSE;
	}

	if (!types)
	{
		PQseterror("PGregisterType[] cannot be NULL");
		return FALSE;
	}

	if (count < 0)
	{
		PQseterror("PGregisterType[] count cannot be less than zero");
		return FALSE;
	}

	if(!checkTypeLookups(res, types, count))
		return FALSE;

	for (i=0; i < PQntuples(res); i++)
	{
		int flags;
		PGint2 typlen;
		PGtypeHandler *h;

		if (which == PQT_USERDEFINED && !types[i].typput && !types[i].typget)
		{
			PQseterror("Must provide a put and/or a get routine: '%s'",
				types[i].typname);
			return FALSE;
		}

		/* make sure conn's type handlers array is large enough */
		if (!expandHandlers(connData))
			return FALSE;

		/* create the handler */
		h = &connData->typhandlers[connData->typhcnt];
		memset(h, 0, sizeof(PGtypeHandler));

		if (!PQgetf(res, i, "%oid %oid %int2", 1, &h->typoid,
			2, &h->typoid_array, 3, &typlen))
		{
			return FALSE;
		}

		h->id = connData->typhcnt + countof(pg_handlers);
		h->typlen = (int) typlen;
		h->base_id = -1;

		if (which == PQT_USERDEFINED)
		{
			h->typput = types[i].typput;
			h->typget = types[i].typget;
		}
		else
		{
			h->typput = h_rec->typput;
			h->typget = h_rec->typget;
		}

		/* parse out type and schema names again */
		(void ) pqt_parsetype(types[i].typname, typschema, typname, &flags, 1);
		pqt_strcpy(h->typschema, sizeof(h->typschema), typschema);
		pqt_strcpy(h->typname, sizeof(h->typname), typname);

		/* Process composite attributes */
		if(which == PQT_COMPOSITE)
		{
			PGtext attrs;
			int nattrs;
			PGrecordAttDesc *attDescs;

			if (!PQgetf(res, i, "%text", 4, &attrs))
			{
				return FALSE;
			}

			if (!(attDescs = initAttDescs(h, attrs)))
				return FALSE;

			for (nattrs=0; *attrs; nattrs++)
			{
				char *p;
				char *name;
				int len;

				/* Attribute Text Encoding:
				 *   "attoid,attlen,atttypmod,name_hex attoid,etc..."
				 */

				attDescs[nattrs].attoid    = (int) strtol(attrs, &attrs, 10);
				attDescs[nattrs].attlen    = (int) strtol(attrs + 1, &attrs, 10);
				attDescs[nattrs].atttypmod = (int) strtol(attrs + 1, &attrs, 10);

				/* skip comma before name */
				attrs++;

				/* attribute name in hex */
				if (!(p = strchr(attrs, ' ')))
					p = attrs + strlen(attrs); /* last attr, point at NUL */

				/* truncate name if it exceeds buffer */
				len = (int) (p - attrs);
				if (len >= (int) sizeof(attDescs[nattrs].attname))
					len = (int) (sizeof(attDescs[nattrs].attname) - 1);

				/* hex decode and copy */
				for (name = attDescs[nattrs].attname; attrs < p; attrs += 2)
					*name++ = (char) (pqt_hex_to_dec(attrs[0]) << 4)
						| pqt_hex_to_dec(attrs[1]);
				*name = 0;
			}

			h->nattrs = nattrs;
			h->attDescs = attDescs;
		}

		connData->typhcnt++;
	}

	return TRUE;
}