mirror of
https://github.com/postgres/postgres.git
synced 2025-07-12 21:01:52 +03:00
6.3 postmaster is supposed to work with pre 6.3 protocol. This is true for little endian architecture servers. But for big endian machines such as Sparc the backward compatibility function do not work. Attached are patches to fix the problem.
235 lines
4.2 KiB
C
235 lines
4.2 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include "postgres.h"
|
|
#include "libpq/pqcomm.h"
|
|
|
|
|
|
/*
|
|
* The backend supports the old little endian byte order and the current
|
|
* network byte order.
|
|
*/
|
|
|
|
#ifndef FRONTEND
|
|
|
|
#include "libpq/libpq-be.h"
|
|
|
|
#ifdef HAVE_ENDIAN_H
|
|
#include <endian.h>
|
|
#endif
|
|
|
|
#ifndef BYTE_ORDER
|
|
#error BYTE_ORDER must be defined as LITTLE_ENDIAN, BIG_ENDIAN or PDP_ENDIAN
|
|
#endif
|
|
|
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
|
|
#define ntoh_s(n) n
|
|
#define ntoh_l(n) n
|
|
#define hton_s(n) n
|
|
#define hton_l(n) n
|
|
|
|
#else
|
|
#if BYTE_ORDER == BIG_ENDIAN
|
|
|
|
/*
|
|
#define ntoh_s(n) (uint16)(((u_char *)&n)[1] << 8 \
|
|
| ((u_char *)&n)[0])
|
|
#define ntoh_l(n) (uint32)(((u_char *)&n)[3] << 24 \
|
|
| ((u_char *)&n)[2] << 16 \
|
|
| ((u_char *)&n)[1] << 8 \
|
|
| ((u_char *)&n)[0])
|
|
*/
|
|
#define ntoh_s(n) (uint16)((((uint16)n & 0x00ff) << 8) | \
|
|
(((uint16)n & 0xff00) >> 8))
|
|
#define ntoh_l(n) (uint32)((((uint32)n & 0x000000ff) << 24) | \
|
|
(((uint32)n & 0x0000ff00) << 8) | \
|
|
(((uint32)n & 0x00ff0000) >> 8) | \
|
|
(((uint32)n & 0xff000000) >> 24))
|
|
#define hton_s(n) (ntoh_s(n))
|
|
#define hton_l(n) (ntoh_l(n))
|
|
|
|
#else
|
|
#if BYTE_ORDER == PDP_ENDIAN
|
|
|
|
#error PDP_ENDIAN macros not written yet
|
|
|
|
#else
|
|
|
|
#error BYTE_ORDER not defined as anything understood
|
|
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqPutShort(int integer, FILE *f)
|
|
{
|
|
uint16 n;
|
|
|
|
#ifdef FRONTEND
|
|
n = htons((uint16) integer);
|
|
#else
|
|
n = ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? hton_s(integer) : htons((uint16) integer));
|
|
#endif
|
|
|
|
if (fwrite(&n, 2, 1, f) != 1)
|
|
return EOF;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqPutLong(int integer, FILE *f)
|
|
{
|
|
uint32 n;
|
|
|
|
#ifdef FRONTEND
|
|
n = htonl((uint32) integer);
|
|
#else
|
|
n = ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? hton_l(integer) : htonl((uint32) integer));
|
|
#endif
|
|
|
|
if (fwrite(&n, 4, 1, f) != 1)
|
|
return EOF;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqGetShort(int *result, FILE *f)
|
|
{
|
|
uint16 n;
|
|
|
|
if (fread(&n, 2, 1, f) != 1)
|
|
return EOF;
|
|
|
|
#ifdef FRONTEND
|
|
*result = (int) ntohs(n);
|
|
#else
|
|
*result = (int) ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? ntoh_s(n) : ntohs(n));
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqGetLong(int *result, FILE *f)
|
|
{
|
|
uint32 n;
|
|
|
|
if (fread(&n, 4, 1, f) != 1)
|
|
return EOF;
|
|
|
|
#ifdef FRONTEND
|
|
*result = (int) ntohl(n);
|
|
#else
|
|
*result = (int) ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? ntoh_l(n) : ntohl(n));
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
/* pqGetNBytes: Read a chunk of exactly len bytes in buffer s (which must be 1
|
|
byte longer) and terminate it with a '\0'.
|
|
Return 0 if ok.
|
|
*/
|
|
int
|
|
pqGetNBytes(char *s, size_t len, FILE *f)
|
|
{
|
|
int cnt;
|
|
|
|
if (f == NULL)
|
|
return EOF;
|
|
|
|
cnt = fread(s, 1, len, f);
|
|
s[cnt] = '\0';
|
|
|
|
return (cnt == len) ? 0 : EOF;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqPutNBytes(const char *s, size_t len, FILE *f)
|
|
{
|
|
if (f == NULL)
|
|
return EOF;
|
|
|
|
if (fwrite(s, 1, len, f) != len)
|
|
return EOF;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqGetString(char *s, size_t len, FILE *f)
|
|
{
|
|
int c;
|
|
|
|
if (f == NULL)
|
|
return EOF;
|
|
|
|
/*
|
|
* Keep on reading until we get the terminating '\0' and discard those
|
|
* bytes we don't have room for.
|
|
*/
|
|
|
|
while ((c = getc(f)) != EOF && c != '\0')
|
|
if (len > 1)
|
|
{
|
|
*s++ = c;
|
|
len--;
|
|
}
|
|
|
|
*s = '\0';
|
|
|
|
if (c == EOF)
|
|
return EOF;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqPutString(const char *s, FILE *f)
|
|
{
|
|
if (f == NULL)
|
|
return 0;
|
|
|
|
if (fputs(s, f) == EOF)
|
|
return EOF;
|
|
|
|
fputc('\0', f); /* important to send an ending \0 since
|
|
* backend expects it */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqGetByte(FILE *f)
|
|
{
|
|
return getc(f);
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
int
|
|
pqPutByte(int c, FILE *f)
|
|
{
|
|
if (!f)
|
|
return 0;
|
|
|
|
return (putc(c, f) == c) ? 0 : EOF;
|
|
}
|