1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-20 00:42:27 +03:00

pgindent run on all C files. Java run to follow. initdb/regression

tests pass.
This commit is contained in:
Bruce Momjian 2001-10-25 05:50:21 +00:00
parent 59da2105d8
commit b81844b173
818 changed files with 21684 additions and 20491 deletions

View File

@ -34,7 +34,6 @@ int32 array_all_int4le(ArrayType *array, int4 value);
int32 array_oideq(ArrayType *array, Oid value); int32 array_oideq(ArrayType *array, Oid value);
int32 array_all_oidne(ArrayType *array, Oid value); int32 array_all_oidne(ArrayType *array, Oid value);
#endif #endif
/* /*

View File

@ -8,43 +8,46 @@
#include "utils/geo_decls.h" #include "utils/geo_decls.h"
#include "utils/elog.h" #include "utils/elog.h"
typedef int (*CMPFUNC)(const void *a, const void *b); typedef int (*CMPFUNC) (const void *a, const void *b);
typedef void (*BINARY_UNION)(Datum*, char*); typedef void (*BINARY_UNION) (Datum *, char *);
typedef struct intkey { typedef struct intkey
int4 lower; {
int4 upper; int4 lower;
} INT4KEY; int4 upper;
} INT4KEY;
typedef struct tskey { typedef struct tskey
Timestamp lower; {
Timestamp upper; Timestamp lower;
} TSKEY; Timestamp upper;
} TSKEY;
/* used for sorting */ /* used for sorting */
typedef struct rix { typedef struct rix
int index; {
char *r; int index;
} RIX; char *r;
} RIX;
/* /*
** int4key in/out ** int4key in/out
*/ */
PG_FUNCTION_INFO_V1(int4key_in); PG_FUNCTION_INFO_V1(int4key_in);
PG_FUNCTION_INFO_V1(int4key_out); PG_FUNCTION_INFO_V1(int4key_out);
Datum int4key_in(PG_FUNCTION_ARGS); Datum int4key_in(PG_FUNCTION_ARGS);
Datum int4key_out(PG_FUNCTION_ARGS); Datum int4key_out(PG_FUNCTION_ARGS);
/* /*
** tskey in/out ** tskey in/out
*/ */
PG_FUNCTION_INFO_V1(tskey_in); PG_FUNCTION_INFO_V1(tskey_in);
PG_FUNCTION_INFO_V1(tskey_out); PG_FUNCTION_INFO_V1(tskey_out);
Datum tskey_in(PG_FUNCTION_ARGS); Datum tskey_in(PG_FUNCTION_ARGS);
Datum tskey_out(PG_FUNCTION_ARGS); Datum tskey_out(PG_FUNCTION_ARGS);
/* /*
** int4 ops ** int4 ops
*/ */
PG_FUNCTION_INFO_V1(gint4_compress); PG_FUNCTION_INFO_V1(gint4_compress);
PG_FUNCTION_INFO_V1(gint4_union); PG_FUNCTION_INFO_V1(gint4_union);
@ -53,15 +56,15 @@ PG_FUNCTION_INFO_V1(gint4_consistent);
PG_FUNCTION_INFO_V1(gint4_penalty); PG_FUNCTION_INFO_V1(gint4_penalty);
PG_FUNCTION_INFO_V1(gint4_same); PG_FUNCTION_INFO_V1(gint4_same);
Datum gint4_compress(PG_FUNCTION_ARGS); Datum gint4_compress(PG_FUNCTION_ARGS);
Datum gint4_union(PG_FUNCTION_ARGS); Datum gint4_union(PG_FUNCTION_ARGS);
Datum gint4_picksplit(PG_FUNCTION_ARGS); Datum gint4_picksplit(PG_FUNCTION_ARGS);
Datum gint4_consistent(PG_FUNCTION_ARGS); Datum gint4_consistent(PG_FUNCTION_ARGS);
Datum gint4_penalty(PG_FUNCTION_ARGS); Datum gint4_penalty(PG_FUNCTION_ARGS);
Datum gint4_same(PG_FUNCTION_ARGS); Datum gint4_same(PG_FUNCTION_ARGS);
static void gint4_binary_union(Datum *r1, char *r2); static void gint4_binary_union(Datum *r1, char *r2);
static int int4key_cmp(const void *a, const void *b); static int int4key_cmp(const void *a, const void *b);
/* /*
** timestamp ops ** timestamp ops
@ -73,51 +76,51 @@ PG_FUNCTION_INFO_V1(gts_consistent);
PG_FUNCTION_INFO_V1(gts_penalty); PG_FUNCTION_INFO_V1(gts_penalty);
PG_FUNCTION_INFO_V1(gts_same); PG_FUNCTION_INFO_V1(gts_same);
Datum gts_compress(PG_FUNCTION_ARGS); Datum gts_compress(PG_FUNCTION_ARGS);
Datum gts_union(PG_FUNCTION_ARGS); Datum gts_union(PG_FUNCTION_ARGS);
Datum gts_picksplit(PG_FUNCTION_ARGS); Datum gts_picksplit(PG_FUNCTION_ARGS);
Datum gts_consistent(PG_FUNCTION_ARGS); Datum gts_consistent(PG_FUNCTION_ARGS);
Datum gts_penalty(PG_FUNCTION_ARGS); Datum gts_penalty(PG_FUNCTION_ARGS);
Datum gts_same(PG_FUNCTION_ARGS); Datum gts_same(PG_FUNCTION_ARGS);
static void gts_binary_union(Datum *r1, char *r2); static void gts_binary_union(Datum *r1, char *r2);
static int tskey_cmp(const void *a, const void *b); static int tskey_cmp(const void *a, const void *b);
/* define for comparison */ /* define for comparison */
#define TSGE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ #define TSGE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
timestamp_ge, \ timestamp_ge, \
PointerGetDatum( ts1 ), \ PointerGetDatum( ts1 ), \
PointerGetDatum( ts2 ) \ PointerGetDatum( ts2 ) \
))) )))
#define TSGT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ #define TSGT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
timestamp_gt, \ timestamp_gt, \
PointerGetDatum( ts1 ), \ PointerGetDatum( ts1 ), \
PointerGetDatum( ts2 ) \ PointerGetDatum( ts2 ) \
))) )))
#define TSEQ( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ #define TSEQ( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
timestamp_eq, \ timestamp_eq, \
PointerGetDatum( ts1 ), \ PointerGetDatum( ts1 ), \
PointerGetDatum( ts2 ) \ PointerGetDatum( ts2 ) \
))) )))
#define TSLT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ #define TSLT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
timestamp_lt, \ timestamp_lt, \
PointerGetDatum( ts1 ), \ PointerGetDatum( ts1 ), \
PointerGetDatum( ts2 ) \ PointerGetDatum( ts2 ) \
))) )))
#define TSLE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ #define TSLE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
timestamp_le, \ timestamp_le, \
PointerGetDatum( ts1 ), \ PointerGetDatum( ts1 ), \
PointerGetDatum( ts2 ) \ PointerGetDatum( ts2 ) \
))) )))
/* /*
** Common btree-function (for all ops) ** Common btree-function (for all ops)
*/ */
static GIST_SPLITVEC * btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, static GIST_SPLITVEC *btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v,
BINARY_UNION bu, CMPFUNC cmp); BINARY_UNION bu, CMPFUNC cmp);
PG_FUNCTION_INFO_V1(btree_decompress); PG_FUNCTION_INFO_V1(btree_decompress);
Datum btree_decompress(PG_FUNCTION_ARGS); Datum btree_decompress(PG_FUNCTION_ARGS);
/************************************************** /**************************************************
* int4 ops * int4 ops
@ -126,334 +129,364 @@ Datum btree_decompress(PG_FUNCTION_ARGS);
Datum Datum
gint4_compress(PG_FUNCTION_ARGS) gint4_compress(PG_FUNCTION_ARGS)
{ {
GISTENTRY *entry=(GISTENTRY*)PG_GETARG_POINTER(0); GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *retval; GISTENTRY *retval;
if (entry->leafkey)
{
INT4KEY *r = palloc(sizeof(INT4KEY));
if ( entry->leafkey) {
INT4KEY *r = palloc(sizeof(INT4KEY));
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
r->lower = r->upper = (entry->key); r->lower = r->upper = (entry->key);
gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
entry->offset, sizeof(INT4KEY),FALSE);
} else { gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
retval = entry; entry->offset, sizeof(INT4KEY), FALSE);
} }
PG_RETURN_POINTER( retval ); else
retval = entry;
PG_RETURN_POINTER(retval);
} }
Datum Datum
gint4_consistent(PG_FUNCTION_ARGS) gint4_consistent(PG_FUNCTION_ARGS)
{ {
GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0); GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
int4 query = PG_GETARG_INT32(1); int4 query = PG_GETARG_INT32(1);
INT4KEY *kkk= (INT4KEY *)DatumGetPointer(entry->key); INT4KEY *kkk = (INT4KEY *) DatumGetPointer(entry->key);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
bool retval; bool retval;
switch(strategy) { switch (strategy)
case BTLessEqualStrategyNumber: {
retval = ( query >= kkk->lower ); case BTLessEqualStrategyNumber:
break; retval = (query >= kkk->lower);
case BTLessStrategyNumber: break;
if (GIST_LEAF(entry)) case BTLessStrategyNumber:
retval = ( query > kkk->lower ); if (GIST_LEAF(entry))
else retval = (query > kkk->lower);
retval = ( query >= kkk->lower ); else
break; retval = (query >= kkk->lower);
case BTEqualStrategyNumber: break;
/* in leaf page kkk->lower always = kkk->upper */ case BTEqualStrategyNumber:
if (GIST_LEAF(entry)) /* in leaf page kkk->lower always = kkk->upper */
retval = ( query == kkk->lower ); if (GIST_LEAF(entry))
else retval = (query == kkk->lower);
retval = ( kkk->lower <= query && query <= kkk->upper ); else
break; retval = (kkk->lower <= query && query <= kkk->upper);
case BTGreaterStrategyNumber: break;
if (GIST_LEAF(entry)) case BTGreaterStrategyNumber:
retval = ( query < kkk->upper ); if (GIST_LEAF(entry))
else retval = (query < kkk->upper);
retval = ( query <= kkk->upper ); else
break; retval = (query <= kkk->upper);
case BTGreaterEqualStrategyNumber: break;
retval = ( query <= kkk->upper ); case BTGreaterEqualStrategyNumber:
break; retval = (query <= kkk->upper);
default: break;
retval = FALSE; default:
} retval = FALSE;
PG_RETURN_BOOL(retval); }
PG_RETURN_BOOL(retval);
} }
Datum Datum
gint4_union(PG_FUNCTION_ARGS) gint4_union(PG_FUNCTION_ARGS)
{ {
bytea *entryvec = (bytea*) PG_GETARG_POINTER(0); bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
int i, numranges; int i,
INT4KEY *cur, *out=palloc(sizeof(INT4KEY)); numranges;
INT4KEY *cur,
*out = palloc(sizeof(INT4KEY));
numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY); numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
*(int*) PG_GETARG_POINTER(1) = sizeof(INT4KEY); *(int *) PG_GETARG_POINTER(1) = sizeof(INT4KEY);
cur = (INT4KEY *)DatumGetPointer( (((GISTENTRY *)(VARDATA(entryvec)))[0].key) ); cur = (INT4KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key));
out->lower = cur->lower; out->lower = cur->lower;
out->upper = cur->upper; out->upper = cur->upper;
for (i = 1; i < numranges; i++) { for (i = 1; i < numranges; i++)
cur = (INT4KEY *)DatumGetPointer( (((GISTENTRY *)(VARDATA(entryvec)))[i].key) ); {
if ( out->lower > cur->lower ) out->lower = cur->lower; cur = (INT4KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key));
if ( out->upper < cur->upper ) out->upper = cur->upper; if (out->lower > cur->lower)
} out->lower = cur->lower;
if (out->upper < cur->upper)
out->upper = cur->upper;
}
PG_RETURN_POINTER( out ); PG_RETURN_POINTER(out);
} }
Datum Datum
gint4_penalty(PG_FUNCTION_ARGS) gint4_penalty(PG_FUNCTION_ARGS)
{ {
INT4KEY *origentry = (INT4KEY*) DatumGetPointer( ((GISTENTRY*) PG_GETARG_POINTER(0))->key ); INT4KEY *origentry = (INT4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
INT4KEY *newentry = (INT4KEY*) DatumGetPointer( ((GISTENTRY*) PG_GETARG_POINTER(1))->key ); INT4KEY *newentry = (INT4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
float *result = (float*) PG_GETARG_POINTER(2); float *result = (float *) PG_GETARG_POINTER(2);
*result = Max( newentry->upper - origentry->upper, 0 ) +
Max( origentry->lower - newentry->lower, 0 );
PG_RETURN_POINTER( result ); *result = Max(newentry->upper - origentry->upper, 0) +
Max(origentry->lower - newentry->lower, 0);
PG_RETURN_POINTER(result);
} }
Datum Datum
gint4_picksplit(PG_FUNCTION_ARGS) gint4_picksplit(PG_FUNCTION_ARGS)
{ {
PG_RETURN_POINTER( btree_picksplit( PG_RETURN_POINTER(btree_picksplit(
(bytea*)PG_GETARG_POINTER(0), (bytea *) PG_GETARG_POINTER(0),
(GIST_SPLITVEC*)PG_GETARG_POINTER(1), (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
gint4_binary_union, gint4_binary_union,
int4key_cmp int4key_cmp
) ); ));
} }
Datum Datum
gint4_same(PG_FUNCTION_ARGS) gint4_same(PG_FUNCTION_ARGS)
{ {
INT4KEY *b1 = (INT4KEY*) PG_GETARG_POINTER(0); INT4KEY *b1 = (INT4KEY *) PG_GETARG_POINTER(0);
INT4KEY *b2 = (INT4KEY*) PG_GETARG_POINTER(1); INT4KEY *b2 = (INT4KEY *) PG_GETARG_POINTER(1);
bool *result = (bool*) PG_GETARG_POINTER(2); bool *result = (bool *) PG_GETARG_POINTER(2);
*result = ( b1->lower == b2->lower && b1->upper == b2->upper ) ? TRUE : FALSE; *result = (b1->lower == b2->lower && b1->upper == b2->upper) ? TRUE : FALSE;
PG_RETURN_POINTER(result); PG_RETURN_POINTER(result);
} }
static void static void
gint4_binary_union(Datum *r1, char *r2) gint4_binary_union(Datum *r1, char *r2)
{ {
INT4KEY *b1; INT4KEY *b1;
INT4KEY *b2 = (INT4KEY*) r2; INT4KEY *b2 = (INT4KEY *) r2;
if ( ! DatumGetPointer( *r1 ) ) {
*r1 = PointerGetDatum( palloc( sizeof(INT4KEY) ) );
b1 = (INT4KEY*)DatumGetPointer( *r1 );
b1->upper = b2->upper;
b1->lower = b2->lower;
} else {
b1 = (INT4KEY*)DatumGetPointer( *r1 );
b1->lower = ( b1->lower > b2->lower ) ? if (!DatumGetPointer(*r1))
b2->lower : b1->lower; {
b1->upper = ( b1->upper > b2->upper ) ? *r1 = PointerGetDatum(palloc(sizeof(INT4KEY)));
b1->upper : b2->upper; b1 = (INT4KEY *) DatumGetPointer(*r1);
} b1->upper = b2->upper;
b1->lower = b2->lower;
}
else
{
b1 = (INT4KEY *) DatumGetPointer(*r1);
b1->lower = (b1->lower > b2->lower) ?
b2->lower : b1->lower;
b1->upper = (b1->upper > b2->upper) ?
b1->upper : b2->upper;
}
} }
static int static int
int4key_cmp(const void *a, const void *b) { int4key_cmp(const void *a, const void *b)
return ( ((INT4KEY*)(((RIX*)a)->r))->lower - ((INT4KEY*)(((RIX*)b)->r))->lower ); {
return (((INT4KEY *) (((RIX *) a)->r))->lower - ((INT4KEY *) (((RIX *) b)->r))->lower);
} }
/************************************************** /**************************************************
* timestamp ops * timestamp ops
**************************************************/ **************************************************/
Datum Datum
gts_compress(PG_FUNCTION_ARGS) gts_compress(PG_FUNCTION_ARGS)
{ {
GISTENTRY *entry=(GISTENTRY*)PG_GETARG_POINTER(0); GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *retval; GISTENTRY *retval;
if (entry->leafkey)
{
TSKEY *r = (TSKEY *) palloc(sizeof(TSKEY));
if ( entry->leafkey) {
TSKEY *r = (TSKEY *)palloc( sizeof(TSKEY) );
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
if ( entry->key ) { if (entry->key)
r->lower = r->upper = *(Timestamp*)(entry->key); {
r->lower = r->upper = *(Timestamp *) (entry->key);
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(TSKEY), FALSE); entry->offset, sizeof(TSKEY), FALSE);
} else { }
else
{
gistentryinit(*retval, PointerGetDatum(NULL), gistentryinit(*retval, PointerGetDatum(NULL),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, 0, FALSE); entry->offset, 0, FALSE);
} }
} else {
retval = entry;
} }
PG_RETURN_POINTER( retval ); else
retval = entry;
PG_RETURN_POINTER(retval);
} }
Datum Datum
gts_consistent(PG_FUNCTION_ARGS) gts_consistent(PG_FUNCTION_ARGS)
{ {
GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0); GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
Timestamp *query = (Timestamp *)PG_GETARG_POINTER(1); Timestamp *query = (Timestamp *) PG_GETARG_POINTER(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
bool retval; bool retval;
TSKEY *key; TSKEY *key;
/*
** if entry is not leaf, use gbox_internal_consistent,
** else use gbox_leaf_consistent
*/
if ( ! entry->key )
return FALSE;
key = (TSKEY*) DatumGetPointer(entry->key);
switch(strategy) { /*
case BTLessEqualStrategyNumber: * * if entry is not leaf, use gbox_internal_consistent, * else use
retval = TSGE( query, &(key->lower) ); * gbox_leaf_consistent
break; */
case BTLessStrategyNumber: if (!entry->key)
if (GIST_LEAF(entry)) return FALSE;
retval = TSGT( query, &(key->lower) ); key = (TSKEY *) DatumGetPointer(entry->key);
else
retval = TSGE( query, &(key->lower) ); switch (strategy)
break; {
case BTEqualStrategyNumber: case BTLessEqualStrategyNumber:
/* in leaf page key->lower always = key->upper */ retval = TSGE(query, &(key->lower));
if (GIST_LEAF(entry)) break;
retval = TSEQ( query, &(key->lower)); case BTLessStrategyNumber:
else if (GIST_LEAF(entry))
retval = ( TSLE( &(key->lower), query ) && TSLE( query, &(key->upper) ) ); retval = TSGT(query, &(key->lower));
break; else
case BTGreaterStrategyNumber: retval = TSGE(query, &(key->lower));
if (GIST_LEAF(entry)) break;
retval = TSLT( query, &(key->upper) ); case BTEqualStrategyNumber:
else /* in leaf page key->lower always = key->upper */
retval = TSLE( query, &(key->upper) ); if (GIST_LEAF(entry))
break; retval = TSEQ(query, &(key->lower));
case BTGreaterEqualStrategyNumber: else
retval = TSLE( query, &(key->upper) ); retval = (TSLE(&(key->lower), query) && TSLE(query, &(key->upper)));
break; break;
default: case BTGreaterStrategyNumber:
retval = FALSE; if (GIST_LEAF(entry))
} retval = TSLT(query, &(key->upper));
PG_RETURN_BOOL(retval); else
retval = TSLE(query, &(key->upper));
break;
case BTGreaterEqualStrategyNumber:
retval = TSLE(query, &(key->upper));
break;
default:
retval = FALSE;
}
PG_RETURN_BOOL(retval);
} }
Datum Datum
gts_union(PG_FUNCTION_ARGS) gts_union(PG_FUNCTION_ARGS)
{ {
bytea *entryvec = (bytea*) PG_GETARG_POINTER(0); bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
int i, numranges; int i,
TSKEY *cur, *out=palloc(sizeof(TSKEY)); numranges;
TSKEY *cur,
*out = palloc(sizeof(TSKEY));
numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY); numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
*(int*) PG_GETARG_POINTER(1) = sizeof(TSKEY); *(int *) PG_GETARG_POINTER(1) = sizeof(TSKEY);
cur = (TSKEY *)DatumGetPointer( (((GISTENTRY *)(VARDATA(entryvec)))[0].key) ); cur = (TSKEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key));
out->lower = cur->lower; out->lower = cur->lower;
out->upper = cur->upper; out->upper = cur->upper;
for (i = 1; i < numranges; i++) { for (i = 1; i < numranges; i++)
cur = (TSKEY *)DatumGetPointer( (((GISTENTRY *)(VARDATA(entryvec)))[i].key) ); {
if ( TSGT( &out->lower, &cur->lower ) ) out->lower = cur->lower; cur = (TSKEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key));
if ( TSLT( &out->upper, &cur->upper ) ) out->upper = cur->upper; if (TSGT(&out->lower, &cur->lower))
} out->lower = cur->lower;
if (TSLT(&out->upper, &cur->upper))
out->upper = cur->upper;
}
PG_RETURN_POINTER( out ); PG_RETURN_POINTER(out);
} }
Datum Datum
gts_penalty(PG_FUNCTION_ARGS) gts_penalty(PG_FUNCTION_ARGS)
{ {
TSKEY *origentry = (TSKEY*) DatumGetPointer( ((GISTENTRY*) PG_GETARG_POINTER(0))->key ); TSKEY *origentry = (TSKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
TSKEY *newentry = (TSKEY*) DatumGetPointer( ((GISTENTRY*) PG_GETARG_POINTER(1))->key ); TSKEY *newentry = (TSKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
float *result = (float*) PG_GETARG_POINTER(2); float *result = (float *) PG_GETARG_POINTER(2);
Interval *intr; Interval *intr;
intr = DatumGetIntervalP( DirectFunctionCall2( intr = DatumGetIntervalP(DirectFunctionCall2(
timestamp_mi, timestamp_mi,
TimestampGetDatum( newentry->upper ), TimestampGetDatum(newentry->upper),
TimestampGetDatum( origentry->upper )) ); TimestampGetDatum(origentry->upper)));
/* see interval_larger */ /* see interval_larger */
*result = Max( intr->time+intr->month * (30.0 * 86400),0 ); *result = Max(intr->time + intr->month * (30.0 * 86400), 0);
pfree( intr ); pfree(intr);
intr = DatumGetIntervalP( DirectFunctionCall2( intr = DatumGetIntervalP(DirectFunctionCall2(
timestamp_mi, timestamp_mi,
TimestampGetDatum( origentry->lower ), TimestampGetDatum(origentry->lower),
TimestampGetDatum( newentry->lower )) ); TimestampGetDatum(newentry->lower)));
/* see interval_larger */ /* see interval_larger */
*result += Max( intr->time+intr->month * (30.0 * 86400),0 ); *result += Max(intr->time + intr->month * (30.0 * 86400), 0);
pfree( intr ); pfree(intr);
PG_RETURN_POINTER( result ); PG_RETURN_POINTER(result);
} }
Datum Datum
gts_picksplit(PG_FUNCTION_ARGS) gts_picksplit(PG_FUNCTION_ARGS)
{ {
PG_RETURN_POINTER( btree_picksplit( PG_RETURN_POINTER(btree_picksplit(
(bytea*)PG_GETARG_POINTER(0), (bytea *) PG_GETARG_POINTER(0),
(GIST_SPLITVEC*)PG_GETARG_POINTER(1), (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
gts_binary_union, gts_binary_union,
tskey_cmp tskey_cmp
) ); ));
} }
Datum Datum
gts_same(PG_FUNCTION_ARGS) gts_same(PG_FUNCTION_ARGS)
{ {
TSKEY *b1 = (TSKEY*) PG_GETARG_POINTER(0); TSKEY *b1 = (TSKEY *) PG_GETARG_POINTER(0);
TSKEY *b2 = (TSKEY*) PG_GETARG_POINTER(1); TSKEY *b2 = (TSKEY *) PG_GETARG_POINTER(1);
bool *result = (bool*) PG_GETARG_POINTER(2); bool *result = (bool *) PG_GETARG_POINTER(2);
if ( b1 && b2 )
*result = ( TSEQ( &(b1->lower), &(b2->lower) ) && TSEQ( &(b1->upper), &(b2->upper) ) ) ? TRUE : FALSE; if (b1 && b2)
else *result = (TSEQ(&(b1->lower), &(b2->lower)) && TSEQ(&(b1->upper), &(b2->upper))) ? TRUE : FALSE;
*result = ( b1==NULL && b2==NULL ) ? TRUE : FALSE; else
PG_RETURN_POINTER(result); *result = (b1 == NULL && b2 == NULL) ? TRUE : FALSE;
PG_RETURN_POINTER(result);
} }
static void static void
gts_binary_union(Datum *r1, char *r2) gts_binary_union(Datum *r1, char *r2)
{ {
TSKEY *b1; TSKEY *b1;
TSKEY *b2 = (TSKEY*) r2; TSKEY *b2 = (TSKEY *) r2;
if ( ! DatumGetPointer( *r1 ) ) { if (!DatumGetPointer(*r1))
*r1 = PointerGetDatum( palloc( sizeof(TSKEY) ) ); {
b1 = (TSKEY*)DatumGetPointer( *r1 ); *r1 = PointerGetDatum(palloc(sizeof(TSKEY)));
b1->upper = b2->upper; b1 = (TSKEY *) DatumGetPointer(*r1);
b1->lower = b2->lower; b1->upper = b2->upper;
} else { b1->lower = b2->lower;
b1 = (TSKEY*)DatumGetPointer( *r1 ); }
else
{
b1 = (TSKEY *) DatumGetPointer(*r1);
b1->lower = ( TSGT( &b1->lower, &b2->lower) ) ? b1->lower = (TSGT(&b1->lower, &b2->lower)) ?
b2->lower : b1->lower; b2->lower : b1->lower;
b1->upper = ( TSGT( &b1->upper, &b2->upper) ) ? b1->upper = (TSGT(&b1->upper, &b2->upper)) ?
b1->upper : b2->upper; b1->upper : b2->upper;
} }
} }
static int static int
tskey_cmp(const void *a, const void *b) { tskey_cmp(const void *a, const void *b)
return DatumGetInt32( {
DirectFunctionCall2( return DatumGetInt32(
timestamp_cmp, DirectFunctionCall2(
TimestampGetDatum( ((TSKEY*)(((RIX*)a)->r))->lower ), timestamp_cmp,
TimestampGetDatum( ((TSKEY*)(((RIX*)b)->r))->lower ) TimestampGetDatum(((TSKEY *) (((RIX *) a)->r))->lower),
) TimestampGetDatum(((TSKEY *) (((RIX *) b)->r))->lower)
); )
);
} }
/************************************************** /**************************************************
@ -466,43 +499,48 @@ tskey_cmp(const void *a, const void *b) {
static GIST_SPLITVEC * static GIST_SPLITVEC *
btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, BINARY_UNION bu, CMPFUNC cmp) btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, BINARY_UNION bu, CMPFUNC cmp)
{ {
OffsetNumber i; OffsetNumber i;
RIX *array; RIX *array;
OffsetNumber maxoff; OffsetNumber maxoff;
int nbytes; int nbytes;
maxoff = ((VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY)) - 1; maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 1;
nbytes = (maxoff + 2) * sizeof(OffsetNumber); nbytes = (maxoff + 2) * sizeof(OffsetNumber);
v->spl_left = (OffsetNumber *) palloc(nbytes); v->spl_left = (OffsetNumber *) palloc(nbytes);
v->spl_right = (OffsetNumber *) palloc(nbytes); v->spl_right = (OffsetNumber *) palloc(nbytes);
v->spl_nleft = 0; v->spl_nleft = 0;
v->spl_nright = 0; v->spl_nright = 0;
v->spl_ldatum = PointerGetDatum( 0 ); v->spl_ldatum = PointerGetDatum(0);
v->spl_rdatum = PointerGetDatum( 0 ); v->spl_rdatum = PointerGetDatum(0);
array = (RIX*)palloc( sizeof(RIX) * (maxoff+1) ); array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1));
/* copy the data into RIXes, and sort the RIXes */
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
array[i].index = i;
array[i].r=(char *)DatumGetPointer( (((GISTENTRY *)(VARDATA(entryvec)))[i].key) );
}
qsort((void*)&array[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1,
sizeof(RIX), cmp);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
if (i <= (maxoff - FirstOffsetNumber + 1)/2) {
v->spl_left[ v->spl_nleft ] = array[i].index;
v->spl_nleft++;
(*bu)( &v->spl_ldatum, array[i].r );
} else {
v->spl_right[ v->spl_nright ] = array[i].index;
v->spl_nright++;
(*bu)( &v->spl_rdatum, array[i].r );
}
}
pfree(array);
return( v ); /* copy the data into RIXes, and sort the RIXes */
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
array[i].index = i;
array[i].r = (char *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key));
}
qsort((void *) &array[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1,
sizeof(RIX), cmp);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
{
v->spl_left[v->spl_nleft] = array[i].index;
v->spl_nleft++;
(*bu) (&v->spl_ldatum, array[i].r);
}
else
{
v->spl_right[v->spl_nright] = array[i].index;
v->spl_nright++;
(*bu) (&v->spl_rdatum, array[i].r);
}
}
pfree(array);
return (v);
} }
/* /*
@ -512,38 +550,44 @@ btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, BINARY_UNION bu, CMPFUNC cmp)
Datum Datum
btree_decompress(PG_FUNCTION_ARGS) btree_decompress(PG_FUNCTION_ARGS)
{ {
PG_RETURN_POINTER(PG_GETARG_POINTER(0)); PG_RETURN_POINTER(PG_GETARG_POINTER(0));
} }
/************************************************** /**************************************************
* In/Out for keys, not really needed * In/Out for keys, not really needed
**************************************************/ **************************************************/
Datum Datum
int4key_in(PG_FUNCTION_ARGS) { int4key_in(PG_FUNCTION_ARGS)
INT4KEY *key = palloc(sizeof(INT4KEY)); {
INT4KEY *key = palloc(sizeof(INT4KEY));
if ( sscanf( PG_GETARG_POINTER(0), "%d|%d", &(key->lower), &(key->upper)) != 2 ) if (sscanf(PG_GETARG_POINTER(0), "%d|%d", &(key->lower), &(key->upper)) != 2)
elog(ERROR, "Error in input format"); elog(ERROR, "Error in input format");
PG_RETURN_POINTER( key );
}
Datum int4key_out(PG_FUNCTION_ARGS) { PG_RETURN_POINTER(key);
INT4KEY *key = (INT4KEY *) PG_GETARG_POINTER(0);
char *str=palloc(sizeof(char)*22);
sprintf(str,"%d|%d", key->lower, key->upper);
PG_RETURN_POINTER( str );
} }
Datum Datum
tskey_in(PG_FUNCTION_ARGS) { int4key_out(PG_FUNCTION_ARGS)
elog(ERROR, "Not implemented"); {
PG_RETURN_POINTER( NULL ); INT4KEY *key = (INT4KEY *) PG_GETARG_POINTER(0);
char *str = palloc(sizeof(char) * 22);
sprintf(str, "%d|%d", key->lower, key->upper);
PG_RETURN_POINTER(str);
} }
Datum Datum
tskey_out(PG_FUNCTION_ARGS) { tskey_in(PG_FUNCTION_ARGS)
{
elog(ERROR, "Not implemented"); elog(ERROR, "Not implemented");
PG_RETURN_POINTER( NULL ); PG_RETURN_POINTER(NULL);
}
Datum
tskey_out(PG_FUNCTION_ARGS)
{
elog(ERROR, "Not implemented");
PG_RETURN_POINTER(NULL);
} }

View File

@ -4,7 +4,7 @@
* darcy@druid.net * darcy@druid.net
* http://www.druid.net/darcy/ * http://www.druid.net/darcy/
* *
* $Id: chkpass.c,v 1.4 2001/05/30 02:11:46 darcy Exp $ * $Id: chkpass.c,v 1.5 2001/10/25 05:49:19 momjian Exp $
* best viewed with tabs set to 4 * best viewed with tabs set to 4
*/ */
@ -31,7 +31,7 @@
typedef struct chkpass typedef struct chkpass
{ {
char password[16]; char password[16];
} chkpass; } chkpass;
/* /*
@ -62,12 +62,12 @@ PG_FUNCTION_INFO_V1(chkpass_in)
Datum Datum
chkpass_in(PG_FUNCTION_ARGS) chkpass_in(PG_FUNCTION_ARGS)
{ {
char *str = PG_GETARG_CSTRING(0); char *str = PG_GETARG_CSTRING(0);
chkpass *result; chkpass *result;
char mysalt[4]; char mysalt[4];
static bool random_initialized = false; static bool random_initialized = false;
static char salt_chars[] = static char salt_chars[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/* special case to let us enter encrypted passwords */ /* special case to let us enter encrypted passwords */
if (*str == ':') if (*str == ':')
@ -81,7 +81,7 @@ chkpass_in(PG_FUNCTION_ARGS)
if (verify_pass(str) != 0) if (verify_pass(str) != 0)
{ {
elog(ERROR, "chkpass_in: purported CHKPASS \"%s\" is a weak password", elog(ERROR, "chkpass_in: purported CHKPASS \"%s\" is a weak password",
str); str);
PG_RETURN_POINTER(NULL); PG_RETURN_POINTER(NULL);
} }
@ -159,17 +159,18 @@ Datum
chkpass_eq(PG_FUNCTION_ARGS) chkpass_eq(PG_FUNCTION_ARGS)
{ {
chkpass *a1 = (chkpass *) PG_GETARG_POINTER(0); chkpass *a1 = (chkpass *) PG_GETARG_POINTER(0);
text *a2 = (text *) PG_GETARG_TEXT_P(1); text *a2 = (text *) PG_GETARG_TEXT_P(1);
char str[10]; char str[10];
int sz = 8; int sz = 8;
if (!a1 || !a2) if (!a1 || !a2)
PG_RETURN_BOOL(0); PG_RETURN_BOOL(0);
if (a2->vl_len < 12) sz = a2->vl_len - 4; if (a2->vl_len < 12)
sz = a2->vl_len - 4;
strncpy(str, a2->vl_dat, sz); strncpy(str, a2->vl_dat, sz);
str[sz] = 0; str[sz] = 0;
PG_RETURN_BOOL (strcmp(a1->password, crypt(str, a1->password)) == 0); PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) == 0);
} }
PG_FUNCTION_INFO_V1(chkpass_ne) PG_FUNCTION_INFO_V1(chkpass_ne)
@ -177,14 +178,15 @@ Datum
chkpass_ne(PG_FUNCTION_ARGS) chkpass_ne(PG_FUNCTION_ARGS)
{ {
chkpass *a1 = (chkpass *) PG_GETARG_POINTER(0); chkpass *a1 = (chkpass *) PG_GETARG_POINTER(0);
text *a2 = (text *) PG_GETARG_TEXT_P(1); text *a2 = (text *) PG_GETARG_TEXT_P(1);
char str[10]; char str[10];
int sz = 8; int sz = 8;
if (!a1 || !a2) PG_RETURN_BOOL(0); if (!a1 || !a2)
if (a2->vl_len < 12) sz = a2->vl_len - 4; PG_RETURN_BOOL(0);
if (a2->vl_len < 12)
sz = a2->vl_len - 4;
strncpy(str, a2->vl_dat, sz); strncpy(str, a2->vl_dat, sz);
str[sz] = 0; str[sz] = 0;
PG_RETURN_BOOL (strcmp(a1->password, crypt(str, a1->password)) != 0); PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) != 0);
} }

View File

@ -166,7 +166,6 @@ g_cube_consistent(GISTENTRY *entry,
NDBOX * query, NDBOX * query,
StrategyNumber strategy) StrategyNumber strategy)
{ {
/* /*
* if entry is not leaf, use g_cube_internal_consistent, else use * if entry is not leaf, use g_cube_internal_consistent, else use
* g_cube_leaf_consistent * g_cube_leaf_consistent
@ -206,7 +205,7 @@ g_cube_union(bytea *entryvec, int *sizep)
for (i = 1; i < numranges; i++) for (i = 1; i < numranges; i++)
{ {
out = g_cube_binary_union(tmp, (NDBOX *) out = g_cube_binary_union(tmp, (NDBOX *)
DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i]).key), DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i]).key),
sizep); sizep);
if (i > 1) if (i > 1)
pfree(tmp); pfree(tmp);
@ -220,13 +219,13 @@ g_cube_union(bytea *entryvec, int *sizep)
** GiST Compress and Decompress methods for boxes ** GiST Compress and Decompress methods for boxes
** do not do anything. ** do not do anything.
*/ */
GISTENTRY * GISTENTRY *
g_cube_compress(GISTENTRY *entry) g_cube_compress(GISTENTRY *entry)
{ {
return (entry); return (entry);
} }
GISTENTRY * GISTENTRY *
g_cube_decompress(GISTENTRY *entry) g_cube_decompress(GISTENTRY *entry)
{ {
return (entry); return (entry);
@ -365,7 +364,6 @@ g_cube_picksplit(bytea *entryvec,
maxoff = OffsetNumberNext(maxoff); maxoff = OffsetNumberNext(maxoff);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{ {
/* /*
* If we've already decided where to place this item, just put it * If we've already decided where to place this item, just put it
* on the right list. Otherwise, we need to figure out which page * on the right list. Otherwise, we need to figure out which page
@ -1001,7 +999,6 @@ cube_contains(NDBOX * box_a, NDBOX * box_b)
if (a->dim < b->dim) if (a->dim < b->dim)
{ {
/* /*
* the further comparisons will make sense if the excess * the further comparisons will make sense if the excess
* dimensions of (b) were zeroes * dimensions of (b) were zeroes

View File

@ -21,159 +21,171 @@
/* open a dbf-file, get it's field-info and store this information */ /* open a dbf-file, get it's field-info and store this information */
dbhead *dbf_open(u_char *file, int flags) { dbhead *
int file_no; dbf_open(u_char *file, int flags)
dbhead *dbh; {
f_descr *fields; int file_no;
dbf_header *head; dbhead *dbh;
dbf_field *fieldc; f_descr *fields;
dbf_header *head;
dbf_field *fieldc;
int t; int t;
if ((dbh = (dbhead *)malloc(sizeof(dbhead))) == NULL) { if ((dbh = (dbhead *) malloc(sizeof(dbhead))) == NULL)
return (dbhead *)DBF_ERROR; return (dbhead *) DBF_ERROR;
}
if ((head = (dbf_header *)malloc(sizeof(dbf_header))) == NULL) { if ((head = (dbf_header *) malloc(sizeof(dbf_header))) == NULL)
{
free(dbh); free(dbh);
return (dbhead *)DBF_ERROR; return (dbhead *) DBF_ERROR;
} }
if ((fieldc = (dbf_field *)malloc(sizeof(dbf_field))) == NULL) { if ((fieldc = (dbf_field *) malloc(sizeof(dbf_field))) == NULL)
{
free(head); free(head);
free(dbh); free(dbh);
return (dbhead *)DBF_ERROR; return (dbhead *) DBF_ERROR;
} }
if ((file_no = open(file, flags)) == -1) { if ((file_no = open(file, flags)) == -1)
{
free(fieldc); free(fieldc);
free(head); free(head);
free(dbh); free(dbh);
return (dbhead *)DBF_ERROR; return (dbhead *) DBF_ERROR;
} }
/* read in the disk-header */ /* read in the disk-header */
if (read(file_no, head, sizeof(dbf_header)) == -1) { if (read(file_no, head, sizeof(dbf_header)) == -1)
{
close(file_no); close(file_no);
free(fieldc); free(fieldc);
free(head); free(head);
free(dbh); free(dbh);
return (dbhead *)DBF_ERROR; return (dbhead *) DBF_ERROR;
} }
if (!(head->dbh_dbt & DBH_NORMAL)) { if (!(head->dbh_dbt & DBH_NORMAL))
close(file_no); {
free(fieldc); close(file_no);
free(head); free(fieldc);
free(dbh); free(head);
return (dbhead *)DBF_ERROR; free(dbh);
return (dbhead *) DBF_ERROR;
} }
dbh->db_fd = file_no; dbh->db_fd = file_no;
if (head->dbh_dbt & DBH_MEMO) { if (head->dbh_dbt & DBH_MEMO)
dbh->db_memo = 1; dbh->db_memo = 1;
} else { else
dbh->db_memo = 0; dbh->db_memo = 0;
}
dbh->db_year = head->dbh_year; dbh->db_year = head->dbh_year;
dbh->db_month = head->dbh_month; dbh->db_month = head->dbh_month;
dbh->db_day = head->dbh_day; dbh->db_day = head->dbh_day;
dbh->db_hlen = get_short((u_char *)&head->dbh_hlen); dbh->db_hlen = get_short((u_char *) &head->dbh_hlen);
dbh->db_records = get_long((u_char *)&head->dbh_records); dbh->db_records = get_long((u_char *) &head->dbh_records);
dbh->db_currec = 0; dbh->db_currec = 0;
dbh->db_rlen = get_short((u_char *)&head->dbh_rlen); dbh->db_rlen = get_short((u_char *) &head->dbh_rlen);
dbh->db_nfields = (dbh->db_hlen - sizeof(dbf_header)) / sizeof(dbf_field); dbh->db_nfields = (dbh->db_hlen - sizeof(dbf_header)) / sizeof(dbf_field);
/* dbh->db_hlen - sizeof(dbf_header) isn't the /*
correct size, cos dbh->hlen is in fact * dbh->db_hlen - sizeof(dbf_header) isn't the correct size, cos
a little more cos of the 0x0D (and * dbh->hlen is in fact a little more cos of the 0x0D (and possibly
possibly another byte, 0x4E, I have * another byte, 0x4E, I have seen this somewhere). Because of
seen this somewhere). Because of rounding * rounding everything turns out right :)
everything turns out right :) */ */
if ((fields = (f_descr *)calloc(dbh->db_nfields, sizeof(f_descr))) if ((fields = (f_descr *) calloc(dbh->db_nfields, sizeof(f_descr)))
== NULL) { == NULL)
close(file_no); {
free(fieldc); close(file_no);
free(head); free(fieldc);
free(dbh); free(head);
return (dbhead *)DBF_ERROR; free(dbh);
return (dbhead *) DBF_ERROR;
} }
for (t = 0; t < dbh->db_nfields; t++) { for (t = 0; t < dbh->db_nfields; t++)
{
/* Maybe I have calculated the number of fields incorrectly. This can happen /* Maybe I have calculated the number of fields incorrectly. This can happen
when programs reserve lots of space at the end of the header for future when programs reserve lots of space at the end of the header for future
expansion. This will catch this situation */ expansion. This will catch this situation */
if (fields[t].db_name[0] == 0x0D) { if (fields[t].db_name[0] == 0x0D)
{
dbh->db_nfields = t; dbh->db_nfields = t;
break; break;
} }
read(file_no, fieldc, sizeof(dbf_field)); read(file_no, fieldc, sizeof(dbf_field));
strncpy(fields[t].db_name, fieldc->dbf_name, DBF_NAMELEN); strncpy(fields[t].db_name, fieldc->dbf_name, DBF_NAMELEN);
fields[t].db_type = fieldc->dbf_type; fields[t].db_type = fieldc->dbf_type;
fields[t].db_flen = fieldc->dbf_flen; fields[t].db_flen = fieldc->dbf_flen;
fields[t].db_dec = fieldc->dbf_dec; fields[t].db_dec = fieldc->dbf_dec;
} }
dbh->db_offset = dbh->db_hlen; dbh->db_offset = dbh->db_hlen;
dbh->db_fields = fields; dbh->db_fields = fields;
if ((dbh->db_buff = (u_char *)malloc(dbh->db_rlen)) == NULL) { if ((dbh->db_buff = (u_char *) malloc(dbh->db_rlen)) == NULL)
return (dbhead *)DBF_ERROR; return (dbhead *) DBF_ERROR;
}
free(fieldc); free(fieldc);
free(head); free(head);
return dbh; return dbh;
} }
int dbf_write_head(dbhead *dbh) { int
dbf_write_head(dbhead * dbh)
{
dbf_header head; dbf_header head;
time_t now; time_t now;
struct tm *dbf_time; struct tm *dbf_time;
if (lseek(dbh->db_fd, 0, SEEK_SET) == -1) { if (lseek(dbh->db_fd, 0, SEEK_SET) == -1)
return DBF_ERROR; return DBF_ERROR;
}
/* fill up the diskheader */ /* fill up the diskheader */
/* Set dataarea of head to '\0' */ /* Set dataarea of head to '\0' */
memset(&head,'\0',sizeof(dbf_header)); memset(&head, '\0', sizeof(dbf_header));
head.dbh_dbt = DBH_NORMAL; head.dbh_dbt = DBH_NORMAL;
if (dbh->db_memo) head.dbh_dbt = DBH_MEMO; if (dbh->db_memo)
head.dbh_dbt = DBH_MEMO;
now = time((time_t *)NULL); now = time((time_t *) NULL);
dbf_time = localtime(&now); dbf_time = localtime(&now);
head.dbh_year = dbf_time->tm_year; head.dbh_year = dbf_time->tm_year;
head.dbh_month = dbf_time->tm_mon + 1; /* Months since January + 1 */ head.dbh_month = dbf_time->tm_mon + 1; /* Months since January +
* 1 */
head.dbh_day = dbf_time->tm_mday; head.dbh_day = dbf_time->tm_mday;
put_long(head.dbh_records, dbh->db_records); put_long(head.dbh_records, dbh->db_records);
put_short(head.dbh_hlen, dbh->db_hlen); put_short(head.dbh_hlen, dbh->db_hlen);
put_short(head.dbh_rlen, dbh->db_rlen); put_short(head.dbh_rlen, dbh->db_rlen);
if (write(dbh->db_fd, &head, sizeof(dbf_header)) != sizeof(dbf_header)) if (write(dbh->db_fd, &head, sizeof(dbf_header)) != sizeof(dbf_header))
return DBF_ERROR; return DBF_ERROR;
return 0; return 0;
} }
int dbf_put_fields(dbhead *dbh) { int
dbf_put_fields(dbhead * dbh)
{
dbf_field field; dbf_field field;
u_long t; u_long t;
u_char end = 0x0D; u_char end = 0x0D;
if (lseek(dbh->db_fd, sizeof(dbf_header), SEEK_SET) == -1) { if (lseek(dbh->db_fd, sizeof(dbf_header), SEEK_SET) == -1)
return DBF_ERROR; return DBF_ERROR;
}
/* Set dataarea of field to '\0' */ /* Set dataarea of field to '\0' */
memset(&field,'\0',sizeof(dbf_field)); memset(&field, '\0', sizeof(dbf_field));
for (t = 0; t < dbh->db_nfields; t++) { for (t = 0; t < dbh->db_nfields; t++)
{
strncpy(field.dbf_name, dbh->db_fields[t].db_name, DBF_NAMELEN - 1); strncpy(field.dbf_name, dbh->db_fields[t].db_name, DBF_NAMELEN - 1);
field.dbf_type = dbh->db_fields[t].db_type; field.dbf_type = dbh->db_fields[t].db_type;
field.dbf_flen = dbh->db_fields[t].db_flen; field.dbf_flen = dbh->db_fields[t].db_flen;
@ -189,16 +201,18 @@ int dbf_put_fields(dbhead *dbh) {
return 0; return 0;
} }
int dbf_add_field(dbhead *dbh, u_char *name, u_char type, int
u_char length, u_char dec) { dbf_add_field(dbhead * dbh, u_char *name, u_char type,
f_descr *ptr; u_char length, u_char dec)
u_char *foo; {
u_long size, field_no; f_descr *ptr;
u_char *foo;
u_long size,
field_no;
size = (dbh->db_nfields + 1) * sizeof(f_descr); size = (dbh->db_nfields + 1) * sizeof(f_descr);
if (!(ptr = (f_descr *) realloc(dbh->db_fields, size))) { if (!(ptr = (f_descr *) realloc(dbh->db_fields, size)))
return DBF_ERROR; return DBF_ERROR;
}
dbh->db_fields = ptr; dbh->db_fields = ptr;
field_no = dbh->db_nfields; field_no = dbh->db_nfields;
@ -211,71 +225,81 @@ u_long size, field_no;
dbh->db_hlen += sizeof(dbf_field); dbh->db_hlen += sizeof(dbf_field);
dbh->db_rlen += length; dbh->db_rlen += length;
if (!(foo = (u_char *) realloc(dbh->db_buff, dbh->db_rlen))) { if (!(foo = (u_char *) realloc(dbh->db_buff, dbh->db_rlen)))
return DBF_ERROR; return DBF_ERROR;
}
dbh->db_buff = foo; dbh->db_buff = foo;
return 0; return 0;
} }
dbhead *dbf_open_new(u_char *name, int flags) { dbhead *
dbhead *dbh; dbf_open_new(u_char *name, int flags)
{
dbhead *dbh;
if (!(dbh = (dbhead *)malloc(sizeof(dbhead)))) { if (!(dbh = (dbhead *) malloc(sizeof(dbhead))))
return (dbhead *)DBF_ERROR; return (dbhead *) DBF_ERROR;
}
if (flags & O_CREAT) { if (flags & O_CREAT)
if ((dbh->db_fd = open(name, flags, DBF_FILE_MODE)) == -1) { {
if ((dbh->db_fd = open(name, flags, DBF_FILE_MODE)) == -1)
{
free(dbh); free(dbh);
return (dbhead *)DBF_ERROR; return (dbhead *) DBF_ERROR;
}
} else {
if ((dbh->db_fd = open(name, flags)) == -1) {
free(dbh);
return (dbhead *)DBF_ERROR;
} }
} }
else
{
if ((dbh->db_fd = open(name, flags)) == -1)
{
free(dbh);
return (dbhead *) DBF_ERROR;
}
}
dbh->db_offset = 0; dbh->db_offset = 0;
dbh->db_memo = 0; dbh->db_memo = 0;
dbh->db_year = 0; dbh->db_year = 0;
dbh->db_month = 0; dbh->db_month = 0;
dbh->db_day = 0; dbh->db_day = 0;
dbh->db_hlen = sizeof(dbf_header) + 1; dbh->db_hlen = sizeof(dbf_header) + 1;
dbh->db_records = 0; dbh->db_records = 0;
dbh->db_currec = 0; dbh->db_currec = 0;
dbh->db_rlen = 1; dbh->db_rlen = 1;
dbh->db_nfields = 0; dbh->db_nfields = 0;
dbh->db_buff = NULL; dbh->db_buff = NULL;
dbh->db_fields = (f_descr *)NULL; dbh->db_fields = (f_descr *) NULL;
return dbh; return dbh;
} }
void dbf_close(dbhead *dbh) { void
int t; dbf_close(dbhead * dbh)
{
int t;
close(dbh->db_fd); close(dbh->db_fd);
for (t = 0; t < dbh->db_nfields; t++) { for (t = 0; t < dbh->db_nfields; t++)
free(&dbh->db_fields[t]); free(&dbh->db_fields[t]);
}
if (dbh->db_buff != NULL) { if (dbh->db_buff != NULL)
free(dbh->db_buff); free(dbh->db_buff);
}
free(dbh); free(dbh);
} }
int dbf_get_record(dbhead *dbh, field *fields, u_long rec) { int
u_char *data; dbf_get_record(dbhead * dbh, field * fields, u_long rec)
int t, i, offset; {
u_char *dbffield, *end; u_char *data;
int t,
i,
offset;
u_char *dbffield,
*end;
/* calculate at which offset we have to read. *DON'T* forget the /* calculate at which offset we have to read. *DON'T* forget the
0x0D which seperates field-descriptions from records! 0x0D which seperates field-descriptions from records!
@ -284,112 +308,133 @@ int dbf_get_record(dbhead *dbh, field *fields, u_long rec) {
*/ */
offset = dbh->db_hlen + (rec * dbh->db_rlen); offset = dbh->db_hlen + (rec * dbh->db_rlen);
if (lseek(dbh->db_fd, offset, SEEK_SET) == -1) { if (lseek(dbh->db_fd, offset, SEEK_SET) == -1)
{
lseek(dbh->db_fd, 0, SEEK_SET); lseek(dbh->db_fd, 0, SEEK_SET);
dbh->db_offset = 0; dbh->db_offset = 0;
return DBF_ERROR; return DBF_ERROR;
} }
dbh->db_offset = offset; dbh->db_offset = offset;
dbh->db_currec = rec; dbh->db_currec = rec;
data = dbh->db_buff; data = dbh->db_buff;
read(dbh->db_fd, data, dbh->db_rlen); read(dbh->db_fd, data, dbh->db_rlen);
if (data[0] == DBF_DELETED) { if (data[0] == DBF_DELETED)
return DBF_DELETED; return DBF_DELETED;
}
dbffield = &data[1]; dbffield = &data[1];
for (t = 0; t < dbh->db_nfields; t++) { for (t = 0; t < dbh->db_nfields; t++)
strncpy(fields[t].db_name, dbh->db_fields[t].db_name, DBF_NAMELEN); {
fields[t].db_type = dbh->db_fields[t].db_type; strncpy(fields[t].db_name, dbh->db_fields[t].db_name, DBF_NAMELEN);
fields[t].db_flen = dbh->db_fields[t].db_flen; fields[t].db_type = dbh->db_fields[t].db_type;
fields[t].db_dec = dbh->db_fields[t].db_dec; fields[t].db_flen = dbh->db_fields[t].db_flen;
fields[t].db_dec = dbh->db_fields[t].db_dec;
if (fields[t].db_type == 'C') { if (fields[t].db_type == 'C')
end = &dbffield[fields[t].db_flen - 1 ]; {
i = fields[t].db_flen; end = &dbffield[fields[t].db_flen - 1];
while (( i > 0) && ((*end < 0x21) || (*end > 0x7E))) { i = fields[t].db_flen;
end--; while ((i > 0) && ((*end < 0x21) || (*end > 0x7E)))
i--; {
} end--;
strncpy(fields[t].db_contents, dbffield, i); i--;
fields[t].db_contents[i] = '\0'; }
} else { strncpy(fields[t].db_contents, dbffield, i);
end = dbffield; fields[t].db_contents[i] = '\0';
i = fields[t].db_flen; }
while (( i > 0) && ((*end < 0x21) || (*end > 0x7E))) { else
end++; {
i--; end = dbffield;
} i = fields[t].db_flen;
strncpy(fields[t].db_contents, end, i); while ((i > 0) && ((*end < 0x21) || (*end > 0x7E)))
fields[t].db_contents[i] = '\0'; {
} end++;
i--;
}
strncpy(fields[t].db_contents, end, i);
fields[t].db_contents[i] = '\0';
}
dbffield += fields[t].db_flen; dbffield += fields[t].db_flen;
} }
dbh->db_offset += dbh->db_rlen; dbh->db_offset += dbh->db_rlen;
return DBF_VALID; return DBF_VALID;
} }
field *dbf_build_record(dbhead *dbh) { field *
int t; dbf_build_record(dbhead * dbh)
field *fields; {
int t;
field *fields;
if (!(fields = (field *)calloc(dbh->db_nfields, sizeof(field)))) { if (!(fields = (field *) calloc(dbh->db_nfields, sizeof(field))))
return (field *)DBF_ERROR; return (field *) DBF_ERROR;
}
for (t = 0; t < dbh->db_nfields; t++)
for ( t = 0; t < dbh->db_nfields; t++) { {
if (!(fields[t].db_contents = if (!(fields[t].db_contents =
(u_char *)malloc(dbh->db_fields[t].db_flen + 1))) { (u_char *) malloc(dbh->db_fields[t].db_flen + 1)))
for (t = 0; t < dbh->db_nfields; t++) { {
if (fields[t].db_contents != 0) { for (t = 0; t < dbh->db_nfields; t++)
{
if (fields[t].db_contents != 0)
{
free(fields[t].db_contents); free(fields[t].db_contents);
free(fields); free(fields);
} }
return (field *)DBF_ERROR; return (field *) DBF_ERROR;
} }
} }
strncpy(fields[t].db_name, dbh->db_fields[t].db_name, DBF_NAMELEN); strncpy(fields[t].db_name, dbh->db_fields[t].db_name, DBF_NAMELEN);
fields[t].db_type = dbh->db_fields[t].db_type; fields[t].db_type = dbh->db_fields[t].db_type;
fields[t].db_flen = dbh->db_fields[t].db_flen; fields[t].db_flen = dbh->db_fields[t].db_flen;
fields[t].db_dec = dbh->db_fields[t].db_dec; fields[t].db_dec = dbh->db_fields[t].db_dec;
} }
return fields; return fields;
} }
void dbf_free_record(dbhead *dbh, field *rec) { void
int t; dbf_free_record(dbhead * dbh, field * rec)
{
int t;
for ( t = 0; t < dbh->db_nfields; t++) { for (t = 0; t < dbh->db_nfields; t++)
free(rec[t].db_contents); free(rec[t].db_contents);
}
free(rec); free(rec);
} }
int dbf_put_record(dbhead *dbh, field *rec, u_long where) { int
u_long offset, new, idx, t, h, length; dbf_put_record(dbhead * dbh, field * rec, u_long where)
u_char *data, end = 0x1a; {
double fl; u_long offset,
u_char foo[128], format[32]; new,
idx,
t,
h,
length;
u_char *data,
end = 0x1a;
double fl;
u_char foo[128],
format[32];
/* offset: offset in file for this record /* offset: offset in file for this record
new: real offset after lseek new: real offset after lseek
idx: index to which place we are inside the 'hardcore'-data for this idx: index to which place we are inside the 'hardcore'-data for this
record record
t: field-counter t: field-counter
data: the hardcore-data that is put on disk data: the hardcore-data that is put on disk
h: index into the field-part in the hardcore-data h: index into the field-part in the hardcore-data
length: length of the data to copy length: length of the data to copy
fl: a float used to get the right precision with real numbers fl: a float used to get the right precision with real numbers
foo: copy of db_contents when field is not 'C' foo: copy of db_contents when field is not 'C'
format: sprintf format-string to get the right precision with real numbers format: sprintf format-string to get the right precision with real numbers
NOTE: this declaration of 'foo' can cause overflow when the contents-field NOTE: this declaration of 'foo' can cause overflow when the contents-field
is longer the 127 chars (which is highly unlikely, cos it is not used is longer the 127 chars (which is highly unlikely, cos it is not used
@ -399,16 +444,17 @@ int dbf_put_record(dbhead *dbh, field *rec, u_long where) {
DO A SEEK_END WITH 0!!!!!! USE -1 !!!!!!!!!! DO A SEEK_END WITH 0!!!!!! USE -1 !!!!!!!!!!
*/ */
if (where > dbh->db_records) { if (where > dbh->db_records)
if ((new = lseek(dbh->db_fd, -1, SEEK_END)) == -1) { {
if ((new = lseek(dbh->db_fd, -1, SEEK_END)) == -1)
return DBF_ERROR; return DBF_ERROR;
}
dbh->db_records++; dbh->db_records++;
} else { }
else
{
offset = dbh->db_hlen + (where * dbh->db_rlen); offset = dbh->db_hlen + (where * dbh->db_rlen);
if ((new = lseek(dbh->db_fd, offset, SEEK_SET)) == -1) { if ((new = lseek(dbh->db_fd, offset, SEEK_SET)) == -1)
return DBF_ERROR; return DBF_ERROR;
}
} }
dbh->db_offset = new; dbh->db_offset = new;
@ -416,49 +462,54 @@ int dbf_put_record(dbhead *dbh, field *rec, u_long where) {
data = dbh->db_buff; data = dbh->db_buff;
/* Set dataarea of data to ' ' (space) */ /* Set dataarea of data to ' ' (space) */
memset(data,' ',dbh->db_rlen); memset(data, ' ', dbh->db_rlen);
/* data[0] = DBF_VALID; */ /* data[0] = DBF_VALID; */
idx = 1; idx = 1;
for (t = 0; t < dbh->db_nfields; t++) { for (t = 0; t < dbh->db_nfields; t++)
{
/* if field is empty, don't do a thing */ /* if field is empty, don't do a thing */
if (rec[t].db_contents[0] != '\0') { if (rec[t].db_contents[0] != '\0')
{
/* Handle text */ /* Handle text */
if (rec[t].db_type == 'C') { if (rec[t].db_type == 'C')
if (strlen(rec[t].db_contents) > rec[t].db_flen) { {
length = rec[t].db_flen; if (strlen(rec[t].db_contents) > rec[t].db_flen)
} else { length = rec[t].db_flen;
length = strlen(rec[t].db_contents); else
length = strlen(rec[t].db_contents);
strncpy(data + idx, rec[t].db_contents, length);
} }
strncpy(data+idx, rec[t].db_contents, length); else
} else { {
/* Handle the rest */ /* Handle the rest */
/* Numeric is special, because of real numbers */ /* Numeric is special, because of real numbers */
if ((rec[t].db_type == 'N') && (rec[t].db_dec != 0)) { if ((rec[t].db_type == 'N') && (rec[t].db_dec != 0))
fl = atof(rec[t].db_contents); {
sprintf(format, "%%.%df", rec[t].db_dec); fl = atof(rec[t].db_contents);
sprintf(foo, format, fl); sprintf(format, "%%.%df", rec[t].db_dec);
} else { sprintf(foo, format, fl);
strcpy(foo, rec[t].db_contents); }
else
strcpy(foo, rec[t].db_contents);
if (strlen(foo) > rec[t].db_flen)
length = rec[t].db_flen;
else
length = strlen(foo);
h = rec[t].db_flen - length;
strncpy(data + idx + h, foo, length);
} }
if (strlen(foo) > rec[t].db_flen) {
length = rec[t].db_flen;
} else {
length = strlen(foo);
}
h = rec[t].db_flen - length;
strncpy(data+idx+h, foo, length);
} }
} idx += rec[t].db_flen;
idx += rec[t].db_flen;
} }
if (write(dbh->db_fd, data, dbh->db_rlen) != dbh->db_rlen) if (write(dbh->db_fd, data, dbh->db_rlen) != dbh->db_rlen)
return DBF_ERROR; return DBF_ERROR;
/* There's a 0x1A at the end of a dbf-file */ /* There's a 0x1A at the end of a dbf-file */
if (where == dbh->db_records) { if (where == dbh->db_records)
{
if (write(dbh->db_fd, &end, 1) != 1) if (write(dbh->db_fd, &end, 1) != 1)
return DBF_ERROR; return DBF_ERROR;
} }

View File

@ -26,7 +26,7 @@
/* maximum fieldname-length */ /* maximum fieldname-length */
#define DBF_NAMELEN 11 #define DBF_NAMELEN 11
/* magic-cookies for the file */ /* magic-cookies for the file */
@ -37,89 +37,93 @@
#define DBF_ERROR -1 #define DBF_ERROR -1
#define DBF_VALID 0x20 #define DBF_VALID 0x20
#define DBF_DELETED 0x2A #define DBF_DELETED 0x2A
/* diskheader */ /* diskheader */
typedef struct { typedef struct
u_char dbh_dbt; /* indentification field */ {
u_char dbh_year; /* last modification-date */ u_char dbh_dbt; /* indentification field */
u_char dbh_month; u_char dbh_year; /* last modification-date */
u_char dbh_day; u_char dbh_month;
u_char dbh_records[4]; /* number of records */ u_char dbh_day;
u_char dbh_hlen[2]; /* length of this header */ u_char dbh_records[4]; /* number of records */
u_char dbh_rlen[2]; /* length of a record */ u_char dbh_hlen[2]; /* length of this header */
u_char dbh_stub[20]; /* misc stuff we don't need */ u_char dbh_rlen[2]; /* length of a record */
} dbf_header; u_char dbh_stub[20]; /* misc stuff we don't need */
} dbf_header;
/* disk field-description */ /* disk field-description */
typedef struct { typedef struct
u_char dbf_name[DBF_NAMELEN]; /* field-name terminated with \0 */ {
u_char dbf_type; /* field-type */ u_char dbf_name[DBF_NAMELEN]; /* field-name terminated with \0 */
u_char dbf_reserved[4]; /* some reserved stuff */ u_char dbf_type; /* field-type */
u_char dbf_flen; /* field-length */ u_char dbf_reserved[4]; /* some reserved stuff */
u_char dbf_dec; /* number of decimal positions if u_char dbf_flen; /* field-length */
type is 'N' */ u_char dbf_dec; /* number of decimal positions if type is
u_char dbf_stub[14]; /* stuff we don't need */ * 'N' */
} dbf_field; u_char dbf_stub[14]; /* stuff we don't need */
} dbf_field;
/* memory field-description */ /* memory field-description */
typedef struct { typedef struct
u_char db_name[DBF_NAMELEN]; /* field-name terminated with \0 */ {
u_char db_type; /* field-type */ u_char db_name[DBF_NAMELEN]; /* field-name terminated with \0 */
u_char db_flen; /* field-length */ u_char db_type; /* field-type */
u_char db_dec; /* number of decimal positions */ u_char db_flen; /* field-length */
} f_descr; u_char db_dec; /* number of decimal positions */
} f_descr;
/* memory dfb-header */ /* memory dfb-header */
typedef struct { typedef struct
int db_fd; /* file-descriptor */ {
u_long db_offset; /* current offset in file */ int db_fd; /* file-descriptor */
u_char db_memo; /* memo-file present */ u_long db_offset; /* current offset in file */
u_char db_year; /* last update as YYMMDD */ u_char db_memo; /* memo-file present */
u_char db_month; u_char db_year; /* last update as YYMMDD */
u_char db_day; u_char db_month;
u_long db_hlen; /* length of the diskheader, for u_char db_day;
calculating the offsets */ u_long db_hlen; /* length of the diskheader, for
u_long db_records; /* number of records */ * calculating the offsets */
u_long db_currec; /* current record-number starting u_long db_records; /* number of records */
at 0 */ u_long db_currec; /* current record-number starting at 0 */
u_short db_rlen; /* length of the record */ u_short db_rlen; /* length of the record */
u_char db_nfields; /* number of fields */ u_char db_nfields; /* number of fields */
u_char *db_buff; /* record-buffer to save malloc()'s */ u_char *db_buff; /* record-buffer to save malloc()'s */
f_descr *db_fields; /* pointer to an array of field- f_descr *db_fields; /* pointer to an array of field-
descriptions */ * descriptions */
} dbhead; } dbhead;
/* structure that contains everything a user wants from a field, including /* structure that contains everything a user wants from a field, including
the contents (in ASCII). Warning! db_flen may be bigger than the actual the contents (in ASCII). Warning! db_flen may be bigger than the actual
length of db_name! This is because a field doesn't have to be completely length of db_name! This is because a field doesn't have to be completely
filled */ filled */
typedef struct { typedef struct
u_char db_name[DBF_NAMELEN]; /* field-name terminated with \0 */ {
u_char db_type; /* field-type */ u_char db_name[DBF_NAMELEN]; /* field-name terminated with \0 */
u_char db_flen; /* field-length */ u_char db_type; /* field-type */
u_char db_dec; /* number of decimal positions */ u_char db_flen; /* field-length */
u_char* db_contents; /* contents of the field in ASCII */ u_char db_dec; /* number of decimal positions */
} field; u_char *db_contents; /* contents of the field in ASCII */
} field;
/* prototypes for functions */ /* prototypes for functions */
extern dbhead* dbf_open(u_char *file ,int flags); extern dbhead *dbf_open(u_char *file, int flags);
extern int dbf_write_head(dbhead *dbh); extern int dbf_write_head(dbhead * dbh);
extern int dbf_put_fields(dbhead *dbh); extern int dbf_put_fields(dbhead * dbh);
extern int dbf_add_field(dbhead *dbh, u_char *name, u_char type, extern int dbf_add_field(dbhead * dbh, u_char *name, u_char type,
u_char length, u_char dec); u_char length, u_char dec);
extern dbhead * dbf_open_new(u_char *name, int flags); extern dbhead *dbf_open_new(u_char *name, int flags);
extern void dbf_close(dbhead *dbh); extern void dbf_close(dbhead * dbh);
extern int dbf_get_record(dbhead *dbh, field *fields, u_long rec); extern int dbf_get_record(dbhead * dbh, field * fields, u_long rec);
extern field* dbf_build_record(dbhead *dbh); extern field *dbf_build_record(dbhead * dbh);
extern void dbf_free_record(dbhead *dbh, field* fields); extern void dbf_free_record(dbhead * dbh, field * fields);
extern int dbf_put_record(dbhead *dbh, field *rec, u_long where); extern int dbf_put_record(dbhead * dbh, field * rec, u_long where);
/********************************************************************* /*********************************************************************
@ -131,5 +135,4 @@ extern long get_long(u_char *cp);
extern void put_long(u_char *cp, long lval); extern void put_long(u_char *cp, long lval);
extern short get_short(u_char *cp); extern short get_short(u_char *cp);
extern void put_short(u_char *cp, short lval); extern void put_short(u_char *cp, short lval);
#endif /* _DBF_H */
#endif /* _DBF_H */

File diff suppressed because it is too large Load Diff

View File

@ -5,41 +5,45 @@
/* /*
* routine to change little endian long to host long * routine to change little endian long to host long
*/ */
long get_long(u_char *cp) long
get_long(u_char *cp)
{ {
long ret; long ret;
ret = *cp++; ret = *cp++;
ret += ((*cp++)<<8); ret += ((*cp++) << 8);
ret += ((*cp++)<<16); ret += ((*cp++) << 16);
ret += ((*cp++)<<24); ret += ((*cp++) << 24);
return ret; return ret;
} }
void put_long(u_char *cp, long lval) void
put_long(u_char *cp, long lval)
{ {
cp[0] = lval & 0xff; cp[0] = lval & 0xff;
cp[1] = (lval >> 8) & 0xff; cp[1] = (lval >> 8) & 0xff;
cp[2] = (lval >> 16) & 0xff; cp[2] = (lval >> 16) & 0xff;
cp[3] = (lval >> 24) & 0xff; cp[3] = (lval >> 24) & 0xff;
} }
/* /*
* routine to change little endian short to host short * routine to change little endian short to host short
*/ */
short get_short(u_char *cp) short
get_short(u_char *cp)
{ {
short ret; short ret;
ret = *cp++; ret = *cp++;
ret += ((*cp++)<<8); ret += ((*cp++) << 8);
return ret; return ret;
} }
void put_short(u_char *cp, short sval) void
put_short(u_char *cp, short sval)
{ {
cp[0] = sval & 0xff; cp[0] = sval & 0xff;
cp[1] = (sval >> 8) & 0xff; cp[1] = (sval >> 8) & 0xff;
} }

View File

@ -4,18 +4,18 @@
* Functions returning results from a remote database * Functions returning results from a remote database
* *
* Copyright (c) Joseph Conway <joe.conway@mail.com>, 2001; * Copyright (c) Joseph Conway <joe.conway@mail.com>, 2001;
* *
* Permission to use, copy, modify, and distribute this software and its * Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without a written agreement * documentation for any purpose, without fee, and without a written agreement
* is hereby granted, provided that the above copyright notice and this * is hereby granted, provided that the above copyright notice and this
* paragraph and the following two paragraphs appear in all copies. * paragraph and the following two paragraphs appear in all copies.
* *
* IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
* LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
* DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
* THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIMS ANY WARRANTIES, * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
@ -30,29 +30,28 @@ PG_FUNCTION_INFO_V1(dblink);
Datum Datum
dblink(PG_FUNCTION_ARGS) dblink(PG_FUNCTION_ARGS)
{ {
PGconn *conn = NULL; PGconn *conn = NULL;
PGresult *res = NULL; PGresult *res = NULL;
dblink_results *results; dblink_results *results;
char *optstr; char *optstr;
char *sqlstatement; char *sqlstatement;
char *curstr = "DECLARE mycursor CURSOR FOR "; char *curstr = "DECLARE mycursor CURSOR FOR ";
char *execstatement; char *execstatement;
char *msg; char *msg;
int ntuples = 0; int ntuples = 0;
ReturnSetInfo *rsi; ReturnSetInfo *rsi;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) { if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
elog(ERROR, "dblink: NULL arguments are not permitted"); elog(ERROR, "dblink: NULL arguments are not permitted");
}
if (fcinfo->resultinfo == NULL || ! IsA(fcinfo->resultinfo, ReturnSetInfo)) { if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
elog(ERROR, "dblink: function called in context that does not accept a set result"); elog(ERROR, "dblink: function called in context that does not accept a set result");
}
optstr = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0)))); optstr = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
sqlstatement = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1)))); sqlstatement = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1))));
if (fcinfo->flinfo->fn_extra == NULL) { if (fcinfo->flinfo->fn_extra == NULL)
{
conn = PQconnectdb(optstr); conn = PQconnectdb(optstr);
if (PQstatus(conn) == CONNECTION_BAD) if (PQstatus(conn) == CONNECTION_BAD)
@ -73,13 +72,14 @@ dblink(PG_FUNCTION_ARGS)
PQclear(res); PQclear(res);
execstatement = (char *) palloc(strlen(curstr) + strlen(sqlstatement) + 1); execstatement = (char *) palloc(strlen(curstr) + strlen(sqlstatement) + 1);
if (execstatement != NULL) { if (execstatement != NULL)
{
strcpy(execstatement, curstr); strcpy(execstatement, curstr);
strcat(execstatement, sqlstatement); strcat(execstatement, sqlstatement);
strcat(execstatement, "\0"); strcat(execstatement, "\0");
} else {
elog(ERROR, "dblink: insufficient memory" );
} }
else
elog(ERROR, "dblink: insufficient memory");
res = PQexec(conn, execstatement); res = PQexec(conn, execstatement);
if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK && PQresultStatus(res) != PGRES_TUPLES_OK)) if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK && PQresultStatus(res) != PGRES_TUPLES_OK))
@ -88,23 +88,27 @@ dblink(PG_FUNCTION_ARGS)
PQclear(res); PQclear(res);
PQfinish(conn); PQfinish(conn);
elog(ERROR, "dblink: sql error: %s", msg); elog(ERROR, "dblink: sql error: %s", msg);
} else { }
else
{
/* /*
* got results, start fetching them * got results, start fetching them
*/ */
PQclear(res); PQclear(res);
res = PQexec(conn, "FETCH ALL in mycursor"); res = PQexec(conn, "FETCH ALL in mycursor");
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
{
msg = pstrdup(PQerrorMessage(conn)); msg = pstrdup(PQerrorMessage(conn));
PQclear(res); PQclear(res);
PQfinish(conn); PQfinish(conn);
elog(ERROR, "dblink: sql error: %s", msg); elog(ERROR, "dblink: sql error: %s", msg);
} }
ntuples = PQntuples(res); ntuples = PQntuples(res);
if (ntuples > 0) { if (ntuples > 0)
{
results = init_dblink_results(fcinfo->flinfo->fn_mcxt); results = init_dblink_results(fcinfo->flinfo->fn_mcxt);
results->tup_num = 0; results->tup_num = 0;
@ -116,44 +120,48 @@ dblink(PG_FUNCTION_ARGS)
results = NULL; results = NULL;
results = fcinfo->flinfo->fn_extra; results = fcinfo->flinfo->fn_extra;
/* close the cursor */ /* close the cursor */
res = PQexec(conn, "CLOSE mycursor"); res = PQexec(conn, "CLOSE mycursor");
PQclear(res); PQclear(res);
/* commit the transaction */ /* commit the transaction */
res = PQexec(conn, "COMMIT"); res = PQexec(conn, "COMMIT");
PQclear(res); PQclear(res);
/* close the connection to the database and cleanup */ /* close the connection to the database and cleanup */
PQfinish(conn); PQfinish(conn);
rsi = (ReturnSetInfo *)fcinfo->resultinfo; rsi = (ReturnSetInfo *) fcinfo->resultinfo;
rsi->isDone = ExprMultipleResult; rsi->isDone = ExprMultipleResult;
PG_RETURN_POINTER(results); PG_RETURN_POINTER(results);
} else { }
else
{
PQclear(res); PQclear(res);
/* close the cursor */ /* close the cursor */
res = PQexec(conn, "CLOSE mycursor"); res = PQexec(conn, "CLOSE mycursor");
PQclear(res); PQclear(res);
/* commit the transaction */ /* commit the transaction */
res = PQexec(conn, "COMMIT"); res = PQexec(conn, "COMMIT");
PQclear(res); PQclear(res);
/* close the connection to the database and cleanup */ /* close the connection to the database and cleanup */
PQfinish(conn); PQfinish(conn);
rsi = (ReturnSetInfo *)fcinfo->resultinfo; rsi = (ReturnSetInfo *) fcinfo->resultinfo;
rsi->isDone = ExprEndResult ; rsi->isDone = ExprEndResult;
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
} }
} else { }
else
{
/* /*
* check for more results * check for more results
*/ */
@ -162,29 +170,30 @@ dblink(PG_FUNCTION_ARGS)
results->tup_num++; results->tup_num++;
ntuples = PQntuples(results->res); ntuples = PQntuples(results->res);
if (results->tup_num < ntuples) { if (results->tup_num < ntuples)
{
/* /*
* fetch them if available * fetch them if available
*/ */
rsi = (ReturnSetInfo *)fcinfo->resultinfo; rsi = (ReturnSetInfo *) fcinfo->resultinfo;
rsi->isDone = ExprMultipleResult; rsi->isDone = ExprMultipleResult;
PG_RETURN_POINTER(results); PG_RETURN_POINTER(results);
} else { }
else
{
/* /*
* or if no more, clean things up * or if no more, clean things up
*/ */
results = fcinfo->flinfo->fn_extra; results = fcinfo->flinfo->fn_extra;
PQclear(results->res); PQclear(results->res);
rsi = (ReturnSetInfo *)fcinfo->resultinfo; rsi = (ReturnSetInfo *) fcinfo->resultinfo;
rsi->isDone = ExprEndResult ; rsi->isDone = ExprEndResult;
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
@ -204,48 +213,48 @@ PG_FUNCTION_INFO_V1(dblink_tok);
Datum Datum
dblink_tok(PG_FUNCTION_ARGS) dblink_tok(PG_FUNCTION_ARGS)
{ {
dblink_results *results; dblink_results *results;
int fldnum; int fldnum;
text *result_text; text *result_text;
char *result; char *result;
int nfields = 0; int nfields = 0;
int text_len = 0; int text_len = 0;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) { if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
elog(ERROR, "dblink: NULL arguments are not permitted"); elog(ERROR, "dblink: NULL arguments are not permitted");
}
results = (dblink_results *) PG_GETARG_POINTER(0); results = (dblink_results *) PG_GETARG_POINTER(0);
if (results == NULL) { if (results == NULL)
elog(ERROR, "dblink: function called with invalid result pointer"); elog(ERROR, "dblink: function called with invalid result pointer");
}
fldnum = PG_GETARG_INT32(1); fldnum = PG_GETARG_INT32(1);
if (fldnum < 0) { if (fldnum < 0)
elog(ERROR, "dblink: field number < 0 not permitted"); elog(ERROR, "dblink: field number < 0 not permitted");
}
nfields = PQnfields(results->res); nfields = PQnfields(results->res);
if (fldnum > (nfields - 1)) { if (fldnum > (nfields - 1))
elog(ERROR, "dblink: field number %d does not exist", fldnum); elog(ERROR, "dblink: field number %d does not exist", fldnum);
}
if (PQgetisnull(results->res, results->tup_num, fldnum) == 1) { if (PQgetisnull(results->res, results->tup_num, fldnum) == 1)
{
PG_RETURN_NULL(); PG_RETURN_NULL();
} else { }
else
{
text_len = PQgetlength(results->res, results->tup_num, fldnum); text_len = PQgetlength(results->res, results->tup_num, fldnum);
result = (char *) palloc(text_len + 1); result = (char *) palloc(text_len + 1);
if (result != NULL) { if (result != NULL)
{
strcpy(result, PQgetvalue(results->res, results->tup_num, fldnum)); strcpy(result, PQgetvalue(results->res, results->tup_num, fldnum));
strcat(result, "\0"); strcat(result, "\0");
} else {
elog(ERROR, "dblink: insufficient memory" );
} }
else
elog(ERROR, "dblink: insufficient memory");
result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(result))); result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(result)));
@ -267,8 +276,8 @@ dblink_tok(PG_FUNCTION_ARGS)
dblink_results * dblink_results *
init_dblink_results(MemoryContext fn_mcxt) init_dblink_results(MemoryContext fn_mcxt)
{ {
MemoryContext oldcontext; MemoryContext oldcontext;
dblink_results *retval; dblink_results *retval;
oldcontext = MemoryContextSwitchTo(fn_mcxt); oldcontext = MemoryContextSwitchTo(fn_mcxt);

View File

@ -4,18 +4,18 @@
* Functions returning results from a remote database * Functions returning results from a remote database
* *
* Copyright (c) Joseph Conway <joe.conway@mail.com>, 2001; * Copyright (c) Joseph Conway <joe.conway@mail.com>, 2001;
* *
* Permission to use, copy, modify, and distribute this software and its * Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without a written agreement * documentation for any purpose, without fee, and without a written agreement
* is hereby granted, provided that the above copyright notice and this * is hereby granted, provided that the above copyright notice and this
* paragraph and the following two paragraphs appear in all copies. * paragraph and the following two paragraphs appear in all copies.
* *
* IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
* LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
* DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
* THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIMS ANY WARRANTIES, * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
@ -52,9 +52,9 @@ typedef struct
/* /*
* the actual query results * the actual query results
*/ */
PGresult *res; PGresult *res;
} dblink_results; } dblink_results;
/* /*
* External declarations * External declarations
@ -66,5 +66,4 @@ extern Datum dblink_tok(PG_FUNCTION_ARGS);
* Internal declarations * Internal declarations
*/ */
dblink_results *init_dblink_results(MemoryContext fn_mcxt); dblink_results *init_dblink_results(MemoryContext fn_mcxt);
#endif /* DBLINK_H */ #endif /* DBLINK_H */

View File

@ -6,52 +6,52 @@
#include "commands/trigger.h" #include "commands/trigger.h"
/* /*
* Trigger function accepts variable number of arguments: * Trigger function accepts variable number of arguments:
* *
* 1. relation in which to store the substrings * 1. relation in which to store the substrings
* 2. fields to extract substrings from * 2. fields to extract substrings from
* *
* The relation in which to insert *must* have the following layout: * The relation in which to insert *must* have the following layout:
* *
* string varchar(#) * string varchar(#)
* id oid * id oid
* *
* where # is the largest size of the varchar columns being indexed * where # is the largest size of the varchar columns being indexed
* *
* Example: * Example:
* *
* -- Create the SQL function based on the compiled shared object * -- Create the SQL function based on the compiled shared object
* create function fti() returns opaque as * create function fti() returns opaque as
* '/usr/local/pgsql/lib/contrib/fti.so' language 'C'; * '/usr/local/pgsql/lib/contrib/fti.so' language 'C';
* *
* -- Create the FTI table * -- Create the FTI table
* create table product_fti (string varchar(255), id oid); * create table product_fti (string varchar(255), id oid);
* *
* -- Create an index to assist string matches * -- Create an index to assist string matches
* create index product_fti_string_idx on product_fti (string); * create index product_fti_string_idx on product_fti (string);
* *
* -- Create an index to assist trigger'd deletes * -- Create an index to assist trigger'd deletes
* create index product_fti_id_idx on product_fti (id); * create index product_fti_id_idx on product_fti (id);
* *
* -- Create an index on the product oid column to assist joins * -- Create an index on the product oid column to assist joins
* -- between the fti table and the product table * -- between the fti table and the product table
* create index product_oid_idx on product (oid); * create index product_oid_idx on product (oid);
* *
* -- Create the trigger to perform incremental changes to the full text index. * -- Create the trigger to perform incremental changes to the full text index.
* create trigger product_fti_trig after update or insert or delete on product * create trigger product_fti_trig after update or insert or delete on product
* for each row execute procedure fti(product_fti, title, artist); * for each row execute procedure fti(product_fti, title, artist);
* ^^^^^^^^^^^ * ^^^^^^^^^^^
* table where full text index is stored * table where full text index is stored
* ^^^^^^^^^^^^^ * ^^^^^^^^^^^^^
* columns to index in the base table * columns to index in the base table
* *
* After populating 'product', try something like: * After populating 'product', try something like:
* *
* SELECT DISTINCT(p.*) FROM product p, product_fti f1, product_fti f2 WHERE * SELECT DISTINCT(p.*) FROM product p, product_fti f1, product_fti f2 WHERE
* f1.string ~ '^slippery' AND f2.string ~ '^wet' AND p.oid=f1.id AND p.oid=f2.id; * f1.string ~ '^slippery' AND f2.string ~ '^wet' AND p.oid=f1.id AND p.oid=f2.id;
* *
* To check that your indicies are being used correctly, make sure you * To check that your indicies are being used correctly, make sure you
* EXPLAIN SELECT ... your test query above. * EXPLAIN SELECT ... your test query above.
* *
* CHANGELOG * CHANGELOG
* --------- * ---------
@ -76,14 +76,14 @@
* TODO * TODO
* ---- * ----
* *
* prevent generating duplicate words for an oid in the fti table * prevent generating duplicate words for an oid in the fti table
* save a plan for deletes * save a plan for deletes
* create a function that will make the index *after* we have populated * create a function that will make the index *after* we have populated
* the main table (probably first delete all contents to be sure there's * the main table (probably first delete all contents to be sure there's
* nothing in it, then re-populate the fti-table) * nothing in it, then re-populate the fti-table)
* *
* can we do something with operator overloading or a seperate function * can we do something with operator overloading or a seperate function
* that can build the final query automatigally? * that can build the final query automatigally?
*/ */
#define MAX_FTI_QUERY_LENGTH 8192 #define MAX_FTI_QUERY_LENGTH 8192
@ -103,16 +103,15 @@ char *StopWords[] = { /* list of words to skip in indexing */
"the", "the",
"yes" "yes"
}; };
#endif /* USE_STOP_WORDS */
#endif /* USE_STOP_WORDS */
/* stuff for caching query-plans, stolen from contrib/spi/\*.c */ /* stuff for caching query-plans, stolen from contrib/spi/\*.c */
typedef struct typedef struct
{ {
char *ident; char *ident;
int nplans; int nplans;
void **splan; void **splan;
} EPlan; } EPlan;
static EPlan *InsertPlans = NULL; static EPlan *InsertPlans = NULL;
static EPlan *DeletePlans = NULL; static EPlan *DeletePlans = NULL;
@ -201,13 +200,11 @@ fti(PG_FUNCTION_ARGS)
Oid *argtypes; Oid *argtypes;
Datum values[1]; Datum values[1];
EPlan *plan; EPlan *plan;
int i; int i;
snprintf(query, MAX_FTI_QUERY_LENGTH, "D%s", indexname); snprintf(query, MAX_FTI_QUERY_LENGTH, "D%s", indexname);
for (i = 1; i < nargs; i++) for (i = 1; i < nargs; i++)
{
snprintf(query, MAX_FTI_QUERY_LENGTH, "%s$%s", query, args[i]); snprintf(query, MAX_FTI_QUERY_LENGTH, "%s$%s", query, args[i]);
}
plan = find_plan(query, &DeletePlans, &nDeletePlans); plan = find_plan(query, &DeletePlans, &nDeletePlans);
if (plan->nplans <= 0) if (plan->nplans <= 0)
@ -238,23 +235,21 @@ fti(PG_FUNCTION_ARGS)
if (isinsert) if (isinsert)
{ {
char *substring; char *substring;
char *column; char *column;
void *pplan; void *pplan;
Oid *argtypes; Oid *argtypes;
Datum values[2]; Datum values[2];
int colnum; int colnum;
struct varlena *data; struct varlena *data;
EPlan *plan; EPlan *plan;
int i; int i;
char *buff; char *buff;
char *string; char *string;
snprintf(query, MAX_FTI_QUERY_LENGTH, "I%s", indexname); snprintf(query, MAX_FTI_QUERY_LENGTH, "I%s", indexname);
for (i = 1; i < nargs; i++) for (i = 1; i < nargs; i++)
{
snprintf(query, MAX_FTI_QUERY_LENGTH, "%s$%s", query, args[i]); snprintf(query, MAX_FTI_QUERY_LENGTH, "%s$%s", query, args[i]);
}
plan = find_plan(query, &InsertPlans, &nInsertPlans); plan = find_plan(query, &InsertPlans, &nInsertPlans);
@ -269,7 +264,7 @@ fti(PG_FUNCTION_ARGS)
/* prepare plan to gain speed */ /* prepare plan to gain speed */
snprintf(query, MAX_FTI_QUERY_LENGTH, "INSERT INTO %s (string, id) VALUES ($1, $2)", snprintf(query, MAX_FTI_QUERY_LENGTH, "INSERT INTO %s (string, id) VALUES ($1, $2)",
indexname); indexname);
pplan = SPI_prepare(query, 2, argtypes); pplan = SPI_prepare(query, 2, argtypes);
if (!pplan) if (!pplan)
elog(ERROR, "Full Text Indexing: SPI_prepare: Returned NULL in insert"); elog(ERROR, "Full Text Indexing: SPI_prepare: Returned NULL in insert");
@ -303,7 +298,7 @@ fti(PG_FUNCTION_ARGS)
string++; string++;
} }
data = (struct varlena *) palloc(sizeof(int32) + strlen(column) + 1); data = (struct varlena *) palloc(sizeof(int32) + strlen(column) +1);
buff = palloc(strlen(column) + 1); buff = palloc(strlen(column) + 1);
/* saves lots of calls in while-loop and in breakup() */ /* saves lots of calls in while-loop and in breakup() */
@ -348,7 +343,6 @@ breakup(char *string, char *substring)
while (cur_pos > string) /* don't read before start of 'string' */ while (cur_pos > string) /* don't read before start of 'string' */
{ {
/* /*
* skip pieces at the end of a string that are not alfa-numeric * skip pieces at the end of a string that are not alfa-numeric
* (ie. 'string$%^&', last_start first points to '&', and after * (ie. 'string$%^&', last_start first points to '&', and after
@ -409,7 +403,7 @@ is_stopword(char *text)
else else
StopHigh = StopMiddle; StopHigh = StopMiddle;
} }
#endif /* USE_STOP_WORDS */ #endif /* USE_STOP_WORDS */
return (false); return (false);
} }

View File

@ -24,13 +24,13 @@
* documentation for any purpose, without fee, and without a written agreement * documentation for any purpose, without fee, and without a written agreement
* is hereby granted, provided that the above copyright notice and this * is hereby granted, provided that the above copyright notice and this
* paragraph and the following two paragraphs appear in all copies. * paragraph and the following two paragraphs appear in all copies.
* *
* IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
* LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
* DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
* THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
@ -50,23 +50,22 @@ PG_FUNCTION_INFO_V1(levenshtein);
Datum Datum
levenshtein(PG_FUNCTION_ARGS) levenshtein(PG_FUNCTION_ARGS)
{ {
char *str_s; char *str_s;
char *str_s0; char *str_s0;
char *str_t; char *str_t;
int cols = 0; int cols = 0;
int rows = 0; int rows = 0;
int *u_cells; int *u_cells;
int *l_cells; int *l_cells;
int *tmp; int *tmp;
int i; int i;
int j; int j;
/* /*
* Fetch the arguments. * Fetch the arguments. str_s is referred to as the "source" cols =
* str_s is referred to as the "source" * length of source + 1 to allow for the initialization column str_t
* cols = length of source + 1 to allow for the initialization column * is referred to as the "target", rows = length of target + 1 rows =
* str_t is referred to as the "target", rows = length of target + 1 * length of target + 1 to allow for the initialization row
* rows = length of target + 1 to allow for the initialization row
*/ */
str_s = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0)))); str_s = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
str_t = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1)))); str_t = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1))));
@ -75,18 +74,19 @@ levenshtein(PG_FUNCTION_ARGS)
rows = strlen(str_t) + 1; rows = strlen(str_t) + 1;
/* /*
* Restrict the length of the strings being compared to something reasonable * Restrict the length of the strings being compared to something
* because we will have to perform rows * cols calcualtions. If longer strings need to be * reasonable because we will have to perform rows * cols
* compared, increase MAX_LEVENSHTEIN_STRLEN to suit (but within your tolerance for * calcualtions. If longer strings need to be compared, increase
* speed and memory usage). * MAX_LEVENSHTEIN_STRLEN to suit (but within your tolerance for speed
* and memory usage).
*/ */
if ((cols > MAX_LEVENSHTEIN_STRLEN + 1) || (rows > MAX_LEVENSHTEIN_STRLEN + 1)) if ((cols > MAX_LEVENSHTEIN_STRLEN + 1) || (rows > MAX_LEVENSHTEIN_STRLEN + 1))
elog(ERROR, "levenshtein: Arguments may not exceed %d characters in length", MAX_LEVENSHTEIN_STRLEN); elog(ERROR, "levenshtein: Arguments may not exceed %d characters in length", MAX_LEVENSHTEIN_STRLEN);
/* /*
* If either rows or cols is 0, the answer is the other value. * If either rows or cols is 0, the answer is the other value. This
* This makes sense since it would take that many insertions * makes sense since it would take that many insertions the build a
* the build a matching string * matching string
*/ */
if (cols == 0) if (cols == 0)
@ -96,8 +96,9 @@ levenshtein(PG_FUNCTION_ARGS)
PG_RETURN_INT32(cols); PG_RETURN_INT32(cols);
/* /*
* Allocate two vectors of integers. One will be used for the "upper" row, * Allocate two vectors of integers. One will be used for the "upper"
* the other for the "lower" row. Initialize the "upper" row to 0..cols * row, the other for the "lower" row. Initialize the "upper" row to
* 0..cols
*/ */
u_cells = palloc(sizeof(int) * cols); u_cells = palloc(sizeof(int) * cols);
for (i = 0; i < cols; i++) for (i = 0; i < cols; i++)
@ -106,33 +107,35 @@ levenshtein(PG_FUNCTION_ARGS)
l_cells = palloc(sizeof(int) * cols); l_cells = palloc(sizeof(int) * cols);
/* /*
* Use str_s0 to "rewind" the pointer to str_s in the nested for loop below * Use str_s0 to "rewind" the pointer to str_s in the nested for loop
* below
*/ */
str_s0 = str_s; str_s0 = str_s;
/* /*
* Loop throught the rows, starting at row 1. Row 0 is used for the initial * Loop throught the rows, starting at row 1. Row 0 is used for the
* "upper" row. * initial "upper" row.
*/ */
for (j = 1; j < rows; j++) for (j = 1; j < rows; j++)
{ {
/* /*
* We'll always start with col 1, * We'll always start with col 1, and initialize lower row col 0
* and initialize lower row col 0 to j * to j
*/ */
l_cells[0] = j; l_cells[0] = j;
for (i = 1; i < cols; i++) for (i = 1; i < cols; i++)
{ {
int c = 0; int c = 0;
int c1 = 0; int c1 = 0;
int c2 = 0; int c2 = 0;
int c3 = 0; int c3 = 0;
/* /*
* The "cost" value is 0 if the character at the current col position * The "cost" value is 0 if the character at the current col
* in the source string, matches the character at the current row position * position in the source string, matches the character at the
* in the target string; cost is 1 otherwise. * current row position in the target string; cost is 1
* otherwise.
*/ */
c = ((CHAREQ(str_s, str_t)) ? 0 : 1); c = ((CHAREQ(str_s, str_t)) ? 0 : 1);
@ -152,8 +155,7 @@ levenshtein(PG_FUNCTION_ARGS)
c3 = u_cells[i - 1] + c; c3 = u_cells[i - 1] + c;
/* /*
* The lower right cell is set to the minimum * The lower right cell is set to the minimum of c1, c2, c3
* of c1, c2, c3
*/ */
l_cells[i] = (c1 < c2 ? c1 : c2) < c3 ? (c1 < c2 ? c1 : c2) : c3; l_cells[i] = (c1 < c2 ? c1 : c2) < c3 ? (c1 < c2 ? c1 : c2) : c3;
@ -164,8 +166,8 @@ levenshtein(PG_FUNCTION_ARGS)
} }
/* /*
* Lower row now becomes the upper row, and the upper row * Lower row now becomes the upper row, and the upper row gets
* gets reused as the new lower row. * reused as the new lower row.
*/ */
tmp = u_cells; tmp = u_cells;
u_cells = l_cells; u_cells = l_cells;
@ -183,8 +185,8 @@ levenshtein(PG_FUNCTION_ARGS)
} }
/* /*
* Because the final value (at position row, col) was swapped from * Because the final value (at position row, col) was swapped from the
* the lower row to the upper row, that's where we'll find it. * lower row to the upper row, that's where we'll find it.
*/ */
PG_RETURN_INT32(u_cells[cols - 1]); PG_RETURN_INT32(u_cells[cols - 1]);
} }
@ -199,10 +201,10 @@ Datum
metaphone(PG_FUNCTION_ARGS) metaphone(PG_FUNCTION_ARGS)
{ {
int reqlen; int reqlen;
char *str_i; char *str_i;
size_t str_i_len; size_t str_i_len;
char *metaph; char *metaph;
text *result_text; text *result_text;
int retval; int retval;
str_i = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0)))); str_i = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
@ -240,7 +242,7 @@ metaphone(PG_FUNCTION_ARGS)
} }
/* /*
* Original code by Michael G Schwern starts here. * Original code by Michael G Schwern starts here.
* Code slightly modified for use as PostgreSQL * Code slightly modified for use as PostgreSQL
* function (palloc, etc). Original includes * function (palloc, etc). Original includes
@ -255,26 +257,28 @@ metaphone(PG_FUNCTION_ARGS)
/* Look at the current letter in the word */ /* Look at the current letter in the word */
#define Curr_Letter (toupper(word[w_idx])) #define Curr_Letter (toupper(word[w_idx]))
/* Go N letters back. */ /* Go N letters back. */
#define Look_Back_Letter(n) (w_idx >= n ? toupper(word[w_idx-n]) : '\0') #define Look_Back_Letter(n) (w_idx >= n ? toupper(word[w_idx-n]) : '\0')
/* Previous letter. I dunno, should this return null on failure? */ /* Previous letter. I dunno, should this return null on failure? */
#define Prev_Letter (Look_Back_Letter(1)) #define Prev_Letter (Look_Back_Letter(1))
/* Look two letters down. It makes sure you don't walk off the string. */ /* Look two letters down. It makes sure you don't walk off the string. */
#define After_Next_Letter (Next_Letter != '\0' ? toupper(word[w_idx+2]) \ #define After_Next_Letter (Next_Letter != '\0' ? toupper(word[w_idx+2]) \
: '\0') : '\0')
#define Look_Ahead_Letter(n) (toupper(Lookahead(word+w_idx, n))) #define Look_Ahead_Letter(n) (toupper(Lookahead(word+w_idx, n)))
/* Allows us to safely look ahead an arbitrary # of letters */ /* Allows us to safely look ahead an arbitrary # of letters */
/* I probably could have just used strlen... */ /* I probably could have just used strlen... */
char Lookahead(char * word, int how_far) { char
char letter_ahead = '\0'; /* null by default */ Lookahead(char *word, int how_far)
int idx; {
for(idx = 0; word[idx] != '\0' && idx < how_far; idx++); char letter_ahead = '\0'; /* null by default */
/* Edge forward in the string... */ int idx;
letter_ahead = word[idx]; /* idx will be either == to how_far or for (idx = 0; word[idx] != '\0' && idx < how_far; idx++);
* at the end of the string /* Edge forward in the string... */
*/
letter_ahead = word[idx]; /* idx will be either == to how_far or at
* the end of the string */
return letter_ahead; return letter_ahead;
} }
@ -282,29 +286,30 @@ char Lookahead(char * word, int how_far) {
/* phonize one letter */ /* phonize one letter */
#define Phonize(c) do {(*phoned_word)[p_idx++] = c;} while (0) #define Phonize(c) do {(*phoned_word)[p_idx++] = c;} while (0)
/* Slap a null character on the end of the phoned word */ /* Slap a null character on the end of the phoned word */
#define End_Phoned_Word do {(*phoned_word)[p_idx] = '\0';} while (0) #define End_Phoned_Word do {(*phoned_word)[p_idx] = '\0';} while (0)
/* How long is the phoned word? */ /* How long is the phoned word? */
#define Phone_Len (p_idx) #define Phone_Len (p_idx)
/* Note is a letter is a 'break' in the word */ /* Note is a letter is a 'break' in the word */
#define Isbreak(c) (!isalpha(c)) #define Isbreak(c) (!isalpha(c))
int _metaphone ( int
/* IN */ _metaphone(
char * word, /* IN */
int max_phonemes, char *word,
/* OUT */ int max_phonemes,
char ** phoned_word /* OUT */
) { char **phoned_word
int w_idx = 0; /* point in the phonization we're at. */ )
int p_idx = 0; /* end of the phoned phrase */ {
int w_idx = 0; /* point in the phonization we're at. */
int p_idx = 0; /* end of the phoned phrase */
/*-- Parameter checks --*/ /*-- Parameter checks --*/
/* /*
* Shouldn't be necessary, but left these here anyway * Shouldn't be necessary, but left these here anyway jec Aug 3, 2001
* jec Aug 3, 2001
*/ */
/* Negative phoneme length is meaningless */ /* Negative phoneme length is meaningless */
@ -314,13 +319,16 @@ int _metaphone (
/* Empty/null string is meaningless */ /* Empty/null string is meaningless */
if ((word == NULL) || !(strlen(word) > 0)) if ((word == NULL) || !(strlen(word) > 0))
elog(ERROR, "metaphone: Input string length must be > 0"); elog(ERROR, "metaphone: Input string length must be > 0");
/*-- Allocate memory for our phoned_phrase --*/ /*-- Allocate memory for our phoned_phrase --*/
if (max_phonemes == 0) { /* Assume largest possible */ if (max_phonemes == 0)
*phoned_word = palloc(sizeof(char) * strlen(word) + 1); { /* Assume largest possible */
*phoned_word = palloc(sizeof(char) * strlen(word) +1);
if (!*phoned_word) if (!*phoned_word)
return META_ERROR; return META_ERROR;
} else { }
else
{
*phoned_word = palloc(sizeof(char) * max_phonemes + 1); *phoned_word = palloc(sizeof(char) * max_phonemes + 1);
if (!*phoned_word) if (!*phoned_word)
return META_ERROR; return META_ERROR;
@ -328,62 +336,70 @@ int _metaphone (
/*-- The first phoneme has to be processed specially. --*/ /*-- The first phoneme has to be processed specially. --*/
/* Find our first letter */ /* Find our first letter */
for( ; !isalpha(Curr_Letter); w_idx++ ) { for (; !isalpha(Curr_Letter); w_idx++)
{
/* On the off chance we were given nothing but crap... */ /* On the off chance we were given nothing but crap... */
if( Curr_Letter == '\0' ) { if (Curr_Letter == '\0')
{
End_Phoned_Word End_Phoned_Word
return META_SUCCESS; /* For testing */ return META_SUCCESS; /* For testing */
} }
} }
switch (Curr_Letter) { switch (Curr_Letter)
/* AE becomes E */ {
/* AE becomes E */
case 'A': case 'A':
if( Next_Letter == 'E' ) { if (Next_Letter == 'E')
{
Phonize('E'); Phonize('E');
w_idx+=2; w_idx += 2;
} }
/* Remember, preserve vowels at the beginning */ /* Remember, preserve vowels at the beginning */
else { else
{
Phonize('A'); Phonize('A');
w_idx++; w_idx++;
} }
break; break;
/* [GKP]N becomes N */ /* [GKP]N becomes N */
case 'G': case 'G':
case 'K': case 'K':
case 'P': case 'P':
if( Next_Letter == 'N' ) { if (Next_Letter == 'N')
{
Phonize('N'); Phonize('N');
w_idx+=2; w_idx += 2;
} }
break; break;
/* WH becomes H,
WR becomes R /*
W if followed by a vowel */ * WH becomes H, WR becomes R W if followed by a vowel
*/
case 'W': case 'W':
if( Next_Letter == 'H' || if (Next_Letter == 'H' ||
Next_Letter == 'R' ) Next_Letter == 'R')
{ {
Phonize(Next_Letter); Phonize(Next_Letter);
w_idx+=2; w_idx += 2;
} }
else if ( isvowel(Next_Letter) ) { else if (isvowel(Next_Letter))
Phonize('W'); {
w_idx+=2; Phonize('W');
w_idx += 2;
} }
/* else ignore */ /* else ignore */
break; break;
/* X becomes S */ /* X becomes S */
case 'X': case 'X':
Phonize('S'); Phonize('S');
w_idx++; w_idx++;
break; break;
/* Vowels are kept */ /* Vowels are kept */
/* We did A already
case 'A': /*
case 'a': * We did A already case 'A': case 'a':
*/ */
case 'E': case 'E':
case 'I': case 'I':
case 'O': case 'O':
@ -395,220 +411,235 @@ int _metaphone (
/* do nothing */ /* do nothing */
break; break;
} }
/* On to the metaphoning */
for(; Curr_Letter != '\0' &&
(max_phonemes == 0 || Phone_Len < max_phonemes);
w_idx++) {
/* How many letters to skip because an eariler encoding handled
* multiple letters */
unsigned short int skip_letter = 0;
/* THOUGHT: It would be nice if, rather than having things like...
* well, SCI. For SCI you encode the S, then have to remember
* to skip the C. So the phonome SCI invades both S and C. It would /* On to the metaphoning */
* be better, IMHO, to skip the C from the S part of the encoding. for (; Curr_Letter != '\0' &&
* Hell, I'm trying it. (max_phonemes == 0 || Phone_Len < max_phonemes);
w_idx++)
{
/*
* How many letters to skip because an eariler encoding handled
* multiple letters
*/ */
unsigned short int skip_letter = 0;
/*
* THOUGHT: It would be nice if, rather than having things
* like... well, SCI. For SCI you encode the S, then have to
* remember to skip the C. So the phonome SCI invades both S and
* C. It would be better, IMHO, to skip the C from the S part of
* the encoding. Hell, I'm trying it.
*/
/* Ignore non-alphas */ /* Ignore non-alphas */
if( !isalpha(Curr_Letter) ) if (!isalpha(Curr_Letter))
continue; continue;
/* Drop duplicates, except CC */ /* Drop duplicates, except CC */
if( Curr_Letter == Prev_Letter && if (Curr_Letter == Prev_Letter &&
Curr_Letter != 'C' ) Curr_Letter != 'C')
continue; continue;
switch (Curr_Letter) { switch (Curr_Letter)
/* B -> B unless in MB */ {
/* B -> B unless in MB */
case 'B': case 'B':
if( Prev_Letter != 'M' ) if (Prev_Letter != 'M')
Phonize('B'); Phonize('B');
break; break;
/* 'sh' if -CIA- or -CH, but not SCH, except SCHW.
* (SCHW is handled in S) /*
* S if -CI-, -CE- or -CY- * 'sh' if -CIA- or -CH, but not SCH, except SCHW. (SCHW
* dropped if -SCI-, SCE-, -SCY- (handed in S) * is handled in S) S if -CI-, -CE- or -CY- dropped if
* else K * -SCI-, SCE-, -SCY- (handed in S) else K
*/ */
case 'C': case 'C':
if( MAKESOFT(Next_Letter) ) { /* C[IEY] */ if (MAKESOFT(Next_Letter))
if( After_Next_Letter == 'A' && { /* C[IEY] */
Next_Letter == 'I' ) { /* CIA */ if (After_Next_Letter == 'A' &&
Next_Letter == 'I')
{ /* CIA */
Phonize(SH); Phonize(SH);
} }
/* SC[IEY] */ /* SC[IEY] */
else if ( Prev_Letter == 'S' ) { else if (Prev_Letter == 'S')
/* Dropped */ {
} /* Dropped */
else {
Phonize('S');
} }
else
Phonize('S');
} }
else if ( Next_Letter == 'H' ) { else if (Next_Letter == 'H')
{
#ifndef USE_TRADITIONAL_METAPHONE #ifndef USE_TRADITIONAL_METAPHONE
if( After_Next_Letter == 'R' || if (After_Next_Letter == 'R' ||
Prev_Letter == 'S' ) { /* Christ, School */ Prev_Letter == 'S')
{ /* Christ, School */
Phonize('K'); Phonize('K');
} }
else { else
Phonize(SH); Phonize(SH);
}
#else #else
Phonize(SH); Phonize(SH);
#endif #endif
skip_letter++; skip_letter++;
} }
else { else
Phonize('K'); Phonize('K');
}
break; break;
/* J if in -DGE-, -DGI- or -DGY-
* else T /*
*/ * J if in -DGE-, -DGI- or -DGY- else T
*/
case 'D': case 'D':
if( Next_Letter == 'G' && if (Next_Letter == 'G' &&
MAKESOFT(After_Next_Letter) ) { MAKESOFT(After_Next_Letter))
{
Phonize('J'); Phonize('J');
skip_letter++; skip_letter++;
} }
else else
Phonize('T'); Phonize('T');
break; break;
/* F if in -GH and not B--GH, D--GH, -H--GH, -H---GH
* else dropped if -GNED, -GN, /*
* else dropped if -DGE-, -DGI- or -DGY- (handled in D) * F if in -GH and not B--GH, D--GH, -H--GH, -H---GH else
* else J if in -GE-, -GI, -GY and not GG * dropped if -GNED, -GN, else dropped if -DGE-, -DGI- or
* else K * -DGY- (handled in D) else J if in -GE-, -GI, -GY and
*/ * not GG else K
*/
case 'G': case 'G':
if( Next_Letter == 'H' ) { if (Next_Letter == 'H')
if( !( NOGHTOF(Look_Back_Letter(3)) || {
Look_Back_Letter(4) == 'H' ) ) { if (!(NOGHTOF(Look_Back_Letter(3)) ||
Look_Back_Letter(4) == 'H'))
{
Phonize('F'); Phonize('F');
skip_letter++; skip_letter++;
} }
else { else
{
/* silent */ /* silent */
} }
} }
else if( Next_Letter == 'N' ) { else if (Next_Letter == 'N')
if( Isbreak(After_Next_Letter) || {
( After_Next_Letter == 'E' && if (Isbreak(After_Next_Letter) ||
Look_Ahead_Letter(3) == 'D' ) ) { (After_Next_Letter == 'E' &&
Look_Ahead_Letter(3) == 'D'))
{
/* dropped */ /* dropped */
} }
else else
Phonize('K'); Phonize('K');
} }
else if( MAKESOFT(Next_Letter) && else if (MAKESOFT(Next_Letter) &&
Prev_Letter != 'G' ) { Prev_Letter != 'G')
Phonize('J'); Phonize('J');
} else
else {
Phonize('K'); Phonize('K');
}
break; break;
/* H if before a vowel and not after C,G,P,S,T */ /* H if before a vowel and not after C,G,P,S,T */
case 'H': case 'H':
if( isvowel(Next_Letter) && if (isvowel(Next_Letter) &&
!AFFECTH(Prev_Letter) ) !AFFECTH(Prev_Letter))
Phonize('H'); Phonize('H');
break; break;
/* dropped if after C
* else K /*
*/ * dropped if after C else K
*/
case 'K': case 'K':
if( Prev_Letter != 'C' ) if (Prev_Letter != 'C')
Phonize('K'); Phonize('K');
break; break;
/* F if before H
* else P /*
*/ * F if before H else P
*/
case 'P': case 'P':
if( Next_Letter == 'H' ) { if (Next_Letter == 'H')
Phonize('F'); Phonize('F');
} else
else {
Phonize('P'); Phonize('P');
}
break; break;
/* K
*/ /*
* K
*/
case 'Q': case 'Q':
Phonize('K'); Phonize('K');
break; break;
/* 'sh' in -SH-, -SIO- or -SIA- or -SCHW-
* else S /*
*/ * 'sh' in -SH-, -SIO- or -SIA- or -SCHW- else S
*/
case 'S': case 'S':
if( Next_Letter == 'I' && if (Next_Letter == 'I' &&
( After_Next_Letter == 'O' || (After_Next_Letter == 'O' ||
After_Next_Letter == 'A' ) ) { After_Next_Letter == 'A'))
Phonize(SH); Phonize(SH);
} else if (Next_Letter == 'H')
else if ( Next_Letter == 'H' ) { {
Phonize(SH); Phonize(SH);
skip_letter++; skip_letter++;
} }
#ifndef USE_TRADITIONAL_METAPHONE #ifndef USE_TRADITIONAL_METAPHONE
else if ( Next_Letter == 'C' && else if (Next_Letter == 'C' &&
Look_Ahead_Letter(2) == 'H' && Look_Ahead_Letter(2) == 'H' &&
Look_Ahead_Letter(3) == 'W' ) { Look_Ahead_Letter(3) == 'W')
{
Phonize(SH); Phonize(SH);
skip_letter += 2; skip_letter += 2;
} }
#endif #endif
else { else
Phonize('S'); Phonize('S');
}
break; break;
/* 'sh' in -TIA- or -TIO-
* else 'th' before H /*
* else T * 'sh' in -TIA- or -TIO- else 'th' before H else T
*/ */
case 'T': case 'T':
if( Next_Letter == 'I' && if (Next_Letter == 'I' &&
( After_Next_Letter == 'O' || (After_Next_Letter == 'O' ||
After_Next_Letter == 'A' ) ) { After_Next_Letter == 'A'))
Phonize(SH); Phonize(SH);
} else if (Next_Letter == 'H')
else if ( Next_Letter == 'H' ) { {
Phonize(TH); Phonize(TH);
skip_letter++; skip_letter++;
} }
else { else
Phonize('T'); Phonize('T');
}
break; break;
/* F */ /* F */
case 'V': case 'V':
Phonize('F'); Phonize('F');
break; break;
/* W before a vowel, else dropped */ /* W before a vowel, else dropped */
case 'W': case 'W':
if( isvowel(Next_Letter) ) if (isvowel(Next_Letter))
Phonize('W'); Phonize('W');
break; break;
/* KS */ /* KS */
case 'X': case 'X':
Phonize('K'); Phonize('K');
Phonize('S'); Phonize('S');
break; break;
/* Y if followed by a vowel */ /* Y if followed by a vowel */
case 'Y': case 'Y':
if( isvowel(Next_Letter) ) if (isvowel(Next_Letter))
Phonize('Y'); Phonize('Y');
break; break;
/* S */ /* S */
case 'Z': case 'Z':
Phonize('S'); Phonize('S');
break; break;
/* No transformation */ /* No transformation */
case 'F': case 'F':
case 'J': case 'J':
case 'L': case 'L':
@ -620,15 +651,15 @@ int _metaphone (
default: default:
/* nothing */ /* nothing */
break; break;
} /* END SWITCH */ } /* END SWITCH */
w_idx += skip_letter; w_idx += skip_letter;
} /* END FOR */ } /* END FOR */
End_Phoned_Word; End_Phoned_Word;
return(META_SUCCESS); return (META_SUCCESS);
} /* END metaphone */ } /* END metaphone */
/* /*

View File

@ -24,13 +24,13 @@
* documentation for any purpose, without fee, and without a written agreement * documentation for any purpose, without fee, and without a written agreement
* is hereby granted, provided that the above copyright notice and this * is hereby granted, provided that the above copyright notice and this
* paragraph and the following two paragraphs appear in all copies. * paragraph and the following two paragraphs appear in all copies.
* *
* IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
* LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
* DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
* THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
@ -88,7 +88,7 @@ static const char *soundex_table = "01230120022455012623010202";
*/ */
#define MAX_METAPHONE_STRLEN 255 #define MAX_METAPHONE_STRLEN 255
/* /*
* Original code by Michael G Schwern starts here. * Original code by Michael G Schwern starts here.
* Code slightly modified for use as PostgreSQL * Code slightly modified for use as PostgreSQL
* function (combined *.h into here). * function (combined *.h into here).
@ -96,26 +96,26 @@ static const char *soundex_table = "01230120022455012623010202";
/************************************************************************** /**************************************************************************
metaphone -- Breaks english phrases down into their phonemes. metaphone -- Breaks english phrases down into their phonemes.
Input Input
word -- An english word to be phonized word -- An english word to be phonized
max_phonemes -- How many phonemes to calculate. If 0, then it max_phonemes -- How many phonemes to calculate. If 0, then it
will phonize the entire phrase. will phonize the entire phrase.
phoned_word -- The final phonized word. (We'll allocate the phoned_word -- The final phonized word. (We'll allocate the
memory.) memory.)
Output Output
error -- A simple error flag, returns TRUE or FALSE error -- A simple error flag, returns TRUE or FALSE
NOTES: ALL non-alpha characters are ignored, this includes whitespace, NOTES: ALL non-alpha characters are ignored, this includes whitespace,
although non-alpha characters will break up phonemes. although non-alpha characters will break up phonemes.
****************************************************************************/ ****************************************************************************/
/************************************************************************** /**************************************************************************
my constants -- constants I like my constants -- constants I like
Probably redundant. Probably redundant.
***************************************************************************/ ***************************************************************************/
#define META_ERROR FALSE #define META_ERROR FALSE
@ -123,22 +123,23 @@ static const char *soundex_table = "01230120022455012623010202";
#define META_FAILURE FALSE #define META_FAILURE FALSE
/* I add modifications to the traditional metaphone algorithm that you /* I add modifications to the traditional metaphone algorithm that you
might find in books. Define this if you want metaphone to behave might find in books. Define this if you want metaphone to behave
traditionally */ traditionally */
#undef USE_TRADITIONAL_METAPHONE #undef USE_TRADITIONAL_METAPHONE
/* Special encodings */ /* Special encodings */
#define SH 'X' #define SH 'X'
#define TH '0' #define TH '0'
char Lookahead(char * word, int how_far); char Lookahead(char *word, int how_far);
int _metaphone ( int
/* IN */ _metaphone(
char * word, /* IN */
int max_phonemes, char *word,
/* OUT */ int max_phonemes,
char ** phoned_word /* OUT */
char **phoned_word
); );
/* Metachar.h ... little bits about characters for metaphone */ /* Metachar.h ... little bits about characters for metaphone */
@ -146,9 +147,9 @@ int _metaphone (
/*-- Character encoding array & accessing macros --*/ /*-- Character encoding array & accessing macros --*/
/* Stolen directly out of the book... */ /* Stolen directly out of the book... */
char _codes[26] = { char _codes[26] = {
1,16,4,16,9,2,4,16,9,2,0,2,2,2,1,4,0,2,4,4,1,0,0,0,8,0 1, 16, 4, 16, 9, 2, 4, 16, 9, 2, 0, 2, 2, 2, 1, 4, 0, 2, 4, 4, 1, 0, 0, 0, 8, 0
/* a b c d e f g h i j k l m n o p q r s t u v w x y z */ /* a b c d e f g h i j k l m n o p q r s t u v w x y z */
}; };
@ -157,16 +158,15 @@ char _codes[26] = {
#define isvowel(c) (ENCODE(c) & 1) /* AEIOU */ #define isvowel(c) (ENCODE(c) & 1) /* AEIOU */
/* These letters are passed through unchanged */ /* These letters are passed through unchanged */
#define NOCHANGE(c) (ENCODE(c) & 2) /* FJMNR */ #define NOCHANGE(c) (ENCODE(c) & 2) /* FJMNR */
/* These form dipthongs when preceding H */ /* These form dipthongs when preceding H */
#define AFFECTH(c) (ENCODE(c) & 4) /* CGPST */ #define AFFECTH(c) (ENCODE(c) & 4) /* CGPST */
/* These make C and G soft */ /* These make C and G soft */
#define MAKESOFT(c) (ENCODE(c) & 8) /* EIY */ #define MAKESOFT(c) (ENCODE(c) & 8) /* EIY */
/* These prevent GH from becoming F */ /* These prevent GH from becoming F */
#define NOGHTOF(c) (ENCODE(c) & 16) /* BDH */ #define NOGHTOF(c) (ENCODE(c) & 16) /* BDH */
#endif /* FUZZYSTRMATCH_H */ #endif /* FUZZYSTRMATCH_H */

View File

@ -1,7 +1,7 @@
/* /*
* PostgreSQL type definitions for managed LargeObjects. * PostgreSQL type definitions for managed LargeObjects.
* *
* $Header: /cvsroot/pgsql/contrib/lo/lo.c,v 1.8 2001/03/22 03:59:09 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/lo/lo.c,v 1.9 2001/10/25 05:49:19 momjian Exp $
* *
*/ */
@ -33,8 +33,8 @@ typedef Oid Blob;
*/ */
Blob *lo_in(char *str); /* Create from String */ Blob *lo_in(char *str); /* Create from String */
char *lo_out(Blob * addr);/* Output oid as String */ char *lo_out(Blob * addr); /* Output oid as String */
Oid lo_oid(Blob * addr);/* Return oid as an oid */ Oid lo_oid(Blob * addr); /* Return oid as an oid */
Blob *lo(Oid oid); /* Return Blob based on oid */ Blob *lo(Oid oid); /* Return Blob based on oid */
Datum lo_manage(PG_FUNCTION_ARGS); /* Trigger handler */ Datum lo_manage(PG_FUNCTION_ARGS); /* Trigger handler */
@ -64,7 +64,6 @@ lo_in(char *str)
} }
else else
{ {
/* /*
* There is no Oid passed, so create a new one * There is no Oid passed, so create a new one
*/ */
@ -140,7 +139,7 @@ lo_manage(PG_FUNCTION_ARGS)
TupleDesc tupdesc; /* Tuple Descriptor */ TupleDesc tupdesc; /* Tuple Descriptor */
HeapTuple rettuple; /* Tuple to be returned */ HeapTuple rettuple; /* Tuple to be returned */
bool isdelete; /* are we deleting? */ bool isdelete; /* are we deleting? */
HeapTuple newtuple = NULL;/* The new value for tuple */ HeapTuple newtuple = NULL; /* The new value for tuple */
HeapTuple trigtuple; /* The original value of tuple */ HeapTuple trigtuple; /* The original value of tuple */
if (!CALLED_AS_TRIGGER(fcinfo)) if (!CALLED_AS_TRIGGER(fcinfo))

View File

@ -229,7 +229,7 @@ msqlGetSequenceInfo(int a, char *b)
{ {
} }
m_field * m_field *
msqlFetchField(m_result * mr) msqlFetchField(m_result * mr)
{ {
m_field *m = (m_field *) mr->fieldCursor; m_field *m = (m_field *) mr->fieldCursor;
@ -242,7 +242,7 @@ msqlFetchField(m_result * mr)
return NULL; return NULL;
} }
m_result * m_result *
msqlListDBs(int a) msqlListDBs(int a)
{ {
m_result *m; m_result *m;
@ -256,7 +256,7 @@ msqlListDBs(int a)
return NULL; return NULL;
} }
m_result * m_result *
msqlListTables(int a) msqlListTables(int a)
{ {
m_result *m; m_result *m;
@ -272,13 +272,13 @@ msqlListTables(int a)
return NULL; return NULL;
} }
m_result * m_result *
msqlListFields(int a, char *b) msqlListFields(int a, char *b)
{ {
} }
m_result * m_result *
msqlListIndex(int a, char *b, char *c) msqlListIndex(int a, char *b, char *c)
{ {
m_result *m; m_result *m;
@ -294,7 +294,7 @@ msqlListIndex(int a, char *b, char *c)
return NULL; return NULL;
} }
m_result * m_result *
msqlStoreResult(void) msqlStoreResult(void)
{ {
if (queryres) if (queryres)

View File

@ -6,5 +6,4 @@ int unlisten(char *relname);
int max(int x, int y); int max(int x, int y);
int min(int x, int y); int min(int x, int y);
int active_listeners(text *relname); int active_listeners(text *relname);
#endif #endif

View File

@ -6,7 +6,7 @@
* copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001; * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
* licence: BSD * licence: BSD
* *
* $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/pg_controldata.c,v 1.4 2001/09/06 10:49:29 petere Exp $ * $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/pg_controldata.c,v 1.5 2001/10/25 05:49:19 momjian Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -24,7 +24,7 @@ dbState(DBState state)
{ {
switch (state) switch (state)
{ {
case DB_STARTUP: case DB_STARTUP:
return "STARTUP"; return "STARTUP";
case DB_SHUTDOWNED: case DB_SHUTDOWNED:
return "SHUTDOWNED"; return "SHUTDOWNED";

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_export.c,v 1.7 2001/03/22 06:16:06 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_export.c,v 1.8 2001/10/25 05:49:19 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -32,14 +32,14 @@ load_lolist(LODumpMaster * pgLO)
int i; int i;
int n; int n;
/* /*
* Now find any candidate tables who have columns of type oid. * Now find any candidate tables who have columns of type oid.
* *
* NOTE: System tables including pg_largeobject will be ignored. * NOTE: System tables including pg_largeobject will be ignored.
* Otherwise we'd end up dumping all LOs, referenced or not. * Otherwise we'd end up dumping all LOs, referenced or not.
* *
* NOTE: the system oid column is ignored, as it has attnum < 1. * NOTE: the system oid column is ignored, as it has attnum < 1. This
* This shouldn't matter for correctness, but it saves time. * shouldn't matter for correctness, but it saves time.
*/ */
pgLO->res = PQexec(pgLO->conn, pgLO->res = PQexec(pgLO->conn,
"SELECT c.relname, a.attname " "SELECT c.relname, a.attname "
@ -107,8 +107,7 @@ pglo_export(LODumpMaster * pgLO)
for (ll = pgLO->lolist; ll->lo_table != NULL; ll++) for (ll = pgLO->lolist; ll->lo_table != NULL; ll++)
{ {
/*
/*
* Query: find the LOs referenced by this column * Query: find the LOs referenced by this column
*/ */
sprintf(Qbuff, "SELECT DISTINCT l.loid FROM \"%s\" x, pg_largeobject l WHERE x.\"%s\" = l.loid", sprintf(Qbuff, "SELECT DISTINCT l.loid FROM \"%s\" x, pg_largeobject l WHERE x.\"%s\" = l.loid",

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_import.c,v 1.5 2001/03/22 06:16:06 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/lo_import.c,v 1.6 2001/10/25 05:49:19 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -50,7 +50,7 @@ pglo_import(LODumpMaster * pgLO)
sprintf(lo_path, "%s/%s", pgLO->space, path); sprintf(lo_path, "%s/%s", pgLO->space, path);
/* /*
* Import LO * Import LO
*/ */
if ((new_oid = lo_import(pgLO->conn, lo_path)) == 0) if ((new_oid = lo_import(pgLO->conn, lo_path)) == 0)
@ -78,7 +78,7 @@ pglo_import(LODumpMaster * pgLO)
pgLO->counter++; pgLO->counter++;
/* /*
* UPDATE oid in tab * UPDATE oid in tab
*/ */
sprintf(Qbuff, "UPDATE \"%s\" SET \"%s\"=%u WHERE \"%s\"=%u", sprintf(Qbuff, "UPDATE \"%s\" SET \"%s\"=%u WHERE \"%s\"=%u",

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/main.c,v 1.8 2001/03/22 06:16:06 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/main.c,v 1.9 2001/10/25 05:49:19 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -152,7 +152,7 @@ main(int argc, char **argv)
exit(RE_ERROR); exit(RE_ERROR);
} }
/* /*
* Check space * Check space
*/ */
if (!pgLO->space && !pgLO->action == ACTION_SHOW) if (!pgLO->space && !pgLO->action == ACTION_SHOW)
@ -170,7 +170,7 @@ main(int argc, char **argv)
exit(RE_ERROR); exit(RE_ERROR);
} }
/* /*
* Make connection * Make connection
*/ */
pgLO->conn = PQsetdbLogin(pgLO->host, NULL, NULL, NULL, pgLO->db, pgLO->conn = PQsetdbLogin(pgLO->host, NULL, NULL, NULL, pgLO->db,
@ -186,7 +186,7 @@ main(int argc, char **argv)
pgLO->user = PQuser(pgLO->conn); pgLO->user = PQuser(pgLO->conn);
/* /*
* Init index file * Init index file
*/ */
if (pgLO->action != ACTION_SHOW) if (pgLO->action != ACTION_SHOW)
@ -304,7 +304,6 @@ usage()
"-q run quietly\n" "-q run quietly\n"
"-w not dump, but show all LO in DB\n" "-w not dump, but show all LO in DB\n"
); /* puts() */ ); /* puts() */
#endif #endif
puts( puts(

View File

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* pg_dumplo * pg_dumplo
* *
* $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/pg_dumplo.h,v 1.4 2001/03/22 03:59:10 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/pg_dumplo.h,v 1.5 2001/10/25 05:49:19 momjian Exp $
* *
* Karel Zak 1999-2000 * Karel Zak 1999-2000
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -64,11 +64,11 @@ typedef struct
typedef enum typedef enum
{ {
ACTION_NONE, ACTION_NONE,
ACTION_SHOW, ACTION_SHOW,
ACTION_EXPORT_ATTR, ACTION_EXPORT_ATTR,
ACTION_EXPORT_ALL, ACTION_EXPORT_ALL,
ACTION_IMPORT ACTION_IMPORT
} PGLODUMP_ACTIONS; } PGLODUMP_ACTIONS;
extern char *progname; extern char *progname;
@ -78,5 +78,4 @@ extern void index_file(LODumpMaster * pgLO);
extern void load_lolist(LODumpMaster * pgLO); extern void load_lolist(LODumpMaster * pgLO);
extern void pglo_export(LODumpMaster * pgLO); extern void pglo_export(LODumpMaster * pgLO);
extern void pglo_import(LODumpMaster * pgLO); extern void pglo_import(LODumpMaster * pgLO);
#endif /* PG_DUMPLO_H */ #endif /* PG_DUMPLO_H */

View File

@ -23,7 +23,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.7 2001/10/25 00:55:48 momjian Exp $ * $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.8 2001/10/25 05:49:19 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -147,7 +147,6 @@ ReadControlFile(void)
if ((fd = open(ControlFilePath, O_RDONLY)) < 0) if ((fd = open(ControlFilePath, O_RDONLY)) < 0)
{ {
/* /*
* If pg_control is not there at all, or we can't read it, the * If pg_control is not there at all, or we can't read it, the
* odds are we've been handed a bad DataDir path, so give up. User * odds are we've been handed a bad DataDir path, so give up. User
@ -412,7 +411,6 @@ CheckControlVersion0(char *buffer, int len)
(char *) malloc(_INTL_MAXLOGRECSZ)); (char *) malloc(_INTL_MAXLOGRECSZ));
if (record == NULL) if (record == NULL)
{ {
/* /*
* We have to guess at the checkpoint contents. * We have to guess at the checkpoint contents.
*/ */
@ -493,7 +491,7 @@ ReadRecordV0(XLogRecPtr *RecPtr, char *buffer)
readFile = XLogFileOpen(readId, readSeg); readFile = XLogFileOpen(readId, readSeg);
if (readFile < 0) if (readFile < 0)
goto next_record_is_invalid; goto next_record_is_invalid;
readOff = (uint32) (-1);/* force read to occur below */ readOff = (uint32) (-1); /* force read to occur below */
} }
targetPageOff = ((RecPtr->xrecoff % XLogSegSize) / BLCKSZ) * BLCKSZ; targetPageOff = ((RecPtr->xrecoff % XLogSegSize) / BLCKSZ) * BLCKSZ;
@ -617,7 +615,6 @@ GuessControlValues(void)
{ {
#ifdef USE_LOCALE #ifdef USE_LOCALE
char *localeptr; char *localeptr;
#endif #endif
/* /*

View File

@ -1,5 +1,5 @@
/* /*
* $Header: /cvsroot/pgsql/contrib/pgbench/pgbench.c,v 1.11 2001/10/24 08:07:22 ishii Exp $ * $Header: /cvsroot/pgsql/contrib/pgbench/pgbench.c,v 1.12 2001/10/25 05:49:19 momjian Exp $
* *
* pgbench: a simple TPC-B like benchmark program for PostgreSQL * pgbench: a simple TPC-B like benchmark program for PostgreSQL
* written by Tatsuo Ishii * written by Tatsuo Ishii
@ -39,7 +39,6 @@
/* for getrlimit */ /* for getrlimit */
#include <sys/resource.h> #include <sys/resource.h>
#endif /* WIN32 */ #endif /* WIN32 */
/******************************************************************** /********************************************************************
@ -67,7 +66,8 @@ int tps = 1;
int remains; /* number of remained clients */ int remains; /* number of remained clients */
int is_connect; /* establish connection for each transactoin */ int is_connect; /* establish connection for each
* transactoin */
char *pghost = ""; char *pghost = "";
char *pgport = NULL; char *pgport = NULL;
@ -107,31 +107,32 @@ getrand(int min, int max)
} }
/* set up a connection to the backend */ /* set up a connection to the backend */
static PGconn *doConnect() static PGconn *
doConnect()
{ {
PGconn *con; PGconn *con;
con = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, con = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName,
login, pwd); login, pwd);
if (con == NULL) if (con == NULL)
{ {
fprintf(stderr, "Connection to database '%s' failed.\n", dbName); fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
fprintf(stderr, "Memory allocatin problem?\n"); fprintf(stderr, "Memory allocatin problem?\n");
return(NULL); return (NULL);
} }
if (PQstatus(con) == CONNECTION_BAD)
{
fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
if (PQerrorMessage(con)) if (PQstatus(con) == CONNECTION_BAD)
fprintf(stderr, "%s", PQerrorMessage(con)); {
else fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
fprintf(stderr, "No explanation from the backend\n");
return(NULL); if (PQerrorMessage(con))
} fprintf(stderr, "%s", PQerrorMessage(con));
return (con); else
fprintf(stderr, "No explanation from the backend\n");
return (NULL);
}
return (con);
} }
/* throw away response from backend */ /* throw away response from backend */
@ -162,7 +163,7 @@ check(CState * state, PGresult *res, int n, int good)
st->con = NULL; st->con = NULL;
return (-1); return (-1);
} }
return (0); /* OK */ return (0); /* OK */
} }
/* process a transaction */ /* process a transaction */
@ -242,8 +243,8 @@ doOne(CState * state, int n, int debug)
if (is_connect) if (is_connect)
{ {
PQfinish(st->con); PQfinish(st->con);
st->con = NULL; st->con = NULL;
} }
if (++st->cnt >= nxacts) if (++st->cnt >= nxacts)
@ -251,8 +252,8 @@ doOne(CState * state, int n, int debug)
remains--; /* I've done */ remains--; /* I've done */
if (st->con != NULL) if (st->con != NULL)
{ {
PQfinish(st->con); PQfinish(st->con);
st->con = NULL; st->con = NULL;
} }
return; return;
} }
@ -267,15 +268,15 @@ doOne(CState * state, int n, int debug)
if (st->con == NULL) if (st->con == NULL)
{ {
if ((st->con = doConnect()) == NULL) if ((st->con = doConnect()) == NULL)
{ {
fprintf(stderr, "Client %d aborted in establishing connection.\n", fprintf(stderr, "Client %d aborted in establishing connection.\n",
n); n);
remains--; /* I've aborted */ remains--; /* I've aborted */
PQfinish(st->con); PQfinish(st->con);
st->con = NULL; st->con = NULL;
return; return;
} }
} }
switch (st->state) switch (st->state)
@ -358,8 +359,8 @@ doSelectOnly(CState * state, int n, int debug)
if (is_connect) if (is_connect)
{ {
PQfinish(st->con); PQfinish(st->con);
st->con = NULL; st->con = NULL;
} }
if (++st->cnt >= nxacts) if (++st->cnt >= nxacts)
@ -367,8 +368,8 @@ doSelectOnly(CState * state, int n, int debug)
remains--; /* I've done */ remains--; /* I've done */
if (st->con != NULL) if (st->con != NULL)
{ {
PQfinish(st->con); PQfinish(st->con);
st->con = NULL; st->con = NULL;
} }
return; return;
} }
@ -383,15 +384,15 @@ doSelectOnly(CState * state, int n, int debug)
if (st->con == NULL) if (st->con == NULL)
{ {
if ((st->con = doConnect()) == NULL) if ((st->con = doConnect()) == NULL)
{ {
fprintf(stderr, "Client %d aborted in establishing connection.\n", fprintf(stderr, "Client %d aborted in establishing connection.\n",
n); n);
remains--; /* I've aborted */ remains--; /* I've aborted */
PQfinish(st->con); PQfinish(st->con);
st->con = NULL; st->con = NULL;
return; return;
} }
} }
switch (st->state) switch (st->state)
@ -450,7 +451,7 @@ init()
int i; int i;
if ((con = doConnect()) == NULL) if ((con = doConnect()) == NULL)
exit(1); exit(1);
for (i = 0; i < (sizeof(DDLs) / sizeof(char *)); i++) for (i = 0; i < (sizeof(DDLs) / sizeof(char *)); i++)
{ {
@ -532,29 +533,30 @@ init()
if (j % 10000 == 0) if (j % 10000 == 0)
{ {
/* /*
* every 10000 tuples, we commit the copy command. * every 10000 tuples, we commit the copy command. this should
* this should avoid generating too much WAL logs * avoid generating too much WAL logs
*/ */
fprintf(stderr, "%d tuples done.\n", j); fprintf(stderr, "%d tuples done.\n", j);
if (PQputline(con, "\\.\n")) if (PQputline(con, "\\.\n"))
{ {
fprintf(stderr, "very last PQputline failed\n"); fprintf(stderr, "very last PQputline failed\n");
exit(1); exit(1);
} }
if (PQendcopy(con)) if (PQendcopy(con))
{ {
fprintf(stderr, "PQendcopy failed\n"); fprintf(stderr, "PQendcopy failed\n");
exit(1); exit(1);
} }
/* /*
* do a checkpoint to purge the old WAL logs * do a checkpoint to purge the old WAL logs
*/ */
res = PQexec(con, "checkpoint"); res = PQexec(con, "checkpoint");
if (PQresultStatus(res) != PGRES_COMMAND_OK) if (PQresultStatus(res) != PGRES_COMMAND_OK)
{ {
fprintf(stderr, "%s", PQerrorMessage(con)); fprintf(stderr, "%s", PQerrorMessage(con));
exit(1); exit(1);
} }
} }
} }
@ -634,7 +636,6 @@ main(int argc, char **argv)
#ifndef __CYGWIN__ #ifndef __CYGWIN__
struct rlimit rlim; struct rlimit rlim;
#endif #endif
PGconn *con; PGconn *con;
@ -691,9 +692,9 @@ main(int argc, char **argv)
} }
#endif /* #ifndef __CYGWIN__ */ #endif /* #ifndef __CYGWIN__ */
break; break;
case 'C': case 'C':
is_connect = 1; is_connect = 1;
break; break;
case 's': case 's':
tps = atoi(optarg); tps = atoi(optarg);
if (tps <= 0) if (tps <= 0)
@ -734,7 +735,7 @@ main(int argc, char **argv)
if (is_init_mode) if (is_init_mode)
{ {
init(); init();
exit(0); exit(0);
} }
@ -749,7 +750,7 @@ main(int argc, char **argv)
/* opening connection... */ /* opening connection... */
con = doConnect(); con = doConnect();
if (con == NULL) if (con == NULL)
exit(1); exit(1);
if (PQstatus(con) == CONNECTION_BAD) if (PQstatus(con) == CONNECTION_BAD)
{ {
@ -836,12 +837,12 @@ main(int argc, char **argv)
if (is_connect == 0) if (is_connect == 0)
{ {
/* make connections to the database */ /* make connections to the database */
for (i = 0; i < nclients; i++) for (i = 0; i < nclients; i++)
{ {
if ((state[i].con = doConnect()) == NULL) if ((state[i].con = doConnect()) == NULL)
exit(1); exit(1);
} }
} }
/* time after connections set up */ /* time after connections set up */

View File

@ -11,15 +11,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by Niels Provos. * This product includes software developed by Niels Provos.
* 4. The name of the author may not be used to endorse or promote products * 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -46,338 +46,354 @@
#undef inline #undef inline
#ifdef __GNUC__ #ifdef __GNUC__
#define inline __inline #define inline __inline
#else /* !__GNUC__ */ #else /* !__GNUC__ */
#define inline #define inline
#endif /* !__GNUC__ */ #endif /* !__GNUC__ */
/* Function for Feistel Networks */ /* Function for Feistel Networks */
#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \ #define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \
+ (s)[0x100 + (((x)>>16)&0xFF)]) \ + (s)[0x100 + (((x)>>16)&0xFF)]) \
^ (s)[0x200 + (((x)>> 8)&0xFF)]) \ ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \
+ (s)[0x300 + ( (x) &0xFF)]) + (s)[0x300 + ( (x) &0xFF)])
#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n]) #define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
void void
Blowfish_encipher(blf_ctx *c, uint32 *x) Blowfish_encipher(blf_ctx * c, uint32 *x)
{ {
uint32 Xl; uint32 Xl;
uint32 Xr; uint32 Xr;
uint32 *s = c->S[0]; uint32 *s = c->S[0];
uint32 *p = c->P; uint32 *p = c->P;
Xl = x[0]; Xl = x[0];
Xr = x[1]; Xr = x[1];
Xl ^= p[0]; Xl ^= p[0];
BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2); BLFRND(s, p, Xr, Xl, 1);
BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4); BLFRND(s, p, Xl, Xr, 2);
BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6); BLFRND(s, p, Xr, Xl, 3);
BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8); BLFRND(s, p, Xl, Xr, 4);
BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10); BLFRND(s, p, Xr, Xl, 5);
BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12); BLFRND(s, p, Xl, Xr, 6);
BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14); BLFRND(s, p, Xr, Xl, 7);
BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16); BLFRND(s, p, Xl, Xr, 8);
BLFRND(s, p, Xr, Xl, 9);
BLFRND(s, p, Xl, Xr, 10);
BLFRND(s, p, Xr, Xl, 11);
BLFRND(s, p, Xl, Xr, 12);
BLFRND(s, p, Xr, Xl, 13);
BLFRND(s, p, Xl, Xr, 14);
BLFRND(s, p, Xr, Xl, 15);
BLFRND(s, p, Xl, Xr, 16);
x[0] = Xr ^ p[17]; x[0] = Xr ^ p[17];
x[1] = Xl; x[1] = Xl;
} }
void void
Blowfish_decipher(blf_ctx *c, uint32 *x) Blowfish_decipher(blf_ctx * c, uint32 *x)
{ {
uint32 Xl; uint32 Xl;
uint32 Xr; uint32 Xr;
uint32 *s = c->S[0]; uint32 *s = c->S[0];
uint32 *p = c->P; uint32 *p = c->P;
Xl = x[0]; Xl = x[0];
Xr = x[1]; Xr = x[1];
Xl ^= p[17]; Xl ^= p[17];
BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15); BLFRND(s, p, Xr, Xl, 16);
BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13); BLFRND(s, p, Xl, Xr, 15);
BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11); BLFRND(s, p, Xr, Xl, 14);
BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9); BLFRND(s, p, Xl, Xr, 13);
BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7); BLFRND(s, p, Xr, Xl, 12);
BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5); BLFRND(s, p, Xl, Xr, 11);
BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3); BLFRND(s, p, Xr, Xl, 10);
BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1); BLFRND(s, p, Xl, Xr, 9);
BLFRND(s, p, Xr, Xl, 8);
BLFRND(s, p, Xl, Xr, 7);
BLFRND(s, p, Xr, Xl, 6);
BLFRND(s, p, Xl, Xr, 5);
BLFRND(s, p, Xr, Xl, 4);
BLFRND(s, p, Xl, Xr, 3);
BLFRND(s, p, Xr, Xl, 2);
BLFRND(s, p, Xl, Xr, 1);
x[0] = Xr ^ p[0]; x[0] = Xr ^ p[0];
x[1] = Xl; x[1] = Xl;
} }
void void
Blowfish_initstate(blf_ctx *c) Blowfish_initstate(blf_ctx * c)
{ {
/* P-box and S-box tables initialized with digits of Pi */ /* P-box and S-box tables initialized with digits of Pi */
const blf_ctx initstate = const blf_ctx initstate =
{ { {{
{ {
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a}, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
{ {
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7}, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
{ {
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0}, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
{ {
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6} 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
}, },
{ {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
@ -385,7 +401,7 @@ Blowfish_initstate(blf_ctx *c)
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b 0x9216d5d9, 0x8979fb1b
} }; }};
*c = initstate; *c = initstate;
@ -394,14 +410,15 @@ Blowfish_initstate(blf_ctx *c)
uint32 uint32
Blowfish_stream2word(const uint8 *data, uint16 databytes, uint16 *current) Blowfish_stream2word(const uint8 *data, uint16 databytes, uint16 *current)
{ {
uint8 i; uint8 i;
uint16 j; uint16 j;
uint32 temp; uint32 temp;
temp = 0x00000000; temp = 0x00000000;
j = *current; j = *current;
for (i = 0; i < 4; i++, j++) { for (i = 0; i < 4; i++, j++)
{
if (j >= databytes) if (j >= databytes)
j = 0; j = 0;
temp = (temp << 8) | data[j]; temp = (temp << 8) | data[j];
@ -412,16 +429,17 @@ Blowfish_stream2word(const uint8 *data, uint16 databytes, uint16 *current)
} }
void void
Blowfish_expand0state(blf_ctx *c, const uint8 *key, uint16 keybytes) Blowfish_expand0state(blf_ctx * c, const uint8 *key, uint16 keybytes)
{ {
uint16 i; uint16 i;
uint16 j; uint16 j;
uint16 k; uint16 k;
uint32 temp; uint32 temp;
uint32 data[2]; uint32 data[2];
j = 0; j = 0;
for (i = 0; i < BLF_N + 2; i++) { for (i = 0; i < BLF_N + 2; i++)
{
/* Extract 4 int8 to 1 int32 from keystream */ /* Extract 4 int8 to 1 int32 from keystream */
temp = Blowfish_stream2word(key, keybytes, &j); temp = Blowfish_stream2word(key, keybytes, &j);
c->P[i] = c->P[i] ^ temp; c->P[i] = c->P[i] ^ temp;
@ -430,15 +448,18 @@ Blowfish_expand0state(blf_ctx *c, const uint8 *key, uint16 keybytes)
j = 0; j = 0;
data[0] = 0x00000000; data[0] = 0x00000000;
data[1] = 0x00000000; data[1] = 0x00000000;
for (i = 0; i < BLF_N + 2; i += 2) { for (i = 0; i < BLF_N + 2; i += 2)
{
Blowfish_encipher(c, data); Blowfish_encipher(c, data);
c->P[i] = data[0]; c->P[i] = data[0];
c->P[i + 1] = data[1]; c->P[i + 1] = data[1];
} }
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++)
for (k = 0; k < 256; k += 2) { {
for (k = 0; k < 256; k += 2)
{
Blowfish_encipher(c, data); Blowfish_encipher(c, data);
c->S[i][k] = data[0]; c->S[i][k] = data[0];
@ -449,17 +470,18 @@ Blowfish_expand0state(blf_ctx *c, const uint8 *key, uint16 keybytes)
void void
Blowfish_expandstate(blf_ctx *c, const uint8 *data, uint16 databytes, Blowfish_expandstate(blf_ctx * c, const uint8 *data, uint16 databytes,
const uint8 *key, uint16 keybytes) const uint8 *key, uint16 keybytes)
{ {
uint16 i; uint16 i;
uint16 j; uint16 j;
uint16 k; uint16 k;
uint32 temp; uint32 temp;
uint32 d[2]; uint32 d[2];
j = 0; j = 0;
for (i = 0; i < BLF_N + 2; i++) { for (i = 0; i < BLF_N + 2; i++)
{
/* Extract 4 int8 to 1 int32 from keystream */ /* Extract 4 int8 to 1 int32 from keystream */
temp = Blowfish_stream2word(key, keybytes, &j); temp = Blowfish_stream2word(key, keybytes, &j);
c->P[i] = c->P[i] ^ temp; c->P[i] = c->P[i] ^ temp;
@ -468,7 +490,8 @@ Blowfish_expandstate(blf_ctx *c, const uint8 *data, uint16 databytes,
j = 0; j = 0;
d[0] = 0x00000000; d[0] = 0x00000000;
d[1] = 0x00000000; d[1] = 0x00000000;
for (i = 0; i < BLF_N + 2; i += 2) { for (i = 0; i < BLF_N + 2; i += 2)
{
d[0] ^= Blowfish_stream2word(data, databytes, &j); d[0] ^= Blowfish_stream2word(data, databytes, &j);
d[1] ^= Blowfish_stream2word(data, databytes, &j); d[1] ^= Blowfish_stream2word(data, databytes, &j);
Blowfish_encipher(c, d); Blowfish_encipher(c, d);
@ -477,9 +500,11 @@ Blowfish_expandstate(blf_ctx *c, const uint8 *data, uint16 databytes,
c->P[i + 1] = d[1]; c->P[i + 1] = d[1];
} }
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++)
for (k = 0; k < 256; k += 2) { {
d[0]^= Blowfish_stream2word(data, databytes, &j); for (k = 0; k < 256; k += 2)
{
d[0] ^= Blowfish_stream2word(data, databytes, &j);
d[1] ^= Blowfish_stream2word(data, databytes, &j); d[1] ^= Blowfish_stream2word(data, databytes, &j);
Blowfish_encipher(c, d); Blowfish_encipher(c, d);
@ -491,7 +516,7 @@ Blowfish_expandstate(blf_ctx *c, const uint8 *data, uint16 databytes,
} }
void void
blf_key(blf_ctx *c, const uint8 *k, uint16 len) blf_key(blf_ctx * c, const uint8 *k, uint16 len)
{ {
/* Initalize S-boxes and subkeys with Pi */ /* Initalize S-boxes and subkeys with Pi */
Blowfish_initstate(c); Blowfish_initstate(c);
@ -501,38 +526,43 @@ blf_key(blf_ctx *c, const uint8 *k, uint16 len)
} }
void void
blf_enc(blf_ctx *c, uint32 *data, uint16 blocks) blf_enc(blf_ctx * c, uint32 *data, uint16 blocks)
{ {
uint32 *d; uint32 *d;
uint16 i; uint16 i;
d = data; d = data;
for (i = 0; i < blocks; i++) { for (i = 0; i < blocks; i++)
{
Blowfish_encipher(c, d); Blowfish_encipher(c, d);
d += 2; d += 2;
} }
} }
void void
blf_dec(blf_ctx *c, uint32 *data, uint16 blocks) blf_dec(blf_ctx * c, uint32 *data, uint16 blocks)
{ {
uint32 *d; uint32 *d;
uint16 i; uint16 i;
d = data; d = data;
for (i = 0; i < blocks; i++) { for (i = 0; i < blocks; i++)
{
Blowfish_decipher(c, d); Blowfish_decipher(c, d);
d += 2; d += 2;
} }
} }
void void
blf_ecb_encrypt(blf_ctx *c, uint8 *data, uint32 len) blf_ecb_encrypt(blf_ctx * c, uint8 *data, uint32 len)
{ {
uint32 l, r, d[2]; uint32 l,
uint32 i; r,
d[2];
uint32 i;
for (i = 0; i < len; i += 8) { for (i = 0; i < len; i += 8)
{
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
d[0] = l; d[0] = l;
@ -553,12 +583,15 @@ blf_ecb_encrypt(blf_ctx *c, uint8 *data, uint32 len)
} }
void void
blf_ecb_decrypt(blf_ctx *c, uint8 *data, uint32 len) blf_ecb_decrypt(blf_ctx * c, uint8 *data, uint32 len)
{ {
uint32 l, r, d[2]; uint32 l,
uint32 i; r,
d[2];
uint32 i;
for (i = 0; i < len; i += 8) { for (i = 0; i < len; i += 8)
{
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
d[0] = l; d[0] = l;
@ -579,12 +612,16 @@ blf_ecb_decrypt(blf_ctx *c, uint8 *data, uint32 len)
} }
void void
blf_cbc_encrypt(blf_ctx *c, uint8 *iv, uint8 *data, uint32 len) blf_cbc_encrypt(blf_ctx * c, uint8 *iv, uint8 *data, uint32 len)
{ {
uint32 l, r, d[2]; uint32 l,
uint32 i, j; r,
d[2];
uint32 i,
j;
for (i = 0; i < len; i += 8) { for (i = 0; i < len; i += 8)
{
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
data[j] ^= iv[j]; data[j] ^= iv[j];
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
@ -608,15 +645,19 @@ blf_cbc_encrypt(blf_ctx *c, uint8 *iv, uint8 *data, uint32 len)
} }
void void
blf_cbc_decrypt(blf_ctx *c, uint8 *iva, uint8 *data, uint32 len) blf_cbc_decrypt(blf_ctx * c, uint8 *iva, uint8 *data, uint32 len)
{ {
uint32 l, r, d[2]; uint32 l,
uint8 *iv; r,
uint32 i, j; d[2];
uint8 *iv;
uint32 i,
j;
iv = data + len - 16; iv = data + len - 16;
data = data + len - 8; data = data + len - 8;
for (i = len - 8; i >= 8; i -= 8) { for (i = len - 8; i >= 8; i -= 8)
{
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
d[0] = l; d[0] = l;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: blf.h,v 1.3 2001/05/15 02:40:35 deraadt Exp $ */ /* $OpenBSD: blf.h,v 1.3 2001/05/15 02:40:35 deraadt Exp $ */
/* /*
* Blowfish - a fast block cipher designed by Bruce Schneier * Blowfish - a fast block cipher designed by Bruce Schneier
@ -10,15 +10,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by Niels Provos. * This product includes software developed by Niels Provos.
* 4. The name of the author may not be used to endorse or promote products * 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -42,14 +42,15 @@
* of the key affect all cipherbits. * of the key affect all cipherbits.
*/ */
#define BLF_N 16 /* Number of Subkeys */ #define BLF_N 16 /* Number of Subkeys */
#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ #define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */
/* Blowfish context */ /* Blowfish context */
typedef struct BlowfishContext { typedef struct BlowfishContext
uint32 S[4][256]; /* S-Boxes */ {
uint32 P[BLF_N + 2]; /* Subkeys */ uint32 S[4][256]; /* S-Boxes */
} blf_ctx; uint32 P[BLF_N + 2]; /* Subkeys */
} blf_ctx;
/* Raw access to customized Blowfish /* Raw access to customized Blowfish
* blf_key is just: * blf_key is just:
@ -57,26 +58,25 @@ typedef struct BlowfishContext {
* Blowfish_expand0state( state, key, keylen ) * Blowfish_expand0state( state, key, keylen )
*/ */
void Blowfish_encipher (blf_ctx *, uint32 *); void Blowfish_encipher(blf_ctx *, uint32 *);
void Blowfish_decipher (blf_ctx *, uint32 *); void Blowfish_decipher(blf_ctx *, uint32 *);
void Blowfish_initstate (blf_ctx *); void Blowfish_initstate(blf_ctx *);
void Blowfish_expand0state (blf_ctx *, const uint8 *, uint16); void Blowfish_expand0state(blf_ctx *, const uint8 *, uint16);
void Blowfish_expandstate void Blowfish_expandstate
(blf_ctx *, const uint8 *, uint16, const uint8 *, uint16); (blf_ctx *, const uint8 *, uint16, const uint8 *, uint16);
/* Standard Blowfish */ /* Standard Blowfish */
void blf_key (blf_ctx *, const uint8 *, uint16); void blf_key(blf_ctx *, const uint8 *, uint16);
void blf_enc (blf_ctx *, uint32 *, uint16); void blf_enc(blf_ctx *, uint32 *, uint16);
void blf_dec (blf_ctx *, uint32 *, uint16); void blf_dec(blf_ctx *, uint32 *, uint16);
/* Converts uint8 to uint32 */ /* Converts uint8 to uint32 */
uint32 Blowfish_stream2word (const uint8 *, uint16, uint16 *); uint32 Blowfish_stream2word(const uint8 *, uint16, uint16 *);
void blf_ecb_encrypt (blf_ctx *, uint8 *, uint32); void blf_ecb_encrypt(blf_ctx *, uint8 *, uint32);
void blf_ecb_decrypt (blf_ctx *, uint8 *, uint32); void blf_ecb_decrypt(blf_ctx *, uint8 *, uint32);
void blf_cbc_encrypt (blf_ctx *, uint8 *, uint8 *, uint32);
void blf_cbc_decrypt (blf_ctx *, uint8 *, uint8 *, uint32);
void blf_cbc_encrypt(blf_ctx *, uint8 *, uint8 *, uint32);
void blf_cbc_decrypt(blf_ctx *, uint8 *, uint8 *, uint32);
#endif #endif

View File

@ -57,10 +57,11 @@ typedef unsigned int BF_word;
typedef BF_word BF_key[BF_N + 2]; typedef BF_word BF_key[BF_N + 2];
typedef struct { typedef struct
BF_word S[4][0x100]; {
BF_key P; BF_word S[4][0x100];
} BF_ctx; BF_key P;
} BF_ctx;
/* /*
* Magic IV for 64 Blowfish encryptions that we do at the end. * Magic IV for 64 Blowfish encryptions that we do at the end.
@ -347,7 +348,7 @@ static BF_ctx BF_init_state = {
}; };
static unsigned char BF_itoa64[64 + 1] = static unsigned char BF_itoa64[64 + 1] =
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
static unsigned char BF_atoi64[0x60] = { static unsigned char BF_atoi64[0x60] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
@ -367,22 +368,30 @@ do { \
(dst) = tmp; \ (dst) = tmp; \
} while (0) } while (0)
static int BF_decode(BF_word *dst, const char *src, int size) static int
BF_decode(BF_word * dst, const char *src, int size)
{ {
unsigned char *dptr = (unsigned char *)dst; unsigned char *dptr = (unsigned char *) dst;
unsigned char *end = dptr + size; unsigned char *end = dptr + size;
unsigned char *sptr = (unsigned char *)src; unsigned char *sptr = (unsigned char *) src;
unsigned int tmp, c1, c2, c3, c4; unsigned int tmp,
c1,
c2,
c3,
c4;
do { do
{
BF_safe_atoi64(c1, *sptr++); BF_safe_atoi64(c1, *sptr++);
BF_safe_atoi64(c2, *sptr++); BF_safe_atoi64(c2, *sptr++);
*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
if (dptr >= end) break; if (dptr >= end)
break;
BF_safe_atoi64(c3, *sptr++); BF_safe_atoi64(c3, *sptr++);
*dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2); *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
if (dptr >= end) break; if (dptr >= end)
break;
BF_safe_atoi64(c4, *sptr++); BF_safe_atoi64(c4, *sptr++);
*dptr++ = ((c3 & 0x03) << 6) | c4; *dptr++ = ((c3 & 0x03) << 6) | c4;
@ -391,18 +400,22 @@ static int BF_decode(BF_word *dst, const char *src, int size)
return 0; return 0;
} }
static void BF_encode(char *dst, const BF_word *src, int size) static void
BF_encode(char *dst, const BF_word * src, int size)
{ {
unsigned char *sptr = (unsigned char *)src; unsigned char *sptr = (unsigned char *) src;
unsigned char *end = sptr + size; unsigned char *end = sptr + size;
unsigned char *dptr = (unsigned char *)dst; unsigned char *dptr = (unsigned char *) dst;
unsigned int c1, c2; unsigned int c1,
c2;
do { do
{
c1 = *sptr++; c1 = *sptr++;
*dptr++ = BF_itoa64[c1 >> 2]; *dptr++ = BF_itoa64[c1 >> 2];
c1 = (c1 & 0x03) << 4; c1 = (c1 & 0x03) << 4;
if (sptr >= end) { if (sptr >= end)
{
*dptr++ = BF_itoa64[c1]; *dptr++ = BF_itoa64[c1];
break; break;
} }
@ -411,7 +424,8 @@ static void BF_encode(char *dst, const BF_word *src, int size)
c1 |= c2 >> 4; c1 |= c2 >> 4;
*dptr++ = BF_itoa64[c1]; *dptr++ = BF_itoa64[c1];
c1 = (c2 & 0x0f) << 2; c1 = (c2 & 0x0f) << 2;
if (sptr >= end) { if (sptr >= end)
{
*dptr++ = BF_itoa64[c1]; *dptr++ = BF_itoa64[c1];
break; break;
} }
@ -423,18 +437,20 @@ static void BF_encode(char *dst, const BF_word *src, int size)
} while (sptr < end); } while (sptr < end);
} }
static void BF_swap(BF_word *x, int count) static void
BF_swap(BF_word * x, int count)
{ {
static int endianness_check = 1; static int endianness_check = 1;
char *is_little_endian = (char *)&endianness_check; char *is_little_endian = (char *) &endianness_check;
BF_word tmp; BF_word tmp;
if (*is_little_endian) if (*is_little_endian)
do { do
tmp = *x; {
tmp = (tmp << 16) | (tmp >> 16); tmp = *x;
*x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); tmp = (tmp << 16) | (tmp >> 16);
} while (--count); *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
} while (--count);
} }
#if BF_SCALE #if BF_SCALE
@ -504,7 +520,8 @@ static void BF_swap(BF_word *x, int count)
#if BF_ASM #if BF_ASM
extern void _BF_body_r(BF_ctx *ctx); extern void _BF_body_r(BF_ctx * ctx);
#define BF_body() \ #define BF_body() \
_BF_body_r(&data.ctx); _BF_body_r(&data.ctx);
@ -527,22 +544,28 @@ extern void _BF_body_r(BF_ctx *ctx);
*(ptr - 2) = L; \ *(ptr - 2) = L; \
*(ptr - 1) = R; \ *(ptr - 1) = R; \
} while (ptr < &data.ctx.S[3][0xFF]); } while (ptr < &data.ctx.S[3][0xFF]);
#endif #endif
static void BF_set_key(const char *key, BF_key expanded, BF_key initial) static void
BF_set_key(const char *key, BF_key expanded, BF_key initial)
{ {
const char *ptr = key; const char *ptr = key;
int i, j; int i,
BF_word tmp; j;
BF_word tmp;
for (i = 0; i < BF_N + 2; i++) { for (i = 0; i < BF_N + 2; i++)
{
tmp = 0; tmp = 0;
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++)
{
tmp <<= 8; tmp <<= 8;
tmp |= *ptr; tmp |= *ptr;
if (!*ptr) ptr = key; else ptr++; if (!*ptr)
ptr = key;
else
ptr++;
} }
expanded[i] = tmp; expanded[i] = tmp;
@ -550,41 +573,51 @@ static void BF_set_key(const char *key, BF_key expanded, BF_key initial)
} }
} }
char *_crypt_blowfish_rn(const char *key, const char *setting, char *
char *output, int size) _crypt_blowfish_rn(const char *key, const char *setting,
char *output, int size)
{ {
struct { struct
BF_ctx ctx; {
BF_key expanded_key; BF_ctx ctx;
union { BF_key expanded_key;
BF_word salt[4]; union
BF_word output[6]; {
} binary; BF_word salt[4];
} data; BF_word output[6];
BF_word L, R; } binary;
BF_word tmp1, tmp2, tmp3, tmp4; } data;
BF_word *ptr; BF_word L,
BF_word count; R;
int i; BF_word tmp1,
tmp2,
tmp3,
tmp4;
BF_word *ptr;
BF_word count;
int i;
if (size < 7 + 22 + 31 + 1) { if (size < 7 + 22 + 31 + 1)
{
__set_errno(ERANGE); __set_errno(ERANGE);
return NULL; return NULL;
} }
if (setting[0] != '$' || if (setting[0] != '$' ||
setting[1] != '2' || setting[1] != '2' ||
setting[2] != 'a' || setting[2] != 'a' ||
setting[3] != '$' || setting[3] != '$' ||
setting[4] < '0' || setting[4] > '3' || setting[4] < '0' || setting[4] > '3' ||
setting[5] < '0' || setting[5] > '9' || setting[5] < '0' || setting[5] > '9' ||
setting[6] != '$') { setting[6] != '$')
{
__set_errno(EINVAL); __set_errno(EINVAL);
return NULL; return NULL;
} }
count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0')); count = (BF_word) 1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16)) { if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16))
{
memset(data.binary.salt, 0, sizeof(data.binary.salt)); memset(data.binary.salt, 0, sizeof(data.binary.salt));
__set_errno(EINVAL); __set_errno(EINVAL);
return NULL; return NULL;
@ -596,7 +629,8 @@ char *_crypt_blowfish_rn(const char *key, const char *setting,
memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S)); memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
L = R = 0; L = R = 0;
for (i = 0; i < BF_N + 2; i += 2) { for (i = 0; i < BF_N + 2; i += 2)
{
L ^= data.binary.salt[i & 2]; L ^= data.binary.salt[i & 2];
R ^= data.binary.salt[(i & 2) + 1]; R ^= data.binary.salt[(i & 2) + 1];
BF_ENCRYPT; BF_ENCRYPT;
@ -605,7 +639,8 @@ char *_crypt_blowfish_rn(const char *key, const char *setting,
} }
ptr = data.ctx.S[0]; ptr = data.ctx.S[0];
do { do
{
ptr += 4; ptr += 4;
L ^= data.binary.salt[(BF_N + 2) & 3]; L ^= data.binary.salt[(BF_N + 2) & 3];
R ^= data.binary.salt[(BF_N + 3) & 3]; R ^= data.binary.salt[(BF_N + 3) & 3];
@ -620,7 +655,8 @@ char *_crypt_blowfish_rn(const char *key, const char *setting,
*(ptr - 1) = R; *(ptr - 1) = R;
} while (ptr < &data.ctx.S[3][0xFF]); } while (ptr < &data.ctx.S[3][0xFF]);
do { do
{
data.ctx.P[0] ^= data.expanded_key[0]; data.ctx.P[0] ^= data.expanded_key[0];
data.ctx.P[1] ^= data.expanded_key[1]; data.ctx.P[1] ^= data.expanded_key[1];
data.ctx.P[2] ^= data.expanded_key[2]; data.ctx.P[2] ^= data.expanded_key[2];
@ -668,12 +704,14 @@ char *_crypt_blowfish_rn(const char *key, const char *setting,
BF_body(); BF_body();
} while (--count); } while (--count);
for (i = 0; i < 6; i += 2) { for (i = 0; i < 6; i += 2)
{
L = BF_magic_w[i]; L = BF_magic_w[i];
R = BF_magic_w[i + 1]; R = BF_magic_w[i + 1];
count = 64; count = 64;
do { do
{
BF_ENCRYPT; BF_ENCRYPT;
} while (--count); } while (--count);
@ -683,7 +721,7 @@ char *_crypt_blowfish_rn(const char *key, const char *setting,
memcpy(output, setting, 7 + 22 - 1); memcpy(output, setting, 7 + 22 - 1);
output[7 + 22 - 1] = BF_itoa64[(int) output[7 + 22 - 1] = BF_itoa64[(int)
BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30]; BF_atoi64[(int) setting[7 + 22 - 1] - 0x20] & 0x30];
/* This has to be bug-compatible with the original implementation, so /* This has to be bug-compatible with the original implementation, so
* only encode 23 of the 24 bytes. :-) */ * only encode 23 of the 24 bytes. :-) */
@ -698,4 +736,3 @@ char *_crypt_blowfish_rn(const char *key, const char *setting,
return output; return output;
} }

View File

@ -244,8 +244,8 @@ des_init()
} }
/* /*
* Convert the inverted S-boxes into 4 arrays of 8 bits. * Convert the inverted S-boxes into 4 arrays of 8 bits. Each will
* Each will handle 12 bits of the S-box input. * handle 12 bits of the S-box input.
*/ */
for (b = 0; b < 4; b++) for (b = 0; b < 4; b++)
for (i = 0; i < 64; i++) for (i = 0; i < 64; i++)
@ -409,10 +409,9 @@ des_setkey(const char *key)
&& rawkey1 == old_rawkey1) && rawkey1 == old_rawkey1)
{ {
/* /*
* Already setup for this key. * Already setup for this key. This optimisation fails on a zero
* This optimisation fails on a zero key (which is weak and * key (which is weak and has bad parity anyway) in order to
* has bad parity anyway) in order to simplify the starting * simplify the starting conditions.
* conditions.
*/ */
return (0); return (0);
} }
@ -420,7 +419,7 @@ des_setkey(const char *key)
old_rawkey1 = rawkey1; old_rawkey1 = rawkey1;
/* /*
* Do key permutation and split into two 28-bit subkeys. * Do key permutation and split into two 28-bit subkeys.
*/ */
k0 = key_perm_maskl[0][rawkey0 >> 25] k0 = key_perm_maskl[0][rawkey0 >> 25]
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
@ -438,8 +437,9 @@ des_setkey(const char *key)
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
/* /*
* Rotate subkeys and do compression permutation. * Rotate subkeys and do compression permutation.
*/ */
shifts = 0; shifts = 0;
for (round = 0; round < 16; round++) for (round = 0; round < 16; round++)
@ -476,10 +476,10 @@ des_setkey(const char *key)
} }
static int static int
do_des(uint32 l_in, uint32 r_in, uint32 * l_out, uint32 * r_out, int count) do_des(uint32 l_in, uint32 r_in, uint32 *l_out, uint32 *r_out, int count)
{ {
/* /*
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
*/ */
uint32 l, uint32 l,
r, r,
@ -513,7 +513,7 @@ do_des(uint32 l_in, uint32 r_in, uint32 * l_out, uint32 * r_out, int count)
} }
/* /*
* Do initial permutation (IP). * Do initial permutation (IP).
*/ */
l = ip_maskl[0][l_in >> 24] l = ip_maskl[0][l_in >> 24]
| ip_maskl[1][(l_in >> 16) & 0xff] | ip_maskl[1][(l_in >> 16) & 0xff]
@ -556,21 +556,24 @@ do_des(uint32 l_in, uint32 r_in, uint32 * l_out, uint32 * r_out, int count)
| ((r & 0x000001f8) << 3) | ((r & 0x000001f8) << 3)
| ((r & 0x0000001f) << 1) | ((r & 0x0000001f) << 1)
| ((r & 0x80000000) >> 31); | ((r & 0x80000000) >> 31);
/* /*
* Do salting for crypt() and friends, and * Do salting for crypt() and friends, and XOR with the
* XOR with the permuted key. * permuted key.
*/ */
f = (r48l ^ r48r) & saltbits; f = (r48l ^ r48r) & saltbits;
r48l ^= f ^ *kl++; r48l ^= f ^ *kl++;
r48r ^= f ^ *kr++; r48r ^= f ^ *kr++;
/* /*
* Do sbox lookups (which shrink it back to 32 bits) * Do sbox lookups (which shrink it back to 32 bits) and do
* and do the pbox permutation at the same time. * the pbox permutation at the same time.
*/ */
f = psbox[0][m_sbox[0][r48l >> 12]] f = psbox[0][m_sbox[0][r48l >> 12]]
| psbox[1][m_sbox[1][r48l & 0xfff]] | psbox[1][m_sbox[1][r48l & 0xfff]]
| psbox[2][m_sbox[2][r48r >> 12]] | psbox[2][m_sbox[2][r48r >> 12]]
| psbox[3][m_sbox[3][r48r & 0xfff]]; | psbox[3][m_sbox[3][r48r & 0xfff]];
/* /*
* Now that we've permuted things, complete f(). * Now that we've permuted things, complete f().
*/ */
@ -581,6 +584,7 @@ do_des(uint32 l_in, uint32 r_in, uint32 * l_out, uint32 * r_out, int count)
r = l; r = l;
l = f; l = f;
} }
/* /*
* Do final permutation (inverse of IP). * Do final permutation (inverse of IP).
*/ */
@ -654,8 +658,8 @@ px_crypt_des(const char *key, const char *setting)
/* /*
* Copy the key, shifting each character up by one bit * Copy the key, shifting each character up by one bit and padding
* and padding with zeros. * with zeros.
*/ */
q = (uint8 *) keybuf; q = (uint8 *) keybuf;
while (q - (uint8 *) keybuf - 8) while (q - (uint8 *) keybuf - 8)
@ -670,9 +674,8 @@ px_crypt_des(const char *key, const char *setting)
if (*setting == _PASSWORD_EFMT1) if (*setting == _PASSWORD_EFMT1)
{ {
/* /*
* "new"-style: * "new"-style: setting - underscore, 4 bytes of count, 4 bytes of
* setting - underscore, 4 bytes of count, 4 bytes of salt * salt key - unlimited characters
* key - unlimited characters
*/ */
for (i = 1, count = 0L; i < 5; i++) for (i = 1, count = 0L; i < 5; i++)
count |= ascii_to_bin(setting[i]) << (i - 1) * 6; count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
@ -687,6 +690,7 @@ px_crypt_des(const char *key, const char *setting)
*/ */
if (des_cipher((uint8 *) keybuf, (uint8 *) keybuf, 0L, 1)) if (des_cipher((uint8 *) keybuf, (uint8 *) keybuf, 0L, 1))
return (NULL); return (NULL);
/* /*
* And XOR with the next 8 characters of the key. * And XOR with the next 8 characters of the key.
*/ */
@ -700,11 +704,10 @@ px_crypt_des(const char *key, const char *setting)
strncpy(output, setting, 9); strncpy(output, setting, 9);
/* /*
* Double check that we weren't given a short setting. * Double check that we weren't given a short setting. If we were,
* If we were, the above code will probably have created * the above code will probably have created wierd values for
* wierd values for count and salt, but we don't really care. * count and salt, but we don't really care. Just make sure the
* Just make sure the output string doesn't have an extra * output string doesn't have an extra NUL in it.
* NUL in it.
*/ */
output[9] = '\0'; output[9] = '\0';
p = output + strlen(output); p = output + strlen(output);
@ -713,9 +716,7 @@ px_crypt_des(const char *key, const char *setting)
#endif /* !DISABLE_XDES */ #endif /* !DISABLE_XDES */
{ {
/* /*
* "old"-style: * "old"-style: setting - 2 bytes of salt key - up to 8 characters
* setting - 2 bytes of salt
* key - up to 8 characters
*/ */
count = 25; count = 25;
@ -723,22 +724,24 @@ px_crypt_des(const char *key, const char *setting)
| ascii_to_bin(setting[0]); | ascii_to_bin(setting[0]);
output[0] = setting[0]; output[0] = setting[0];
/* /*
* If the encrypted password that the salt was extracted from * If the encrypted password that the salt was extracted from is
* is only 1 character long, the salt will be corrupted. We * only 1 character long, the salt will be corrupted. We need to
* need to ensure that the output string doesn't have an extra * ensure that the output string doesn't have an extra NUL in it!
* NUL in it!
*/ */
output[1] = setting[1] ? setting[1] : output[0]; output[1] = setting[1] ? setting[1] : output[0];
p = output + 2; p = output + 2;
} }
setup_salt(salt); setup_salt(salt);
/* /*
* Do it. * Do it.
*/ */
if (do_des(0L, 0L, &r0, &r1, count)) if (do_des(0L, 0L, &r0, &r1, count))
return (NULL); return (NULL);
/* /*
* Now encode the result... * Now encode the result...
*/ */

View File

@ -7,7 +7,7 @@
* entirely in crypt_blowfish.c. * entirely in crypt_blowfish.c.
* *
* Put bcrypt generator also here as crypt-blowfish.c * Put bcrypt generator also here as crypt-blowfish.c
* may not be compiled always. -- marko * may not be compiled always. -- marko
*/ */
#include "postgres.h" #include "postgres.h"
@ -22,48 +22,55 @@
typedef unsigned int BF_word; typedef unsigned int BF_word;
unsigned char _crypt_itoa64[64 + 1] = unsigned char _crypt_itoa64[64 + 1] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *_crypt_gensalt_traditional_rn(unsigned long count, char *
const char *input, int size, char *output, int output_size) _crypt_gensalt_traditional_rn(unsigned long count,
const char *input, int size, char *output, int output_size)
{ {
if (size < 2 || output_size < 2 + 1 || (count && count != 25)) { if (size < 2 || output_size < 2 + 1 || (count && count != 25))
if (output_size > 0) output[0] = '\0'; {
if (output_size > 0)
output[0] = '\0';
__set_errno((output_size < 2 + 1) ? ERANGE : EINVAL); __set_errno((output_size < 2 + 1) ? ERANGE : EINVAL);
return NULL; return NULL;
} }
output[0] = _crypt_itoa64[(unsigned int)input[0] & 0x3f]; output[0] = _crypt_itoa64[(unsigned int) input[0] & 0x3f];
output[1] = _crypt_itoa64[(unsigned int)input[1] & 0x3f]; output[1] = _crypt_itoa64[(unsigned int) input[1] & 0x3f];
output[2] = '\0'; output[2] = '\0';
return output; return output;
} }
char *_crypt_gensalt_extended_rn(unsigned long count, char *
const char *input, int size, char *output, int output_size) _crypt_gensalt_extended_rn(unsigned long count,
const char *input, int size, char *output, int output_size)
{ {
unsigned long value; unsigned long value;
/* Even iteration counts make it easier to detect weak DES keys from a look /* Even iteration counts make it easier to detect weak DES keys from a look
* at the hash, so they should be avoided */ * at the hash, so they should be avoided */
if (size < 3 || output_size < 1 + 4 + 4 + 1 || if (size < 3 || output_size < 1 + 4 + 4 + 1 ||
(count && (count > 0xffffff || !(count & 1)))) { (count && (count > 0xffffff || !(count & 1))))
if (output_size > 0) output[0] = '\0'; {
if (output_size > 0)
output[0] = '\0';
__set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL); __set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL);
return NULL; return NULL;
} }
if (!count) count = 725; if (!count)
count = 725;
output[0] = '_'; output[0] = '_';
output[1] = _crypt_itoa64[count & 0x3f]; output[1] = _crypt_itoa64[count & 0x3f];
output[2] = _crypt_itoa64[(count >> 6) & 0x3f]; output[2] = _crypt_itoa64[(count >> 6) & 0x3f];
output[3] = _crypt_itoa64[(count >> 12) & 0x3f]; output[3] = _crypt_itoa64[(count >> 12) & 0x3f];
output[4] = _crypt_itoa64[(count >> 18) & 0x3f]; output[4] = _crypt_itoa64[(count >> 18) & 0x3f];
value = (unsigned long)input[0] | value = (unsigned long) input[0] |
((unsigned long)input[1] << 8) | ((unsigned long) input[1] << 8) |
((unsigned long)input[2] << 16); ((unsigned long) input[2] << 16);
output[5] = _crypt_itoa64[value & 0x3f]; output[5] = _crypt_itoa64[value & 0x3f];
output[6] = _crypt_itoa64[(value >> 6) & 0x3f]; output[6] = _crypt_itoa64[(value >> 6) & 0x3f];
output[7] = _crypt_itoa64[(value >> 12) & 0x3f]; output[7] = _crypt_itoa64[(value >> 12) & 0x3f];
@ -73,13 +80,16 @@ char *_crypt_gensalt_extended_rn(unsigned long count,
return output; return output;
} }
char *_crypt_gensalt_md5_rn(unsigned long count, char *
const char *input, int size, char *output, int output_size) _crypt_gensalt_md5_rn(unsigned long count,
const char *input, int size, char *output, int output_size)
{ {
unsigned long value; unsigned long value;
if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) { if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000))
if (output_size > 0) output[0] = '\0'; {
if (output_size > 0)
output[0] = '\0';
__set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL); __set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL);
return NULL; return NULL;
} }
@ -87,19 +97,20 @@ char *_crypt_gensalt_md5_rn(unsigned long count,
output[0] = '$'; output[0] = '$';
output[1] = '1'; output[1] = '1';
output[2] = '$'; output[2] = '$';
value = (unsigned long)input[0] | value = (unsigned long) input[0] |
((unsigned long)input[1] << 8) | ((unsigned long) input[1] << 8) |
((unsigned long)input[2] << 16); ((unsigned long) input[2] << 16);
output[3] = _crypt_itoa64[value & 0x3f]; output[3] = _crypt_itoa64[value & 0x3f];
output[4] = _crypt_itoa64[(value >> 6) & 0x3f]; output[4] = _crypt_itoa64[(value >> 6) & 0x3f];
output[5] = _crypt_itoa64[(value >> 12) & 0x3f]; output[5] = _crypt_itoa64[(value >> 12) & 0x3f];
output[6] = _crypt_itoa64[(value >> 18) & 0x3f]; output[6] = _crypt_itoa64[(value >> 18) & 0x3f];
output[7] = '\0'; output[7] = '\0';
if (size >= 6 && output_size >= 3 + 4 + 4 + 1) { if (size >= 6 && output_size >= 3 + 4 + 4 + 1)
value = (unsigned long)input[3] | {
((unsigned long)input[4] << 8) | value = (unsigned long) input[3] |
((unsigned long)input[5] << 16); ((unsigned long) input[4] << 8) |
((unsigned long) input[5] << 16);
output[7] = _crypt_itoa64[value & 0x3f]; output[7] = _crypt_itoa64[value & 0x3f];
output[8] = _crypt_itoa64[(value >> 6) & 0x3f]; output[8] = _crypt_itoa64[(value >> 6) & 0x3f];
output[9] = _crypt_itoa64[(value >> 12) & 0x3f]; output[9] = _crypt_itoa64[(value >> 12) & 0x3f];
@ -113,20 +124,24 @@ char *_crypt_gensalt_md5_rn(unsigned long count,
static unsigned char BF_itoa64[64 + 1] = static unsigned char BF_itoa64[64 + 1] =
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
static void BF_encode(char *dst, const BF_word *src, int size) static void
BF_encode(char *dst, const BF_word * src, int size)
{ {
unsigned char *sptr = (unsigned char *)src; unsigned char *sptr = (unsigned char *) src;
unsigned char *end = sptr + size; unsigned char *end = sptr + size;
unsigned char *dptr = (unsigned char *)dst; unsigned char *dptr = (unsigned char *) dst;
unsigned int c1, c2; unsigned int c1,
c2;
do { do
{
c1 = *sptr++; c1 = *sptr++;
*dptr++ = BF_itoa64[c1 >> 2]; *dptr++ = BF_itoa64[c1 >> 2];
c1 = (c1 & 0x03) << 4; c1 = (c1 & 0x03) << 4;
if (sptr >= end) { if (sptr >= end)
{
*dptr++ = BF_itoa64[c1]; *dptr++ = BF_itoa64[c1];
break; break;
} }
@ -135,7 +150,8 @@ static void BF_encode(char *dst, const BF_word *src, int size)
c1 |= c2 >> 4; c1 |= c2 >> 4;
*dptr++ = BF_itoa64[c1]; *dptr++ = BF_itoa64[c1];
c1 = (c2 & 0x0f) << 2; c1 = (c2 & 0x0f) << 2;
if (sptr >= end) { if (sptr >= end)
{
*dptr++ = BF_itoa64[c1]; *dptr++ = BF_itoa64[c1];
break; break;
} }
@ -147,17 +163,21 @@ static void BF_encode(char *dst, const BF_word *src, int size)
} while (sptr < end); } while (sptr < end);
} }
char *_crypt_gensalt_blowfish_rn(unsigned long count, char *
const char *input, int size, char *output, int output_size) _crypt_gensalt_blowfish_rn(unsigned long count,
const char *input, int size, char *output, int output_size)
{ {
if (size < 16 || output_size < 7 + 22 + 1 || if (size < 16 || output_size < 7 + 22 + 1 ||
(count && (count < 4 || count > 31))) { (count && (count < 4 || count > 31)))
if (output_size > 0) output[0] = '\0'; {
if (output_size > 0)
output[0] = '\0';
__set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL); __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
return NULL; return NULL;
} }
if (!count) count = 5; if (!count)
count = 5;
output[0] = '$'; output[0] = '$';
output[1] = '2'; output[1] = '2';
@ -167,9 +187,8 @@ char *_crypt_gensalt_blowfish_rn(unsigned long count,
output[5] = '0' + count % 10; output[5] = '0' + count % 10;
output[6] = '$'; output[6] = '$';
BF_encode(&output[7], (BF_word *)input, 16); BF_encode(&output[7], (BF_word *) input, 16);
output[7 + 22] = '\0'; output[7 + 22] = '\0';
return output; return output;
} }

View File

@ -9,7 +9,7 @@
* $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $ * $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $
* *
*/ */
/* $Id: crypt-md5.c,v 1.1 2001/08/21 01:32:01 momjian Exp $ */ /* $Id: crypt-md5.c,v 1.2 2001/10/25 05:49:19 momjian Exp $ */
#include <postgres.h> #include <postgres.h>
#include "px.h" #include "px.h"
@ -23,12 +23,9 @@
char * char *
px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen) px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen)
{ {
static char *magic = "$1$"; /* static char *magic = "$1$"; /* This string is magic for this
* This string is magic for * algorithm. Having it this way, we can
* this algorithm. Having * get get better later on */
* it this way, we can get
* get better later on
*/
static char *p; static char *p;
static const char *sp, static const char *sp,
*ep; *ep;
@ -43,7 +40,7 @@ px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen)
if (!passwd || dstlen < 120) if (!passwd || dstlen < 120)
return NULL; return NULL;
/* Refine the Salt first */ /* Refine the Salt first */
sp = salt; sp = salt;
@ -99,9 +96,9 @@ px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen)
px_md_finish(ctx, final); px_md_finish(ctx, final);
/* /*
* and now, just to make sure things don't run too fast * and now, just to make sure things don't run too fast On a 60 Mhz
* On a 60 Mhz Pentium this takes 34 msec, so you would * Pentium this takes 34 msec, so you would need 30 seconds to build a
* need 30 seconds to build a 1000 entry dictionary... * 1000 entry dictionary...
*/ */
for (i = 0; i < 1000; i++) for (i = 0; i < 1000; i++)
{ {

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: internal.c,v 1.5 2001/10/15 19:12:48 tgl Exp $ * $Id: internal.c,v 1.6 2001/10/25 05:49:19 momjian Exp $
*/ */
@ -61,11 +61,18 @@ static struct int_digest
{ {
char *name; char *name;
void (*init) (PX_MD * h); void (*init) (PX_MD * h);
} int_digest_list[] = } int_digest_list[] =
{ {
{ "md5", init_md5 }, {
{ "sha1", init_sha1 }, "md5", init_md5
{ NULL, NULL } },
{
"sha1", init_sha1
},
{
NULL, NULL
}
}; };
/* MD5 */ /* MD5 */
@ -83,7 +90,7 @@ int_md5_block_len(PX_MD * h)
} }
static void static void
int_md5_update(PX_MD * h, const uint8 * data, uint dlen) int_md5_update(PX_MD * h, const uint8 *data, uint dlen)
{ {
MD5_CTX *ctx = (MD5_CTX *) h->p.ptr; MD5_CTX *ctx = (MD5_CTX *) h->p.ptr;
@ -99,7 +106,7 @@ int_md5_reset(PX_MD * h)
} }
static void static void
int_md5_finish(PX_MD * h, uint8 * dst) int_md5_finish(PX_MD * h, uint8 *dst)
{ {
MD5_CTX *ctx = (MD5_CTX *) h->p.ptr; MD5_CTX *ctx = (MD5_CTX *) h->p.ptr;
@ -130,7 +137,7 @@ int_sha1_block_len(PX_MD * h)
} }
static void static void
int_sha1_update(PX_MD * h, const uint8 * data, uint dlen) int_sha1_update(PX_MD * h, const uint8 *data, uint dlen)
{ {
SHA1_CTX *ctx = (SHA1_CTX *) h->p.ptr; SHA1_CTX *ctx = (SHA1_CTX *) h->p.ptr;
@ -146,7 +153,7 @@ int_sha1_reset(PX_MD * h)
} }
static void static void
int_sha1_finish(PX_MD * h, uint8 * dst) int_sha1_finish(PX_MD * h, uint8 *dst)
{ {
SHA1_CTX *ctx = (SHA1_CTX *) h->p.ptr; SHA1_CTX *ctx = (SHA1_CTX *) h->p.ptr;
@ -209,22 +216,27 @@ init_sha1(PX_MD * md)
#define INT_MAX_KEY (512/8) #define INT_MAX_KEY (512/8)
#define INT_MAX_IV (128/8) #define INT_MAX_IV (128/8)
struct int_ctx { struct int_ctx
uint8 keybuf[INT_MAX_KEY]; {
uint8 iv[INT_MAX_IV]; uint8 keybuf[INT_MAX_KEY];
union { uint8 iv[INT_MAX_IV];
blf_ctx bf; union
{
blf_ctx bf;
rijndael_ctx rj; rijndael_ctx rj;
} ctx; } ctx;
uint keylen; uint keylen;
int is_init; int is_init;
int mode; int mode;
}; };
static void intctx_free(PX_Cipher *c) static void
intctx_free(PX_Cipher * c)
{ {
struct int_ctx *cx = (struct int_ctx *)c->ptr; struct int_ctx *cx = (struct int_ctx *) c->ptr;
if (cx) {
if (cx)
{
memset(cx, 0, sizeof *cx); memset(cx, 0, sizeof *cx);
px_free(cx); px_free(cx);
} }
@ -238,78 +250,88 @@ static void intctx_free(PX_Cipher *c)
#define MODE_ECB 0 #define MODE_ECB 0
#define MODE_CBC 1 #define MODE_CBC 1
static uint rj_block_size(PX_Cipher *c) static uint
rj_block_size(PX_Cipher * c)
{ {
return 128/8; return 128 / 8;
} }
static uint rj_key_size(PX_Cipher *c) static uint
rj_key_size(PX_Cipher * c)
{ {
return 256/8; return 256 / 8;
} }
static uint rj_iv_size(PX_Cipher *c) static uint
rj_iv_size(PX_Cipher * c)
{ {
return 128/8; return 128 / 8;
} }
static int rj_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv) static int
rj_init(PX_Cipher * c, const uint8 *key, uint klen, const uint8 *iv)
{ {
struct int_ctx *cx = (struct int_ctx *)c->ptr; struct int_ctx *cx = (struct int_ctx *) c->ptr;
if (klen <= 128/8) if (klen <= 128 / 8)
cx->keylen = 128/8; cx->keylen = 128 / 8;
else if (klen <= 192/8) else if (klen <= 192 / 8)
cx->keylen = 192/8; cx->keylen = 192 / 8;
else if (klen <= 256/8) else if (klen <= 256 / 8)
cx->keylen = 256/8; cx->keylen = 256 / 8;
else else
return -1; return -1;
memcpy(&cx->keybuf, key, klen); memcpy(&cx->keybuf, key, klen);
if (iv) if (iv)
memcpy(cx->iv, iv, 128/8); memcpy(cx->iv, iv, 128 / 8);
return 0; return 0;
} }
static int rj_real_init(struct int_ctx *cx, int dir) static int
rj_real_init(struct int_ctx * cx, int dir)
{ {
aes_set_key(&cx->ctx.rj, cx->keybuf, cx->keylen*8, dir); aes_set_key(&cx->ctx.rj, cx->keybuf, cx->keylen * 8, dir);
return 0; return 0;
} }
static int rj_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) static int
rj_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
struct int_ctx *cx = (struct int_ctx *)c->ptr; struct int_ctx *cx = (struct int_ctx *) c->ptr;
if (!cx->is_init) { if (!cx->is_init)
{
if (rj_real_init(cx, 1)) if (rj_real_init(cx, 1))
return -1; return -1;
} }
if (dlen == 0) if (dlen == 0)
return 0; return 0;
if ((dlen & 15) || (((unsigned)res) & 3)) if ((dlen & 15) || (((unsigned) res) & 3))
return -1; return -1;
memcpy(res, data, dlen); memcpy(res, data, dlen);
if (cx->mode == MODE_CBC) { if (cx->mode == MODE_CBC)
{
aes_cbc_encrypt(&cx->ctx.rj, cx->iv, res, dlen); aes_cbc_encrypt(&cx->ctx.rj, cx->iv, res, dlen);
memcpy(cx->iv, res + dlen - 16, 16); memcpy(cx->iv, res + dlen - 16, 16);
} else }
else
aes_ecb_encrypt(&cx->ctx.rj, res, dlen); aes_ecb_encrypt(&cx->ctx.rj, res, dlen);
return 0; return 0;
} }
static int rj_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) static int
rj_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
struct int_ctx *cx = (struct int_ctx *)c->ptr; struct int_ctx *cx = (struct int_ctx *) c->ptr;
if (!cx->is_init) if (!cx->is_init)
if (rj_real_init(cx, 0)) if (rj_real_init(cx, 0))
return -1; return -1;
@ -317,17 +339,19 @@ static int rj_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
if (dlen == 0) if (dlen == 0)
return 0; return 0;
if ((dlen & 15) || (((unsigned)res) & 3)) if ((dlen & 15) || (((unsigned) res) & 3))
return -1; return -1;
memcpy(res, data, dlen); memcpy(res, data, dlen);
if (cx->mode == MODE_CBC) { if (cx->mode == MODE_CBC)
{
aes_cbc_decrypt(&cx->ctx.rj, cx->iv, res, dlen); aes_cbc_decrypt(&cx->ctx.rj, cx->iv, res, dlen);
memcpy(cx->iv, data + dlen - 16, 16); memcpy(cx->iv, data + dlen - 16, 16);
} else }
else
aes_ecb_decrypt(&cx->ctx.rj, res, dlen); aes_ecb_decrypt(&cx->ctx.rj, res, dlen);
return 0; return 0;
} }
@ -335,11 +359,12 @@ static int rj_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
* initializers * initializers
*/ */
static PX_Cipher * rj_load(int mode) static PX_Cipher *
rj_load(int mode)
{ {
PX_Cipher *c; PX_Cipher *c;
struct int_ctx *cx; struct int_ctx *cx;
c = px_alloc(sizeof *c); c = px_alloc(sizeof *c);
memset(c, 0, sizeof *c); memset(c, 0, sizeof *c);
@ -363,24 +388,28 @@ static PX_Cipher * rj_load(int mode)
* blowfish * blowfish
*/ */
static uint bf_block_size(PX_Cipher *c) static uint
bf_block_size(PX_Cipher * c)
{ {
return 8; return 8;
} }
static uint bf_key_size(PX_Cipher *c) static uint
bf_key_size(PX_Cipher * c)
{ {
return BLF_MAXKEYLEN; return BLF_MAXKEYLEN;
} }
static uint bf_iv_size(PX_Cipher *c) static uint
bf_iv_size(PX_Cipher * c)
{ {
return 8; return 8;
} }
static int bf_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv) static int
bf_init(PX_Cipher * c, const uint8 *key, uint klen, const uint8 *iv)
{ {
struct int_ctx *cx = (struct int_ctx *)c->ptr; struct int_ctx *cx = (struct int_ctx *) c->ptr;
blf_key(&cx->ctx.bf, key, klen); blf_key(&cx->ctx.bf, key, klen);
if (iv) if (iv)
@ -389,55 +418,60 @@ static int bf_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv)
return 0; return 0;
} }
static int bf_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) static int
bf_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
struct int_ctx *cx = (struct int_ctx *)c->ptr; struct int_ctx *cx = (struct int_ctx *) c->ptr;
if (dlen == 0)
return 0;
if ((dlen & 7) || (((unsigned)res) & 3))
return -1;
memcpy(res, data, dlen);
switch (cx->mode) {
case MODE_ECB:
blf_ecb_encrypt(&cx->ctx.bf, res, dlen);
break;
case MODE_CBC:
blf_cbc_encrypt(&cx->ctx.bf, cx->iv, res, dlen);
memcpy(cx->iv, res + dlen - 8, 8);
}
return 0;
}
static int bf_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
{
struct int_ctx *cx = (struct int_ctx *)c->ptr;
if (dlen == 0) if (dlen == 0)
return 0; return 0;
if ((dlen & 7) || (((unsigned)res) & 3)) if ((dlen & 7) || (((unsigned) res) & 3))
return -1; return -1;
memcpy(res, data, dlen); memcpy(res, data, dlen);
switch (cx->mode) { switch (cx->mode)
case MODE_ECB: {
blf_ecb_decrypt(&cx->ctx.bf, res, dlen); case MODE_ECB:
break; blf_ecb_encrypt(&cx->ctx.bf, res, dlen);
case MODE_CBC: break;
blf_cbc_decrypt(&cx->ctx.bf, cx->iv, res, dlen); case MODE_CBC:
memcpy(cx->iv, data + dlen - 8, 8); blf_cbc_encrypt(&cx->ctx.bf, cx->iv, res, dlen);
memcpy(cx->iv, res + dlen - 8, 8);
} }
return 0; return 0;
} }
static PX_Cipher * bf_load(int mode) static int
bf_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
PX_Cipher *c; struct int_ctx *cx = (struct int_ctx *) c->ptr;
if (dlen == 0)
return 0;
if ((dlen & 7) || (((unsigned) res) & 3))
return -1;
memcpy(res, data, dlen);
switch (cx->mode)
{
case MODE_ECB:
blf_ecb_decrypt(&cx->ctx.bf, res, dlen);
break;
case MODE_CBC:
blf_cbc_decrypt(&cx->ctx.bf, cx->iv, res, dlen);
memcpy(cx->iv, data + dlen - 8, 8);
}
return 0;
}
static PX_Cipher *
bf_load(int mode)
{
PX_Cipher *c;
struct int_ctx *cx; struct int_ctx *cx;
c = px_alloc(sizeof *c); c = px_alloc(sizeof *c);
memset(c, 0, sizeof *c); memset(c, 0, sizeof *c);
@ -458,47 +492,64 @@ static PX_Cipher * bf_load(int mode)
/* ciphers */ /* ciphers */
static PX_Cipher * rj_128_ecb() static PX_Cipher *
rj_128_ecb()
{ {
return rj_load(MODE_ECB); return rj_load(MODE_ECB);
} }
static PX_Cipher * rj_128_cbc() static PX_Cipher *
rj_128_cbc()
{ {
return rj_load(MODE_CBC); return rj_load(MODE_CBC);
} }
static PX_Cipher * bf_ecb_load() static PX_Cipher *
bf_ecb_load()
{ {
return bf_load(MODE_ECB); return bf_load(MODE_ECB);
} }
static PX_Cipher * bf_cbc_load() static PX_Cipher *
bf_cbc_load()
{ {
return bf_load(MODE_CBC); return bf_load(MODE_CBC);
} }
static struct { static struct
char *name; {
PX_Cipher *(*load)(void); char *name;
} int_ciphers [] = { PX_Cipher *(*load) (void);
{ "bf-cbc", bf_cbc_load }, } int_ciphers[] =
{ "bf-ecb", bf_ecb_load },
{ "aes-128-cbc", rj_128_cbc }, {
{ "aes-128-ecb", rj_128_ecb }, {
{ NULL, NULL } "bf-cbc", bf_cbc_load
},
{
"bf-ecb", bf_ecb_load
},
{
"aes-128-cbc", rj_128_cbc
},
{
"aes-128-ecb", rj_128_ecb
},
{
NULL, NULL
}
}; };
static PX_Alias int_aliases [] = { static PX_Alias int_aliases[] = {
{ "bf", "bf-cbc" }, {"bf", "bf-cbc"},
{ "blowfish", "bf-cbc" }, {"blowfish", "bf-cbc"},
{ "aes", "aes-128-cbc" }, {"aes", "aes-128-cbc"},
{ "aes-ecb", "aes-128-ecb" }, {"aes-ecb", "aes-128-ecb"},
{ "aes-cbc", "aes-128-cbc" }, {"aes-cbc", "aes-128-cbc"},
{ "aes-128", "aes-128-cbc" }, {"aes-128", "aes-128-cbc"},
{ "rijndael", "aes-128-cbc" }, {"rijndael", "aes-128-cbc"},
{ "rijndael-128", "aes-128-cbc" }, {"rijndael-128", "aes-128-cbc"},
{ NULL, NULL } {NULL, NULL}
}; };
/* PUBLIC FUNCTIONS */ /* PUBLIC FUNCTIONS */
@ -523,15 +574,16 @@ px_find_digest(const char *name, PX_MD ** res)
} }
int int
px_find_cipher(const char *name, PX_Cipher **res) px_find_cipher(const char *name, PX_Cipher ** res)
{ {
int i; int i;
PX_Cipher *c = NULL; PX_Cipher *c = NULL;
name = px_resolve_alias(int_aliases, name); name = px_resolve_alias(int_aliases, name);
for (i = 0; int_ciphers[i].name; i++) for (i = 0; int_ciphers[i].name; i++)
if (!strcmp(int_ciphers[i].name, name)) { if (!strcmp(int_ciphers[i].name, name))
{
c = int_ciphers[i].load(); c = int_ciphers[i].load();
break; break;
} }
@ -542,5 +594,3 @@ px_find_cipher(const char *name, PX_Cipher **res)
*res = c; *res = c;
return 0; return 0;
} }

View File

@ -1,4 +1,4 @@
/* $Id: md5.c,v 1.7 2001/10/25 01:29:37 momjian Exp $ */ /* $Id: md5.c,v 1.8 2001/10/25 05:49:19 momjian Exp $ */
/* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */ /* $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $ */
/* /*
@ -132,7 +132,7 @@ static const uint8 md5_paddat[MD5_BUFLEN] = {
static void md5_calc(uint8 *, md5_ctxt *); static void md5_calc(uint8 *, md5_ctxt *);
void void
md5_init(md5_ctxt *ctxt) md5_init(md5_ctxt * ctxt)
{ {
ctxt->md5_n = 0; ctxt->md5_n = 0;
ctxt->md5_i = 0; ctxt->md5_i = 0;
@ -144,7 +144,7 @@ md5_init(md5_ctxt *ctxt)
} }
void void
md5_loop(md5_ctxt *ctxt, const uint8 *input, unsigned len) md5_loop(md5_ctxt * ctxt, const uint8 *input, unsigned len)
{ {
unsigned int gap, unsigned int gap,
i; i;
@ -173,7 +173,7 @@ md5_loop(md5_ctxt *ctxt, const uint8 *input, unsigned len)
} }
void void
md5_pad(md5_ctxt *ctxt) md5_pad(md5_ctxt * ctxt)
{ {
unsigned int gap; unsigned int gap;
@ -215,7 +215,7 @@ md5_pad(md5_ctxt *ctxt)
} }
void void
md5_result(uint8 *digest, md5_ctxt *ctxt) md5_result(uint8 *digest, md5_ctxt * ctxt)
{ {
/* 4 byte words */ /* 4 byte words */
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
@ -242,11 +242,11 @@ md5_result(uint8 *digest, md5_ctxt *ctxt)
} }
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
static uint32 X[16]; static uint32 X[16];
#endif #endif
static void static void
md5_calc(uint8 *b64, md5_ctxt *ctxt) md5_calc(uint8 *b64, md5_ctxt * ctxt)
{ {
uint32 A = ctxt->md5_sta; uint32 A = ctxt->md5_sta;
uint32 B = ctxt->md5_stb; uint32 B = ctxt->md5_stb;

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: mhash.c,v 1.4 2001/08/21 00:42:41 momjian Exp $ * $Id: mhash.c,v 1.5 2001/10/25 05:49:19 momjian Exp $
*/ */
#include <postgres.h> #include <postgres.h>
@ -75,7 +75,7 @@ digest_reset(PX_MD * h)
} }
static void static void
digest_update(PX_MD * h, const uint8 * data, uint dlen) digest_update(PX_MD * h, const uint8 *data, uint dlen)
{ {
MHASH mh = (MHASH) h->p.ptr; MHASH mh = (MHASH) h->p.ptr;
@ -83,7 +83,7 @@ digest_update(PX_MD * h, const uint8 * data, uint dlen)
} }
static void static void
digest_finish(PX_MD * h, uint8 * dst) digest_finish(PX_MD * h, uint8 *dst)
{ {
MHASH mh = (MHASH) h->p.ptr; MHASH mh = (MHASH) h->p.ptr;
uint hlen = digest_result_size(h); uint hlen = digest_result_size(h);
@ -111,34 +111,37 @@ digest_free(PX_MD * h)
/* ENCRYPT / DECRYPT */ /* ENCRYPT / DECRYPT */
static uint static uint
cipher_block_size(PX_Cipher *c) cipher_block_size(PX_Cipher * c)
{ {
MCRYPT ctx = (MCRYPT)c->ptr; MCRYPT ctx = (MCRYPT) c->ptr;
return mcrypt_enc_get_block_size(ctx); return mcrypt_enc_get_block_size(ctx);
} }
static uint static uint
cipher_key_size(PX_Cipher *c) cipher_key_size(PX_Cipher * c)
{ {
MCRYPT ctx = (MCRYPT)c->ptr; MCRYPT ctx = (MCRYPT) c->ptr;
return mcrypt_enc_get_key_size(ctx); return mcrypt_enc_get_key_size(ctx);
} }
static uint static uint
cipher_iv_size(PX_Cipher *c) cipher_iv_size(PX_Cipher * c)
{ {
MCRYPT ctx = (MCRYPT)c->ptr; MCRYPT ctx = (MCRYPT) c->ptr;
return mcrypt_enc_mode_has_iv(ctx) return mcrypt_enc_mode_has_iv(ctx)
? mcrypt_enc_get_iv_size(ctx) : 0; ? mcrypt_enc_get_iv_size(ctx) : 0;
} }
static int static int
cipher_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv) cipher_init(PX_Cipher * c, const uint8 *key, uint klen, const uint8 *iv)
{ {
int err; int err;
MCRYPT ctx = (MCRYPT)c->ptr; MCRYPT ctx = (MCRYPT) c->ptr;
err = mcrypt_generic_init(ctx, (char *)key, klen, (char*)iv); err = mcrypt_generic_init(ctx, (char *) key, klen, (char *) iv);
if (err < 0) if (err < 0)
elog(ERROR, "mcrypt_generic_init error: %s", mcrypt_strerror(err)); elog(ERROR, "mcrypt_generic_init error: %s", mcrypt_strerror(err));
@ -147,10 +150,10 @@ cipher_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv)
} }
static int static int
cipher_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) cipher_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
int err; int err;
MCRYPT ctx = (MCRYPT)c->ptr; MCRYPT ctx = (MCRYPT) c->ptr;
memcpy(res, data, dlen); memcpy(res, data, dlen);
@ -161,10 +164,10 @@ cipher_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
} }
static int static int
cipher_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) cipher_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
int err; int err;
MCRYPT ctx = (MCRYPT)c->ptr; MCRYPT ctx = (MCRYPT) c->ptr;
memcpy(res, data, dlen); memcpy(res, data, dlen);
@ -176,15 +179,15 @@ cipher_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
static void static void
cipher_free(PX_Cipher *c) cipher_free(PX_Cipher * c)
{ {
MCRYPT ctx = (MCRYPT)c->ptr; MCRYPT ctx = (MCRYPT) c->ptr;
if (c->pstat) if (c->pstat)
mcrypt_generic_end(ctx); mcrypt_generic_end(ctx);
else else
mcrypt_module_close(ctx); mcrypt_module_close(ctx);
px_free(c); px_free(c);
} }
@ -223,33 +226,34 @@ static char *modes[] = {
}; };
static PX_Alias aliases[] = { static PX_Alias aliases[] = {
{"bf", "blowfish" }, {"bf", "blowfish"},
{"3des", "tripledes" }, {"3des", "tripledes"},
{"des3", "tripledes" }, {"des3", "tripledes"},
{"aes", "rijndael-128" }, {"aes", "rijndael-128"},
{"rijndael", "rijndael-128" }, {"rijndael", "rijndael-128"},
{"aes-128", "rijndael-128" }, {"aes-128", "rijndael-128"},
{"aes-192", "rijndael-192" }, {"aes-192", "rijndael-192"},
{"aes-256", "rijndael-256" }, {"aes-256", "rijndael-256"},
{ NULL, NULL } {NULL, NULL}
}; };
static PX_Alias mode_aliases[] = { static PX_Alias mode_aliases[] = {
#if 0 /* N/A */ #if 0 /* N/A */
{ "cfb", "ncfb" }, {"cfb", "ncfb"},
{ "ofb", "nofb" }, {"ofb", "nofb"},
{ "cfb64", "ncfb" }, {"cfb64", "ncfb"},
#endif #endif
/* { "ofb64", "nofb" }, not sure it works */ /* { "ofb64", "nofb" }, not sure it works */
{ "cfb8", "cfb" }, {"cfb8", "cfb"},
{ "ofb8", "ofb" }, {"ofb8", "ofb"},
{ NULL, NULL } {NULL, NULL}
}; };
static int is_mode(char *s) static int
is_mode(char *s)
{ {
char **p; char **p;
if (*s >= '0' && *s <= '9') if (*s >= '0' && *s <= '9')
return 0; return 0;
@ -263,7 +267,7 @@ static int is_mode(char *s)
/* PUBLIC FUNCTIONS */ /* PUBLIC FUNCTIONS */
int int
px_find_digest(const char *name, PX_MD **res) px_find_digest(const char *name, PX_MD ** res)
{ {
PX_MD *h; PX_MD *h;
MHASH mh; MHASH mh;
@ -290,19 +294,21 @@ px_find_digest(const char *name, PX_MD **res)
int int
px_find_cipher(const char *name, PX_Cipher **res) px_find_cipher(const char *name, PX_Cipher ** res)
{ {
char nbuf[PX_MAX_NAMELEN + 1]; char nbuf[PX_MAX_NAMELEN + 1];
const char *mode = NULL; const char *mode = NULL;
char *p; char *p;
MCRYPT ctx; MCRYPT ctx;
PX_Cipher *c; PX_Cipher *c;
strcpy(nbuf, name); strcpy(nbuf, name);
if ((p = strrchr(nbuf, '-')) != NULL) { if ((p = strrchr(nbuf, '-')) != NULL)
if (is_mode(p + 1)) { {
if (is_mode(p + 1))
{
mode = p + 1; mode = p + 1;
*p = 0; *p = 0;
} }
@ -310,19 +316,19 @@ px_find_cipher(const char *name, PX_Cipher **res)
name = px_resolve_alias(aliases, nbuf); name = px_resolve_alias(aliases, nbuf);
if (!mode) { if (!mode)
{
mode = "cbc"; mode = "cbc";
/* /*
if (mcrypt_module_is_block_algorithm(name, NULL)) * if (mcrypt_module_is_block_algorithm(name, NULL)) mode = "cbc";
mode = "cbc"; * else mode = "stream";
else */
mode = "stream";
*/
} }
mode = px_resolve_alias(mode_aliases, mode); mode = px_resolve_alias(mode_aliases, mode);
ctx = mcrypt_module_open((char*)name, NULL, (char*)mode, NULL); ctx = mcrypt_module_open((char *) name, NULL, (char *) mode, NULL);
if (ctx == (void*)MCRYPT_FAILED) if (ctx == (void *) MCRYPT_FAILED)
return -1; return -1;
c = palloc(sizeof *c); c = palloc(sizeof *c);
@ -339,4 +345,3 @@ px_find_cipher(const char *name, PX_Cipher **res)
*res = c; *res = c;
return 0; return 0;
} }

View File

@ -33,7 +33,7 @@
#include "px-crypt.h" #include "px-crypt.h"
char px_crypt_a64[] = char px_crypt_a64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/* 0000000000111111111122222222223333333333444444444455555555556666 */ /* 0000000000111111111122222222223333333333444444444455555555556666 */
/* 0123456789012345678901234567890123456789012345678901234567890123 */ /* 0123456789012345678901234567890123456789012345678901234567890123 */

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: openssl.c,v 1.5 2001/09/23 04:12:44 momjian Exp $ * $Id: openssl.c,v 1.6 2001/10/25 05:49:19 momjian Exp $
*/ */
#include <postgres.h> #include <postgres.h>
@ -60,7 +60,7 @@ digest_reset(PX_MD * h)
} }
static void static void
digest_update(PX_MD * h, const uint8 * data, uint dlen) digest_update(PX_MD * h, const uint8 *data, uint dlen)
{ {
EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr; EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
@ -68,7 +68,7 @@ digest_update(PX_MD * h, const uint8 * data, uint dlen)
} }
static void static void
digest_finish(PX_MD * h, uint8 * dst) digest_finish(PX_MD * h, uint8 *dst)
{ {
EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr; EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
@ -94,50 +94,57 @@ digest_free(PX_MD * h)
*/ */
typedef struct { typedef struct
union { {
struct { union
BF_KEY key; {
int num; struct
} bf; {
BF_KEY key;
int num;
} bf;
EVP_CIPHER_CTX evp_ctx; EVP_CIPHER_CTX evp_ctx;
} u; } u;
const EVP_CIPHER *evp_ciph; const EVP_CIPHER *evp_ciph;
uint8 key[EVP_MAX_KEY_LENGTH]; uint8 key[EVP_MAX_KEY_LENGTH];
uint8 iv[EVP_MAX_IV_LENGTH]; uint8 iv[EVP_MAX_IV_LENGTH];
uint klen; uint klen;
uint init; uint init;
} ossldata; } ossldata;
/* generic EVP */ /* generic EVP */
static uint static uint
gen_evp_block_size(PX_Cipher *c) gen_evp_block_size(PX_Cipher * c)
{ {
ossldata *od = (ossldata *)c->ptr; ossldata *od = (ossldata *) c->ptr;
return EVP_CIPHER_block_size(od->evp_ciph); return EVP_CIPHER_block_size(od->evp_ciph);
} }
static uint static uint
gen_evp_key_size(PX_Cipher *c) gen_evp_key_size(PX_Cipher * c)
{ {
ossldata *od = (ossldata *)c->ptr; ossldata *od = (ossldata *) c->ptr;
return EVP_CIPHER_key_length(od->evp_ciph); return EVP_CIPHER_key_length(od->evp_ciph);
} }
static uint static uint
gen_evp_iv_size(PX_Cipher *c) gen_evp_iv_size(PX_Cipher * c)
{ {
uint ivlen; uint ivlen;
ossldata *od = (ossldata *)c->ptr; ossldata *od = (ossldata *) c->ptr;
ivlen = EVP_CIPHER_iv_length(od->evp_ciph); ivlen = EVP_CIPHER_iv_length(od->evp_ciph);
return ivlen; return ivlen;
} }
static void static void
gen_evp_free(PX_Cipher *c) gen_evp_free(PX_Cipher * c)
{ {
ossldata *od = (ossldata*)c->ptr; ossldata *od = (ossldata *) c->ptr;
memset(od, 0, sizeof(*od)); memset(od, 0, sizeof(*od));
pfree(od); pfree(od);
pfree(c); pfree(c);
@ -146,13 +153,14 @@ gen_evp_free(PX_Cipher *c)
/* fun */ /* fun */
static int static int
gen_evp_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv) gen_evp_init(PX_Cipher * c, const uint8 *key, uint klen, const uint8 *iv)
{ {
ossldata *od = (ossldata*)c->ptr; ossldata *od = (ossldata *) c->ptr;
uint bs = gen_evp_block_size(c); uint bs = gen_evp_block_size(c);
if (iv) {
if (iv)
memcpy(od->iv, iv, bs); memcpy(od->iv, iv, bs);
} else else
memset(od->iv, 0, bs); memset(od->iv, 0, bs);
memcpy(od->key, key, klen); memcpy(od->key, key, klen);
od->klen = klen; od->klen = klen;
@ -161,19 +169,20 @@ gen_evp_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv)
} }
static void static void
_gen_init(PX_Cipher *c, int enc) _gen_init(PX_Cipher * c, int enc)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
od->evp_ciph->init(&od->u.evp_ctx, od->key, od->iv, enc); od->evp_ciph->init(&od->u.evp_ctx, od->key, od->iv, enc);
od->init = 1; od->init = 1;
od->u.evp_ctx.encrypt = enc; od->u.evp_ctx.encrypt = enc;
} }
static int static int
gen_evp_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) gen_evp_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
if (!od->init) if (!od->init)
_gen_init(c, 1); _gen_init(c, 1);
od->evp_ciph->do_cipher(&od->u.evp_ctx, res, data, dlen); od->evp_ciph->do_cipher(&od->u.evp_ctx, res, data, dlen);
@ -181,9 +190,10 @@ gen_evp_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
} }
static int static int
gen_evp_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) gen_evp_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
if (!od->init) if (!od->init)
_gen_init(c, 0); _gen_init(c, 0);
od->evp_ciph->do_cipher(&od->u.evp_ctx, res, data, dlen); od->evp_ciph->do_cipher(&od->u.evp_ctx, res, data, dlen);
@ -193,84 +203,95 @@ gen_evp_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
/* Blowfish */ /* Blowfish */
static int static int
bf_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv) bf_init(PX_Cipher * c, const uint8 *key, uint klen, const uint8 *iv)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
BF_set_key(&od->u.bf.key, klen, key); BF_set_key(&od->u.bf.key, klen, key);
if (iv) { if (iv)
memcpy(od->iv, iv, BF_BLOCK); memcpy(od->iv, iv, BF_BLOCK);
} else else
memset(od->iv, 0, BF_BLOCK); memset(od->iv, 0, BF_BLOCK);
od->u.bf.num = 0; od->u.bf.num = 0;
return 0; return 0;
} }
static int static int
bf_ecb_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) bf_ecb_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
uint bs = gen_evp_block_size(c), i; uint bs = gen_evp_block_size(c),
ossldata *od = c->ptr; i;
ossldata *od = c->ptr;
for (i = 0; i < dlen / bs; i++) for (i = 0; i < dlen / bs; i++)
BF_ecb_encrypt(data+i*bs, res+i*bs, &od->u.bf.key, BF_ENCRYPT); BF_ecb_encrypt(data + i * bs, res + i * bs, &od->u.bf.key, BF_ENCRYPT);
return 0; return 0;
} }
static int static int
bf_ecb_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) bf_ecb_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
uint bs = gen_evp_block_size(c), i; uint bs = gen_evp_block_size(c),
ossldata *od = c->ptr; i;
ossldata *od = c->ptr;
for (i = 0; i < dlen / bs; i++) for (i = 0; i < dlen / bs; i++)
BF_ecb_encrypt(data+i*bs, res+i*bs, &od->u.bf.key, BF_DECRYPT); BF_ecb_encrypt(data + i * bs, res + i * bs, &od->u.bf.key, BF_DECRYPT);
return 0; return 0;
} }
static int static int
bf_cbc_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) bf_cbc_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_ENCRYPT); BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_ENCRYPT);
return 0; return 0;
} }
static int static int
bf_cbc_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) bf_cbc_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_DECRYPT); BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_DECRYPT);
return 0; return 0;
} }
static int static int
bf_cfb64_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) bf_cfb64_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
&od->u.bf.num, BF_ENCRYPT); &od->u.bf.num, BF_ENCRYPT);
return 0; return 0;
} }
static int static int
bf_cfb64_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) bf_cfb64_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
&od->u.bf.num, BF_DECRYPT); &od->u.bf.num, BF_DECRYPT);
return 0; return 0;
} }
static int static int
bf_ofb64_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) bf_ofb64_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
BF_ofb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, &od->u.bf.num); BF_ofb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, &od->u.bf.num);
return 0; return 0;
} }
static int static int
bf_ofb64_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res) bf_ofb64_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
{ {
ossldata *od = c->ptr; ossldata *od = c->ptr;
BF_ofb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, &od->u.bf.num); BF_ofb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, &od->u.bf.num);
return 0; return 0;
} }
@ -279,14 +300,14 @@ bf_ofb64_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
* aliases * aliases
*/ */
static PX_Alias ossl_aliases [] = { static PX_Alias ossl_aliases[] = {
{ "bf", "bf-cbc" }, {"bf", "bf-cbc"},
{ "blowfish", "bf-cbc" }, {"blowfish", "bf-cbc"},
{ "blowfish-cbc", "bf-cbc" }, {"blowfish-cbc", "bf-cbc"},
{ "blowfish-ecb", "bf-ecb" }, {"blowfish-ecb", "bf-ecb"},
{ "blowfish-cfb", "bf-cfb" }, {"blowfish-cfb", "bf-cfb"},
{ "blowfish-ofb", "bf-ofb" }, {"blowfish-ofb", "bf-ofb"},
{ NULL } {NULL}
}; };
/* /*
@ -299,19 +320,44 @@ static PX_Alias ossl_mode_aliases [] = {
/* /*
* Special handlers * Special handlers
*/ */
struct { struct
char *name; {
PX_Cipher cf; char *name;
} spec_types [] = { PX_Cipher cf;
{ "bf-cbc", { gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size, } spec_types[] =
bf_init, bf_cbc_encrypt, bf_cbc_decrypt, gen_evp_free}},
{ "bf-ecb", { gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size, {
bf_init, bf_ecb_encrypt, bf_ecb_decrypt, gen_evp_free}}, {
{ "bf-cfb", { gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size, "bf-cbc",
bf_init, bf_cfb64_encrypt, bf_cfb64_decrypt, gen_evp_free}}, {
{ "bf-ofb", { gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size, gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
bf_init, bf_ofb64_encrypt, bf_ofb64_decrypt, gen_evp_free}}, bf_init, bf_cbc_encrypt, bf_cbc_decrypt, gen_evp_free
{ NULL } }
},
{
"bf-ecb",
{
gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
bf_init, bf_ecb_encrypt, bf_ecb_decrypt, gen_evp_free
}
},
{
"bf-cfb",
{
gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
bf_init, bf_cfb64_encrypt, bf_cfb64_decrypt, gen_evp_free
}
},
{
"bf-ofb",
{
gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
bf_init, bf_ofb64_encrypt, bf_ofb64_decrypt, gen_evp_free
}
},
{
NULL
}
}; };
/* /*
@ -322,7 +368,7 @@ static PX_Cipher gen_evp_handler = {
gen_evp_init, gen_evp_encrypt, gen_evp_decrypt, gen_evp_free gen_evp_init, gen_evp_encrypt, gen_evp_decrypt, gen_evp_free
}; };
static int px_openssl_initialized = 0; static int px_openssl_initialized = 0;
/* ATM not needed /* ATM not needed
static void *o_alloc(uint s) { return px_alloc(s); } static void *o_alloc(uint s) { return px_alloc(s); }
@ -333,7 +379,7 @@ static void o_free(void *p) { px_free(p); }
/* PUBLIC functions */ /* PUBLIC functions */
int int
px_find_digest(const char *name, PX_MD **res) px_find_digest(const char *name, PX_MD ** res)
{ {
const EVP_MD *md; const EVP_MD *md;
EVP_MD_CTX *ctx; EVP_MD_CTX *ctx;
@ -342,7 +388,7 @@ px_find_digest(const char *name, PX_MD **res)
if (!px_openssl_initialized) if (!px_openssl_initialized)
{ {
px_openssl_initialized = 1; px_openssl_initialized = 1;
/*CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free);*/ /* CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free); */
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
} }
@ -368,17 +414,19 @@ px_find_digest(const char *name, PX_MD **res)
int int
px_find_cipher(const char *name, PX_Cipher **res) px_find_cipher(const char *name, PX_Cipher ** res)
{ {
uint i; uint i;
PX_Cipher *c = NULL, *csrc; PX_Cipher *c = NULL,
ossldata *od; *csrc;
ossldata *od;
const EVP_CIPHER *evp_c; const EVP_CIPHER *evp_c;
if (!px_openssl_initialized) { if (!px_openssl_initialized)
{
px_openssl_initialized = 1; px_openssl_initialized = 1;
/*CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free);*/ /* CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free); */
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
} }
@ -390,23 +438,23 @@ px_find_cipher(const char *name, PX_Cipher **res)
od = px_alloc(sizeof(*od)); od = px_alloc(sizeof(*od));
memset(od, 0, sizeof(*od)); memset(od, 0, sizeof(*od));
od->evp_ciph = evp_c; od->evp_ciph = evp_c;
csrc = NULL; csrc = NULL;
for (i = 0; spec_types[i].name; i++) for (i = 0; spec_types[i].name; i++)
if (!strcmp(name, spec_types[i].name)) { if (!strcmp(name, spec_types[i].name))
{
csrc = &spec_types[i].cf; csrc = &spec_types[i].cf;
break; break;
} }
if (csrc == NULL) if (csrc == NULL)
csrc = &gen_evp_handler; csrc = &gen_evp_handler;
c = px_alloc(sizeof(*c)); c = px_alloc(sizeof(*c));
memcpy(c, csrc, sizeof(*c)); memcpy(c, csrc, sizeof(*c));
c->ptr = od; c->ptr = od;
*res = c; *res = c;
return 0; return 0;
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: pgcrypto.c,v 1.9 2001/09/23 04:12:44 momjian Exp $ * $Id: pgcrypto.c,v 1.10 2001/10/25 05:49:19 momjian Exp $
*/ */
#include <postgres.h> #include <postgres.h>
@ -41,7 +41,7 @@
typedef int (*PFN) (const char *name, void **res); typedef int (*PFN) (const char *name, void **res);
static void * static void *
find_provider(text * name, PFN pf, char *desc, int silent); find_provider(text *name, PFN pf, char *desc, int silent);
/* SQL function: hash(text, text) returns text */ /* SQL function: hash(text, text) returns text */
PG_FUNCTION_INFO_V1(pg_digest); PG_FUNCTION_INFO_V1(pg_digest);
@ -313,17 +313,21 @@ PG_FUNCTION_INFO_V1(pg_encrypt);
Datum Datum
pg_encrypt(PG_FUNCTION_ARGS) pg_encrypt(PG_FUNCTION_ARGS)
{ {
int err; int err;
bytea *data, *key, *res; bytea *data,
text *type; *key,
PX_Combo *c; *res;
uint dlen, klen, rlen; text *type;
PX_Combo *c;
uint dlen,
klen,
rlen;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2)) if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
PG_RETURN_NULL(); PG_RETURN_NULL();
type = PG_GETARG_TEXT_P(2); type = PG_GETARG_TEXT_P(2);
c = find_provider(type, (PFN)px_find_combo, "Cipher", 0); c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
data = PG_GETARG_BYTEA_P(0); data = PG_GETARG_BYTEA_P(0);
key = PG_GETARG_BYTEA_P(1); key = PG_GETARG_BYTEA_P(1);
@ -341,8 +345,9 @@ pg_encrypt(PG_FUNCTION_ARGS)
PG_FREE_IF_COPY(data, 0); PG_FREE_IF_COPY(data, 0);
PG_FREE_IF_COPY(key, 1); PG_FREE_IF_COPY(key, 1);
PG_FREE_IF_COPY(type, 2); PG_FREE_IF_COPY(type, 2);
if (err) { if (err)
{
pfree(res); pfree(res);
elog(ERROR, "encrypt error: %d", err); elog(ERROR, "encrypt error: %d", err);
} }
@ -357,17 +362,21 @@ PG_FUNCTION_INFO_V1(pg_decrypt);
Datum Datum
pg_decrypt(PG_FUNCTION_ARGS) pg_decrypt(PG_FUNCTION_ARGS)
{ {
int err; int err;
bytea *data, *key, *res; bytea *data,
text *type; *key,
PX_Combo *c; *res;
uint dlen, klen, rlen; text *type;
PX_Combo *c;
uint dlen,
klen,
rlen;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2)) if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
PG_RETURN_NULL(); PG_RETURN_NULL();
type = PG_GETARG_TEXT_P(2); type = PG_GETARG_TEXT_P(2);
c = find_provider(type, (PFN)px_find_combo, "Cipher", 0); c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
data = PG_GETARG_BYTEA_P(0); data = PG_GETARG_BYTEA_P(0);
key = PG_GETARG_BYTEA_P(1); key = PG_GETARG_BYTEA_P(1);
@ -401,18 +410,24 @@ PG_FUNCTION_INFO_V1(pg_encrypt_iv);
Datum Datum
pg_encrypt_iv(PG_FUNCTION_ARGS) pg_encrypt_iv(PG_FUNCTION_ARGS)
{ {
int err; int err;
bytea *data, *key, *iv, *res; bytea *data,
text *type; *key,
PX_Combo *c; *iv,
uint dlen, klen, ivlen, rlen; *res;
text *type;
PX_Combo *c;
uint dlen,
klen,
ivlen,
rlen;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1) if (PG_ARGISNULL(0) || PG_ARGISNULL(1)
|| PG_ARGISNULL(2) || PG_ARGISNULL(3)) || PG_ARGISNULL(2) || PG_ARGISNULL(3))
PG_RETURN_NULL(); PG_RETURN_NULL();
type = PG_GETARG_TEXT_P(3); type = PG_GETARG_TEXT_P(3);
c = find_provider(type, (PFN)px_find_combo, "Cipher", 0); c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
data = PG_GETARG_BYTEA_P(0); data = PG_GETARG_BYTEA_P(0);
key = PG_GETARG_BYTEA_P(1); key = PG_GETARG_BYTEA_P(1);
@ -449,18 +464,24 @@ PG_FUNCTION_INFO_V1(pg_decrypt_iv);
Datum Datum
pg_decrypt_iv(PG_FUNCTION_ARGS) pg_decrypt_iv(PG_FUNCTION_ARGS)
{ {
int err; int err;
bytea *data, *key, *iv, *res; bytea *data,
text *type; *key,
PX_Combo *c; *iv,
uint dlen, klen, rlen, ivlen; *res;
text *type;
PX_Combo *c;
uint dlen,
klen,
rlen,
ivlen;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1) if (PG_ARGISNULL(0) || PG_ARGISNULL(1)
|| PG_ARGISNULL(2) || PG_ARGISNULL(3)) || PG_ARGISNULL(2) || PG_ARGISNULL(3))
PG_RETURN_NULL(); PG_RETURN_NULL();
type = PG_GETARG_TEXT_P(3); type = PG_GETARG_TEXT_P(3);
c = find_provider(type, (PFN)px_find_combo, "Cipher", 0); c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
data = PG_GETARG_BYTEA_P(0); data = PG_GETARG_BYTEA_P(0);
key = PG_GETARG_BYTEA_P(1); key = PG_GETARG_BYTEA_P(1);
@ -480,7 +501,7 @@ pg_decrypt_iv(PG_FUNCTION_ARGS)
if (err) if (err)
elog(ERROR, "decrypt_iv error: %d", err); elog(ERROR, "decrypt_iv error: %d", err);
VARATT_SIZEP(res) = VARHDRSZ + rlen; VARATT_SIZEP(res) = VARHDRSZ + rlen;
PG_FREE_IF_COPY(data, 0); PG_FREE_IF_COPY(data, 0);
@ -497,15 +518,15 @@ PG_FUNCTION_INFO_V1(pg_cipher_exists);
Datum Datum
pg_cipher_exists(PG_FUNCTION_ARGS) pg_cipher_exists(PG_FUNCTION_ARGS)
{ {
text *arg; text *arg;
PX_Combo *c; PX_Combo *c;
if (PG_ARGISNULL(0)) if (PG_ARGISNULL(0))
PG_RETURN_NULL(); PG_RETURN_NULL();
arg = PG_GETARG_TEXT_P(0); arg = PG_GETARG_TEXT_P(0);
c = find_provider(arg, (PFN)px_find_combo, "Cipher", 1); c = find_provider(arg, (PFN) px_find_combo, "Cipher", 1);
if (c != NULL) if (c != NULL)
px_combo_free(c); px_combo_free(c);
@ -514,7 +535,7 @@ pg_cipher_exists(PG_FUNCTION_ARGS)
static void * static void *
find_provider(text * name, find_provider(text *name,
PFN provider_lookup, PFN provider_lookup,
char *desc, int silent) char *desc, int silent)
{ {

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: pgcrypto.h,v 1.5 2001/09/23 04:12:44 momjian Exp $ * $Id: pgcrypto.h,v 1.6 2001/10/25 05:49:20 momjian Exp $
*/ */
#ifndef _PG_CRYPTO_H #ifndef _PG_CRYPTO_H
@ -45,6 +45,4 @@ Datum pg_decrypt(PG_FUNCTION_ARGS);
Datum pg_encrypt_iv(PG_FUNCTION_ARGS); Datum pg_encrypt_iv(PG_FUNCTION_ARGS);
Datum pg_decrypt_iv(PG_FUNCTION_ARGS); Datum pg_decrypt_iv(PG_FUNCTION_ARGS);
Datum pg_cipher_exists(PG_FUNCTION_ARGS); Datum pg_cipher_exists(PG_FUNCTION_ARGS);
#endif #endif

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: px-crypt.c,v 1.2 2001/09/23 04:12:44 momjian Exp $ * $Id: px-crypt.c,v 1.3 2001/10/25 05:49:20 momjian Exp $
*/ */
#include <postgres.h> #include <postgres.h>
@ -38,7 +38,7 @@
static char * static char *
run_crypt_des(const char *psw, const char *salt, run_crypt_des(const char *psw, const char *salt,
char *buf, unsigned len) char *buf, unsigned len)
{ {
char *res; char *res;
@ -51,37 +51,51 @@ run_crypt_des(const char *psw, const char *salt,
static char * static char *
run_crypt_md5(const char *psw, const char *salt, run_crypt_md5(const char *psw, const char *salt,
char *buf, unsigned len) char *buf, unsigned len)
{ {
char *res; char *res;
res = px_crypt_md5(psw, salt, buf, len); res = px_crypt_md5(psw, salt, buf, len);
return res; return res;
} }
static char * static char *
run_crypt_bf(const char *psw, const char *salt, run_crypt_bf(const char *psw, const char *salt,
char *buf, unsigned len) char *buf, unsigned len)
{ {
char *res; char *res;
res = _crypt_blowfish_rn(psw, salt, buf, len); res = _crypt_blowfish_rn(psw, salt, buf, len);
return res; return res;
} }
static struct static struct
{ {
char *id; char *id;
unsigned id_len; unsigned id_len;
char *(*crypt) (const char *psw, const char *salt, char *(*crypt) (const char *psw, const char *salt,
char *buf, unsigned len); char *buf, unsigned len);
} px_crypt_list[] = } px_crypt_list[] =
{ {
{ "$2a$", 4, run_crypt_bf }, {
{ "$2$", 3, NULL }, /* N/A */ "$2a$", 4, run_crypt_bf
{ "$1$", 3, run_crypt_md5 }, },
{ "_", 1, run_crypt_des }, {
{ "", 0, run_crypt_des }, "$2$", 3, NULL
{ NULL, 0, NULL } }, /* N/A */
{
"$1$", 3, run_crypt_md5
},
{
"_", 1, run_crypt_des
},
{
"", 0, run_crypt_des
},
{
NULL, 0, NULL
}
}; };
char * char *
@ -125,41 +139,45 @@ px_crypt(const char *psw, const char *salt,
* salt generators * salt generators
*/ */
struct generator { struct generator
char *name; {
char *(*gen)(unsigned long count, const char *input, int size, char *name;
char *output, int output_size); char *(*gen) (unsigned long count, const char *input, int size,
int input_len; char *output, int output_size);
int def_rounds; int input_len;
int min_rounds; int def_rounds;
int max_rounds; int min_rounds;
int max_rounds;
}; };
static struct generator gen_list [] = { static struct generator gen_list[] = {
{ "des", _crypt_gensalt_traditional_rn, 2, 0, 0, 0 }, {"des", _crypt_gensalt_traditional_rn, 2, 0, 0, 0},
{ "md5", _crypt_gensalt_md5_rn, 6, 0, 0, 0 }, {"md5", _crypt_gensalt_md5_rn, 6, 0, 0, 0},
{ "xdes", _crypt_gensalt_extended_rn, 3, PX_XDES_ROUNDS, 1, 0xFFFFFF }, {"xdes", _crypt_gensalt_extended_rn, 3, PX_XDES_ROUNDS, 1, 0xFFFFFF},
{ "bf", _crypt_gensalt_blowfish_rn, 16, PX_BF_ROUNDS, 4, 31 }, {"bf", _crypt_gensalt_blowfish_rn, 16, PX_BF_ROUNDS, 4, 31},
{ NULL, NULL, 0, 0, 0 } {NULL, NULL, 0, 0, 0}
}; };
uint uint
px_gen_salt(const char *salt_type, char *buf, int rounds) px_gen_salt(const char *salt_type, char *buf, int rounds)
{ {
int i, res; int i,
res;
struct generator *g; struct generator *g;
char *p; char *p;
char rbuf[16]; char rbuf[16];
for (i = 0; gen_list[i].name; i++) { for (i = 0; gen_list[i].name; i++)
{
g = &gen_list[i]; g = &gen_list[i];
if (strcasecmp(g->name, salt_type) != 0) if (strcasecmp(g->name, salt_type) != 0)
continue; continue;
if (g->def_rounds) { if (g->def_rounds)
{
if (rounds == 0) if (rounds == 0)
rounds = g->def_rounds; rounds = g->def_rounds;
if (rounds < g->min_rounds || rounds > g->max_rounds) if (rounds < g->min_rounds || rounds > g->max_rounds)
return 0; return 0;
} }
@ -170,10 +188,9 @@ px_gen_salt(const char *salt_type, char *buf, int rounds)
p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN); p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN);
memset(rbuf, 0, sizeof(rbuf)); memset(rbuf, 0, sizeof(rbuf));
return p != NULL ? strlen(p) : 0; return p != NULL ? strlen(p) : 0;
} }
return 0; return 0;
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: px-crypt.h,v 1.2 2001/09/23 04:12:44 momjian Exp $ * $Id: px-crypt.h,v 1.3 2001/10/25 05:49:20 momjian Exp $
*/ */
#ifndef _PX_CRYPT_H #ifndef _PX_CRYPT_H
@ -36,7 +36,7 @@
#define PX_MAX_CRYPT 128 #define PX_MAX_CRYPT 128
/* max salt returned by gen_salt() */ /* max salt returned by gen_salt() */
#define PX_MAX_SALT_LEN 128 #define PX_MAX_SALT_LEN 128
/* default rounds for xdes salt */ /* default rounds for xdes salt */
/* NetBSD bin/passwd/local_passwd.c has (29 * 25)*/ /* NetBSD bin/passwd/local_passwd.c has (29 * 25)*/
@ -58,19 +58,20 @@ unsigned px_gen_salt(const char *salt_type, char *dst, int rounds);
/* misc.c */ /* misc.c */
extern void px_crypt_to64(char *s, unsigned long v, int n); extern void px_crypt_to64(char *s, unsigned long v, int n);
extern char px_crypt_a64[]; extern char px_crypt_a64[];
/* avoid conflicts with system libs */ /* avoid conflicts with system libs */
#define _crypt_to64 px_crypt_to64 #define _crypt_to64 px_crypt_to64
#define _crypt_a64 px_crypt_a64 #define _crypt_a64 px_crypt_a64
/* crypt-gensalt.c */ /* crypt-gensalt.c */
char *_crypt_gensalt_traditional_rn(unsigned long count, char *_crypt_gensalt_traditional_rn(unsigned long count,
const char *input, int size, char *output, int output_size); const char *input, int size, char *output, int output_size);
char *_crypt_gensalt_extended_rn(unsigned long count, char *_crypt_gensalt_extended_rn(unsigned long count,
const char *input, int size, char *output, int output_size); const char *input, int size, char *output, int output_size);
char *_crypt_gensalt_md5_rn(unsigned long count, char *_crypt_gensalt_md5_rn(unsigned long count,
const char *input, int size, char *output, int output_size); const char *input, int size, char *output, int output_size);
char *_crypt_gensalt_blowfish_rn(unsigned long count, char *_crypt_gensalt_blowfish_rn(unsigned long count,
const char *input, int size, char *output, int output_size); const char *input, int size, char *output, int output_size);
#ifndef PX_SYSTEM_CRYPT #ifndef PX_SYSTEM_CRYPT
@ -85,8 +86,7 @@ char *_crypt_blowfish_rn(const char *key, const char *setting,
char *px_crypt_des(const char *key, const char *setting); char *px_crypt_des(const char *key, const char *setting);
/* crypt-md5.c */ /* crypt-md5.c */
char *px_crypt_md5(const char *pw, const char *salt, char *px_crypt_md5(const char *pw, const char *salt,
char *dst, unsigned dstlen); char *dst, unsigned dstlen);
#endif /* !PX_SYSTEM_CRYPT */ #endif /* !PX_SYSTEM_CRYPT */
#endif /* _PX_CRYPT_H */ #endif /* _PX_CRYPT_H */

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: px-hmac.c,v 1.1 2001/08/21 01:32:01 momjian Exp $ * $Id: px-hmac.c,v 1.2 2001/10/25 05:49:20 momjian Exp $
*/ */
@ -50,7 +50,7 @@ hmac_block_size(PX_HMAC * h)
} }
static void static void
hmac_init(PX_HMAC * h, const uint8 * key, uint klen) hmac_init(PX_HMAC * h, const uint8 *key, uint klen)
{ {
uint bs, uint bs,
hlen, hlen,
@ -95,13 +95,13 @@ hmac_reset(PX_HMAC * h)
} }
static void static void
hmac_update(PX_HMAC * h, const uint8 * data, uint dlen) hmac_update(PX_HMAC * h, const uint8 *data, uint dlen)
{ {
px_md_update(h->md, data, dlen); px_md_update(h->md, data, dlen);
} }
static void static void
hmac_finish(PX_HMAC * h, uint8 * dst) hmac_finish(PX_HMAC * h, uint8 *dst)
{ {
PX_MD *md = h->md; PX_MD *md = h->md;
uint bs, uint bs,

View File

@ -1,7 +1,7 @@
/* /*
* px.c * px.c
* Various cryptographic stuff for PostgreSQL. * Various cryptographic stuff for PostgreSQL.
* *
* Copyright (c) 2001 Marko Kreen * Copyright (c) 2001 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: px.c,v 1.2 2001/09/06 03:21:39 momjian Exp $ * $Id: px.c,v 1.3 2001/10/25 05:49:20 momjian Exp $
*/ */
#include <postgres.h> #include <postgres.h>
@ -35,9 +35,10 @@
const char * const char *
px_resolve_alias(const PX_Alias *list, const char *name) px_resolve_alias(const PX_Alias * list, const char *name)
{ {
while (list->name) { while (list->name)
{
if (!strcasecmp(list->alias, name)) if (!strcasecmp(list->alias, name))
return list->name; return list->name;
list++; list++;
@ -50,32 +51,35 @@ px_resolve_alias(const PX_Alias *list, const char *name)
*/ */
static uint static uint
combo_encrypt_len(PX_Combo *cx, uint dlen) combo_encrypt_len(PX_Combo * cx, uint dlen)
{ {
return dlen + 512; return dlen + 512;
} }
static uint static uint
combo_decrypt_len(PX_Combo *cx, uint dlen) combo_decrypt_len(PX_Combo * cx, uint dlen)
{ {
return dlen; return dlen;
} }
static int static int
combo_init(PX_Combo *cx, const uint8 *key, uint klen, combo_init(PX_Combo * cx, const uint8 *key, uint klen,
const uint8 *iv, uint ivlen) const uint8 *iv, uint ivlen)
{ {
int err; int err;
uint bs, ks, ivs; uint bs,
PX_Cipher *c = cx->cipher; ks,
uint8 *ivbuf = NULL; ivs;
uint8 *keybuf; PX_Cipher *c = cx->cipher;
uint8 *ivbuf = NULL;
uint8 *keybuf;
bs = px_cipher_block_size(c); bs = px_cipher_block_size(c);
ks = px_cipher_key_size(c); ks = px_cipher_key_size(c);
ivs = px_cipher_iv_size(c); ivs = px_cipher_iv_size(c);
if (ivs > 0) { if (ivs > 0)
{
ivbuf = px_alloc(ivs); ivbuf = px_alloc(ivs);
memset(ivbuf, 0, ivs); memset(ivbuf, 0, ivs);
if (ivlen > ivs) if (ivlen > ivs)
@ -97,39 +101,48 @@ combo_init(PX_Combo *cx, const uint8 *key, uint klen,
} }
static int static int
combo_encrypt(PX_Combo *cx, const uint8 *data, uint dlen, combo_encrypt(PX_Combo * cx, const uint8 *data, uint dlen,
uint8 *res, uint *rlen) uint8 *res, uint *rlen)
{ {
int err = 0; int err = 0;
uint8 *bbuf; uint8 *bbuf;
uint bs, maxlen, bpos, i, pad; uint bs,
maxlen,
bpos,
i,
pad;
PX_Cipher *c = cx->cipher; PX_Cipher *c = cx->cipher;
bbuf = NULL; bbuf = NULL;
maxlen = *rlen; maxlen = *rlen;
bs = px_cipher_block_size(c); bs = px_cipher_block_size(c);
/* encrypt */ /* encrypt */
if (bs > 1) { if (bs > 1)
{
bbuf = px_alloc(bs * 4); bbuf = px_alloc(bs * 4);
bpos = dlen % bs; bpos = dlen % bs;
*rlen = dlen - bpos; *rlen = dlen - bpos;
memcpy(bbuf, data + *rlen, bpos); memcpy(bbuf, data + *rlen, bpos);
/* encrypt full-block data */ /* encrypt full-block data */
if (*rlen) { if (*rlen)
{
err = px_cipher_encrypt(c, data, *rlen, res); err = px_cipher_encrypt(c, data, *rlen, res);
if (err) if (err)
goto out; goto out;
} }
/* bbuf has now bpos bytes of stuff */ /* bbuf has now bpos bytes of stuff */
if (cx->padding) { if (cx->padding)
{
pad = bs - (bpos % bs); pad = bs - (bpos % bs);
for (i = 0; i < pad; i++) for (i = 0; i < pad; i++)
bbuf[bpos++] = pad; bbuf[bpos++] = pad;
} else if (bpos % bs) { }
else if (bpos % bs)
{
/* ERROR? */ /* ERROR? */
pad = bs - (bpos % bs); pad = bs - (bpos % bs);
for (i = 0; i < pad; i++) for (i = 0; i < pad; i++)
@ -137,11 +150,14 @@ combo_encrypt(PX_Combo *cx, const uint8 *data, uint dlen,
} }
/* encrypt the rest - pad */ /* encrypt the rest - pad */
if (bpos) { if (bpos)
{
err = px_cipher_encrypt(c, bbuf, bpos, res + *rlen); err = px_cipher_encrypt(c, bbuf, bpos, res + *rlen);
*rlen += bpos; *rlen += bpos;
} }
} else { }
else
{
/* stream cipher/mode - no pad needed */ /* stream cipher/mode - no pad needed */
err = px_cipher_encrypt(c, data, dlen, res); err = px_cipher_encrypt(c, data, dlen, res);
if (err) if (err)
@ -149,48 +165,53 @@ combo_encrypt(PX_Combo *cx, const uint8 *data, uint dlen,
*rlen = dlen; *rlen = dlen;
} }
out: out:
if (bbuf) px_free(bbuf); if (bbuf)
px_free(bbuf);
return err; return err;
} }
static int static int
combo_decrypt(PX_Combo *cx, const uint8 *data, uint dlen, combo_decrypt(PX_Combo * cx, const uint8 *data, uint dlen,
uint8 *res, uint *rlen) uint8 *res, uint *rlen)
{ {
uint bs, i, pad; uint bs,
uint pad_ok; i,
pad;
uint pad_ok;
PX_Cipher *c = cx->cipher; PX_Cipher *c = cx->cipher;
bs = px_cipher_block_size(c); bs = px_cipher_block_size(c);
if (bs > 1 && (dlen % bs) != 0) { if (bs > 1 && (dlen % bs) != 0)
goto block_error; goto block_error;
}
/* decrypt */ /* decrypt */
*rlen = dlen; *rlen = dlen;
px_cipher_decrypt(c, data, dlen, res); px_cipher_decrypt(c, data, dlen, res);
/* unpad */ /* unpad */
if (bs > 1 && cx->padding) { if (bs > 1 && cx->padding)
{
pad = res[*rlen - 1]; pad = res[*rlen - 1];
pad_ok = 0; pad_ok = 0;
if (pad > 0 && pad <= bs && pad <= *rlen) { if (pad > 0 && pad <= bs && pad <= *rlen)
{
pad_ok = 1; pad_ok = 1;
for (i = *rlen - pad; i < *rlen; i++) for (i = *rlen - pad; i < *rlen; i++)
if (res[i] != pad) { if (res[i] != pad)
{
pad_ok = 0; pad_ok = 0;
break; break;
} }
} }
if (pad_ok) if (pad_ok)
*rlen -= pad; *rlen -= pad;
} }
return 0; return 0;
/* error reporting should be done in pgcrypto.c */ /* error reporting should be done in pgcrypto.c */
block_error: block_error:
elog(NOTICE, "Data not a multiple of block size"); elog(NOTICE, "Data not a multiple of block size");
@ -198,7 +219,7 @@ block_error:
} }
static void static void
combo_free(PX_Combo *cx) combo_free(PX_Combo * cx)
{ {
if (cx->cipher) if (cx->cipher)
px_cipher_free(cx->cipher); px_cipher_free(cx->cipher);
@ -211,31 +232,38 @@ combo_free(PX_Combo *cx)
static int static int
parse_cipher_name(char *full, char **cipher, char **pad) parse_cipher_name(char *full, char **cipher, char **pad)
{ {
char *p, *p2, *q; char *p,
*p2,
*q;
*cipher = full; *cipher = full;
*pad = NULL; *pad = NULL;
p = strchr(full, '/'); p = strchr(full, '/');
if (p != NULL) if (p != NULL)
*p++ = 0; *p++ = 0;
while (p != NULL) { while (p != NULL)
{
if ((q = strchr(p, '/')) != NULL) if ((q = strchr(p, '/')) != NULL)
*q++ = 0; *q++ = 0;
if (!*p) { if (!*p)
{
p = q; p = q;
continue; continue;
} }
p2 = strchr(p, ':'); p2 = strchr(p, ':');
if (p2 != NULL) { if (p2 != NULL)
{
*p2++ = 0; *p2++ = 0;
if (!strcmp(p, "pad")) if (!strcmp(p, "pad"))
*pad = p2; *pad = p2;
else else
return -1; return -1;
} else }
else
return -1; return -1;
p = q; p = q;
} }
return 0; return 0;
@ -244,12 +272,14 @@ parse_cipher_name(char *full, char **cipher, char **pad)
/* provider */ /* provider */
int int
px_find_combo(const char *name, PX_Combo **res) px_find_combo(const char *name, PX_Combo ** res)
{ {
int err; int err;
char *buf, *s_cipher, *s_pad; char *buf,
*s_cipher,
*s_pad;
PX_Combo *cx; PX_Combo *cx;
cx = px_alloc(sizeof(*cx)); cx = px_alloc(sizeof(*cx));
memset(cx, 0, sizeof(*cx)); memset(cx, 0, sizeof(*cx));
@ -258,7 +288,8 @@ px_find_combo(const char *name, PX_Combo **res)
strcpy(buf, name); strcpy(buf, name);
err = parse_cipher_name(buf, &s_cipher, &s_pad); err = parse_cipher_name(buf, &s_cipher, &s_pad);
if (err) { if (err)
{
px_free(buf); px_free(buf);
px_free(cx); px_free(cx);
return err; return err;
@ -267,15 +298,17 @@ px_find_combo(const char *name, PX_Combo **res)
err = px_find_cipher(s_cipher, &cx->cipher); err = px_find_cipher(s_cipher, &cx->cipher);
if (err) if (err)
goto err1; goto err1;
if (s_pad != NULL) { if (s_pad != NULL)
{
if (!strcmp(s_pad, "pkcs")) if (!strcmp(s_pad, "pkcs"))
cx->padding = 1; cx->padding = 1;
else if (!strcmp(s_pad, "none")) else if (!strcmp(s_pad, "none"))
cx->padding = 0; cx->padding = 0;
else else
goto err1; goto err1;
} else }
else
cx->padding = 1; cx->padding = 1;
cx->init = combo_init; cx->init = combo_init;
@ -290,7 +323,7 @@ px_find_combo(const char *name, PX_Combo **res)
*res = cx; *res = cx;
return 0; return 0;
err1: err1:
if (cx->cipher) if (cx->cipher)
px_cipher_free(cx->cipher); px_cipher_free(cx->cipher);
@ -298,4 +331,3 @@ err1:
px_free(buf); px_free(buf);
return -1; return -1;
} }

View File

@ -1,7 +1,7 @@
/* /*
* px.h * px.h
* Header file for pgcrypto. * Header file for pgcrypto.
* *
* Copyright (c) 2001 Marko Kreen * Copyright (c) 2001 Marko Kreen
* All rights reserved. * All rights reserved.
* *
@ -9,15 +9,15 @@
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: px.h,v 1.2 2001/09/23 04:12:44 momjian Exp $ * $Id: px.h,v 1.3 2001/10/25 05:49:20 momjian Exp $
*/ */
#ifndef __PX_H #ifndef __PX_H
@ -36,22 +36,21 @@
#define px_alloc(s) palloc(s) #define px_alloc(s) palloc(s)
#define px_realloc(p, s) prealloc(p, s) #define px_realloc(p, s) prealloc(p, s)
#define px_free(p) pfree(p) #define px_free(p) pfree(p)
#else #else
void *xalloc(size_t s); void *xalloc(size_t s);
void *xrealloc(void *p, size_t s); void *xrealloc(void *p, size_t s);
void xfree(void *p); void xfree(void *p);
#define px_alloc(s) xalloc(s) #define px_alloc(s) xalloc(s)
#define px_realloc(p, s) xrealloc(p, s) #define px_realloc(p, s) xrealloc(p, s)
#define px_free(p) xfree(p) #define px_free(p) xfree(p)
#endif #endif
/* max len of 'type' parms */ /* max len of 'type' parms */
#define PX_MAX_NAMELEN 128 #define PX_MAX_NAMELEN 128
/* max salt returned */ /* max salt returned */
#define PX_MAX_SALT_LEN 128 #define PX_MAX_SALT_LEN 128
@ -63,79 +62,86 @@ typedef struct px_hmac PX_HMAC;
typedef struct px_cipher PX_Cipher; typedef struct px_cipher PX_Cipher;
typedef struct px_combo PX_Combo; typedef struct px_combo PX_Combo;
struct px_digest { struct px_digest
uint (*result_size)(PX_MD *h); {
uint (*block_size)(PX_MD *h); uint (*result_size) (PX_MD * h);
void (*reset)(PX_MD *h); uint (*block_size) (PX_MD * h);
void (*update)(PX_MD *h, const uint8 *data, uint dlen); void (*reset) (PX_MD * h);
void (*finish)(PX_MD *h, uint8 *dst); void (*update) (PX_MD * h, const uint8 *data, uint dlen);
void (*free)(PX_MD *h); void (*finish) (PX_MD * h, uint8 *dst);
void (*free) (PX_MD * h);
/* private */ /* private */
union { union
uint code; {
uint code;
const void *ptr; const void *ptr;
} p; } p;
}; };
struct px_alias { struct px_alias
char *alias; {
char *name; char *alias;
char *name;
}; };
struct px_hmac { struct px_hmac
uint (*result_size)(PX_HMAC *h); {
uint (*block_size)(PX_HMAC *h); uint (*result_size) (PX_HMAC * h);
void (*reset)(PX_HMAC *h); uint (*block_size) (PX_HMAC * h);
void (*update)(PX_HMAC *h, const uint8 *data, uint dlen); void (*reset) (PX_HMAC * h);
void (*finish)(PX_HMAC *h, uint8 *dst); void (*update) (PX_HMAC * h, const uint8 *data, uint dlen);
void (*free)(PX_HMAC *h); void (*finish) (PX_HMAC * h, uint8 *dst);
void (*init)(PX_HMAC *h, const uint8 *key, uint klen); void (*free) (PX_HMAC * h);
void (*init) (PX_HMAC * h, const uint8 *key, uint klen);
PX_MD *md;
PX_MD *md;
/* private */ /* private */
struct { struct
uint8 *ipad; {
uint8 *opad; uint8 *ipad;
} p; uint8 *opad;
} p;
}; };
struct px_cipher { struct px_cipher
uint (*block_size)(PX_Cipher *c); {
uint (*key_size)(PX_Cipher *c); /* max key len */ uint (*block_size) (PX_Cipher * c);
uint (*iv_size)(PX_Cipher *c); uint (*key_size) (PX_Cipher * c); /* max key len */
uint (*iv_size) (PX_Cipher * c);
int (*init)(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv);
int (*encrypt)(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res); int (*init) (PX_Cipher * c, const uint8 *key, uint klen, const uint8 *iv);
int (*decrypt)(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res); int (*encrypt) (PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res);
void (*free)(PX_Cipher *c); int (*decrypt) (PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res);
void (*free) (PX_Cipher * c);
/* private */ /* private */
void *ptr; void *ptr;
int pstat; /* mcrypt uses it */ int pstat; /* mcrypt uses it */
}; };
struct px_combo { struct px_combo
int (*init)(PX_Combo *cx, const uint8 *key, uint klen, {
const uint8 *iv, uint ivlen); int (*init) (PX_Combo * cx, const uint8 *key, uint klen,
int (*encrypt)(PX_Combo *cx, const uint8 *data, uint dlen, const uint8 *iv, uint ivlen);
uint8 *res, uint *rlen); int (*encrypt) (PX_Combo * cx, const uint8 *data, uint dlen,
int (*decrypt)(PX_Combo *cx, const uint8 *data, uint dlen, uint8 *res, uint *rlen);
uint8 *res, uint *rlen); int (*decrypt) (PX_Combo * cx, const uint8 *data, uint dlen,
uint (*encrypt_len)(PX_Combo *cx, uint dlen); uint8 *res, uint *rlen);
uint (*decrypt_len)(PX_Combo *cx, uint dlen); uint (*encrypt_len) (PX_Combo * cx, uint dlen);
void (*free)(PX_Combo *cx); uint (*decrypt_len) (PX_Combo * cx, uint dlen);
void (*free) (PX_Combo * cx);
PX_Cipher *cipher; PX_Cipher *cipher;
uint padding; uint padding;
}; };
int px_find_digest(const char *name, PX_MD **res); int px_find_digest(const char *name, PX_MD ** res);
int px_find_hmac(const char *name, PX_HMAC **res); int px_find_hmac(const char *name, PX_HMAC ** res);
int px_find_cipher(const char *name, PX_Cipher **res); int px_find_cipher(const char *name, PX_Cipher ** res);
int px_find_combo(const char *name, PX_Combo **res); int px_find_combo(const char *name, PX_Combo ** res);
int px_get_random_bytes(uint8 *dst, unsigned count); int px_get_random_bytes(uint8 *dst, unsigned count);
const char *px_resolve_alias(const PX_Alias *aliases, const char *name); const char *px_resolve_alias(const PX_Alias * aliases, const char *name);
#define px_md_result_size(md) (md)->result_size(md) #define px_md_result_size(md) (md)->result_size(md)
#define px_md_block_size(md) (md)->block_size(md) #define px_md_block_size(md) (md)->block_size(md)
@ -174,6 +180,4 @@ const char *px_resolve_alias(const PX_Alias *aliases, const char *name);
(c)->decrypt(c, data, dlen, res, rlen) (c)->decrypt(c, data, dlen, res, rlen)
#define px_combo_free(c) (c)->free(c) #define px_combo_free(c) (c)->free(c)
#endif /* __PX_H */
#endif /* __PX_H */

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: random.c,v 1.2 2001/09/29 03:12:51 momjian Exp $ * $Id: random.c,v 1.3 2001/10/25 05:49:20 momjian Exp $
*/ */
@ -44,13 +44,15 @@
static int static int
safe_read(int fd, void *buf, size_t count) safe_read(int fd, void *buf, size_t count)
{ {
int done = 0; int done = 0;
char *p = buf; char *p = buf;
int res; int res;
while (count) { while (count)
{
res = read(fd, p, count); res = read(fd, p, count);
if (res <= 0) { if (res <= 0)
{
if (errno == EINTR) if (errno == EINTR)
continue; continue;
return -1; return -1;
@ -65,8 +67,8 @@ safe_read(int fd, void *buf, size_t count)
int int
px_get_random_bytes(uint8 *dst, unsigned count) px_get_random_bytes(uint8 *dst, unsigned count)
{ {
int fd; int fd;
int res; int res;
fd = open(RAND_DEV, O_RDONLY); fd = open(RAND_DEV, O_RDONLY);
if (fd == -1) if (fd == -1)
@ -75,21 +77,20 @@ px_get_random_bytes(uint8 *dst, unsigned count)
close(fd); close(fd);
return res; return res;
} }
#endif /* RAND_DEV */
#endif /* RAND_DEV */
#ifdef RAND_SILLY #ifdef RAND_SILLY
int px_get_random_bytes(uint8 *dst, unsigned count) int
px_get_random_bytes(uint8 *dst, unsigned count)
{ {
int i; int i;
for (i = 0; i < count; i++) {
for (i = 0; i < count; i++)
*dst++ = random(); *dst++ = random();
}
return i; return i;
} }
#endif /* RAND_SILLY */
#endif /* RAND_SILLY */
#ifdef RAND_OPENSSL #ifdef RAND_OPENSSL
@ -98,30 +99,29 @@ int px_get_random_bytes(uint8 *dst, unsigned count)
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/err.h> #include <openssl/err.h>
static int openssl_random_init = 0; static int openssl_random_init = 0;
int px_get_random_bytes(uint8 *dst, unsigned count) int
px_get_random_bytes(uint8 *dst, unsigned count)
{ {
int res; int res;
if (!openssl_random_init) { if (!openssl_random_init)
if (RAND_get_rand_method() == NULL) { {
if (RAND_get_rand_method() == NULL)
RAND_set_rand_method(RAND_SSLeay()); RAND_set_rand_method(RAND_SSLeay());
}
openssl_random_init = 1; openssl_random_init = 1;
} }
/* /*
* OpenSSL random should re-feeded occasionally. * OpenSSL random should re-feeded occasionally. From /dev/urandom
* From /dev/urandom preferrably. * preferrably.
*/ */
res = RAND_bytes(dst, count); res = RAND_bytes(dst, count);
if (res > 0) if (res > 0)
return count; return count;
return -1; return -1;
} }
#endif /* RAND_OPENSSL */
#endif /* RAND_OPENSSL */

View File

@ -1,40 +1,40 @@
/* $OpenBSD: rijndael.c,v 1.6 2000/12/09 18:51:34 markus Exp $ */ /* $OpenBSD: rijndael.c,v 1.6 2000/12/09 18:51:34 markus Exp $ */
/* This is an independent implementation of the encryption algorithm: */ /* This is an independent implementation of the encryption algorithm: */
/* */ /* */
/* RIJNDAEL by Joan Daemen and Vincent Rijmen */ /* RIJNDAEL by Joan Daemen and Vincent Rijmen */
/* */ /* */
/* which is a candidate algorithm in the Advanced Encryption Standard */ /* which is a candidate algorithm in the Advanced Encryption Standard */
/* programme of the US National Institute of Standards and Technology. */ /* programme of the US National Institute of Standards and Technology. */
/* */ /* */
/* Copyright in this implementation is held by Dr B R Gladman but I */ /* Copyright in this implementation is held by Dr B R Gladman but I */
/* hereby give permission for its free direct or derivative use subject */ /* hereby give permission for its free direct or derivative use subject */
/* to acknowledgment of its origin and compliance with any conditions */ /* to acknowledgment of its origin and compliance with any conditions */
/* that the originators of the algorithm place on its exploitation. */ /* that the originators of the algorithm place on its exploitation. */
/* */ /* */
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */ /* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
/* Timing data for Rijndael (rijndael.c) /* Timing data for Rijndael (rijndael.c)
Algorithm: rijndael (rijndael.c) Algorithm: rijndael (rijndael.c)
128 bit key: 128 bit key:
Key Setup: 305/1389 cycles (encrypt/decrypt) Key Setup: 305/1389 cycles (encrypt/decrypt)
Encrypt: 374 cycles = 68.4 mbits/sec Encrypt: 374 cycles = 68.4 mbits/sec
Decrypt: 352 cycles = 72.7 mbits/sec Decrypt: 352 cycles = 72.7 mbits/sec
Mean: 363 cycles = 70.5 mbits/sec Mean: 363 cycles = 70.5 mbits/sec
192 bit key: 192 bit key:
Key Setup: 277/1595 cycles (encrypt/decrypt) Key Setup: 277/1595 cycles (encrypt/decrypt)
Encrypt: 439 cycles = 58.3 mbits/sec Encrypt: 439 cycles = 58.3 mbits/sec
Decrypt: 425 cycles = 60.2 mbits/sec Decrypt: 425 cycles = 60.2 mbits/sec
Mean: 432 cycles = 59.3 mbits/sec Mean: 432 cycles = 59.3 mbits/sec
256 bit key: 256 bit key:
Key Setup: 374/1960 cycles (encrypt/decrypt) Key Setup: 374/1960 cycles (encrypt/decrypt)
Encrypt: 502 cycles = 51.0 mbits/sec Encrypt: 502 cycles = 51.0 mbits/sec
Decrypt: 498 cycles = 51.4 mbits/sec Decrypt: 498 cycles = 51.4 mbits/sec
Mean: 500 cycles = 51.2 mbits/sec Mean: 500 cycles = 51.2 mbits/sec
*/ */
@ -47,29 +47,29 @@ Mean: 500 cycles = 51.2 mbits/sec
static void gen_tabs(void); static void gen_tabs(void);
/* 3. Basic macros for speeding up generic operations */ /* 3. Basic macros for speeding up generic operations */
/* Circular rotate of 32 bit values */ /* Circular rotate of 32 bit values */
#define rotr(x,n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n)))) #define rotr(x,n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n))))
#define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n)))) #define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n))))
/* Invert byte order in a 32 bit variable */ /* Invert byte order in a 32 bit variable */
#define bswap(x) ((rotl(x, 8) & 0x00ff00ff) | (rotr(x, 8) & 0xff00ff00)) #define bswap(x) ((rotl(x, 8) & 0x00ff00ff) | (rotr(x, 8) & 0xff00ff00))
/* Extract byte from a 32 bit quantity (little endian notation) */ /* Extract byte from a 32 bit quantity (little endian notation) */
#define byte(x,n) ((u1byte)((x) >> (8 * n))) #define byte(x,n) ((u1byte)((x) >> (8 * n)))
#if BYTE_ORDER != LITTLE_ENDIAN #if BYTE_ORDER != LITTLE_ENDIAN
#define BYTE_SWAP #define BYTE_SWAP
#endif #endif
#ifdef BYTE_SWAP #ifdef BYTE_SWAP
#define io_swap(x) bswap(x) #define io_swap(x) bswap(x)
#else #else
#define io_swap(x) (x) #define io_swap(x) (x)
#endif #endif
#ifdef PRINT_TABS #ifdef PRINT_TABS
@ -81,279 +81,311 @@ static void gen_tabs(void);
#include "rijndael.tbl" #include "rijndael.tbl"
#define tab_gen 1 #define tab_gen 1
#else /* !PRE_CALC_TABLES */ #else /* !PRE_CALC_TABLES */
static u1byte pow_tab[256]; static u1byte pow_tab[256];
static u1byte log_tab[256]; static u1byte log_tab[256];
static u1byte sbx_tab[256]; static u1byte sbx_tab[256];
static u1byte isb_tab[256]; static u1byte isb_tab[256];
static u4byte rco_tab[ 10]; static u4byte rco_tab[10];
static u4byte ft_tab[4][256]; static u4byte ft_tab[4][256];
static u4byte it_tab[4][256]; static u4byte it_tab[4][256];
#ifdef LARGE_TABLES #ifdef LARGE_TABLES
static u4byte fl_tab[4][256]; static u4byte fl_tab[4][256];
static u4byte il_tab[4][256]; static u4byte il_tab[4][256];
#endif #endif
static u4byte tab_gen = 0; static u4byte tab_gen = 0;
#endif /* !PRE_CALC_TABLES */ #endif /* !PRE_CALC_TABLES */
#define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0) #define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0)
#define f_rn(bo, bi, n, k) \ #define f_rn(bo, bi, n, k) \
bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rn(bo, bi, n, k) \ #define i_rn(bo, bi, n, k) \
bo[n] = it_tab[0][byte(bi[n],0)] ^ \ bo[n] = it_tab[0][byte(bi[n],0)] ^ \
it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
#ifdef LARGE_TABLES #ifdef LARGE_TABLES
#define ls_box(x) \ #define ls_box(x) \
( fl_tab[0][byte(x, 0)] ^ \ ( fl_tab[0][byte(x, 0)] ^ \
fl_tab[1][byte(x, 1)] ^ \ fl_tab[1][byte(x, 1)] ^ \
fl_tab[2][byte(x, 2)] ^ \ fl_tab[2][byte(x, 2)] ^ \
fl_tab[3][byte(x, 3)] ) fl_tab[3][byte(x, 3)] )
#define f_rl(bo, bi, n, k) \ #define f_rl(bo, bi, n, k) \
bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rl(bo, bi, n, k) \ #define i_rl(bo, bi, n, k) \
bo[n] = il_tab[0][byte(bi[n],0)] ^ \ bo[n] = il_tab[0][byte(bi[n],0)] ^ \
il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
#else #else
#define ls_box(x) \ #define ls_box(x) \
((u4byte)sbx_tab[byte(x, 0)] << 0) ^ \ ((u4byte)sbx_tab[byte(x, 0)] << 0) ^ \
((u4byte)sbx_tab[byte(x, 1)] << 8) ^ \ ((u4byte)sbx_tab[byte(x, 1)] << 8) ^ \
((u4byte)sbx_tab[byte(x, 2)] << 16) ^ \ ((u4byte)sbx_tab[byte(x, 2)] << 16) ^ \
((u4byte)sbx_tab[byte(x, 3)] << 24) ((u4byte)sbx_tab[byte(x, 3)] << 24)
#define f_rl(bo, bi, n, k) \ #define f_rl(bo, bi, n, k) \
bo[n] = (u4byte)sbx_tab[byte(bi[n],0)] ^ \ bo[n] = (u4byte)sbx_tab[byte(bi[n],0)] ^ \
rotl(((u4byte)sbx_tab[byte(bi[(n + 1) & 3],1)]), 8) ^ \ rotl(((u4byte)sbx_tab[byte(bi[(n + 1) & 3],1)]), 8) ^ \
rotl(((u4byte)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \ rotl(((u4byte)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \
rotl(((u4byte)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n) rotl(((u4byte)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n)
#define i_rl(bo, bi, n, k) \
bo[n] = (u4byte)isb_tab[byte(bi[n],0)] ^ \
rotl(((u4byte)isb_tab[byte(bi[(n + 3) & 3],1)]), 8) ^ \
rotl(((u4byte)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \
rotl(((u4byte)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n)
#define i_rl(bo, bi, n, k) \
bo[n] = (u4byte)isb_tab[byte(bi[n],0)] ^ \
rotl(((u4byte)isb_tab[byte(bi[(n + 3) & 3],1)]), 8) ^ \
rotl(((u4byte)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \
rotl(((u4byte)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n)
#endif #endif
static void static void
gen_tabs(void) gen_tabs(void)
{ {
#ifndef PRE_CALC_TABLES #ifndef PRE_CALC_TABLES
u4byte i, t; u4byte i,
u1byte p, q; t;
u1byte p,
q;
/* log and power tables for GF(2**8) finite field with */ /* log and power tables for GF(2**8) finite field with */
/* 0x11b as modular polynomial - the simplest prmitive */ /* 0x11b as modular polynomial - the simplest prmitive */
/* root is 0x11, used here to generate the tables */ /* root is 0x11, used here to generate the tables */
for(i = 0,p = 1; i < 256; ++i) { for (i = 0, p = 1; i < 256; ++i)
pow_tab[i] = (u1byte)p; log_tab[p] = (u1byte)i; {
pow_tab[i] = (u1byte) p;
log_tab[p] = (u1byte) i;
p = p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0); p = p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0);
} }
log_tab[1] = 0; p = 1; log_tab[1] = 0;
p = 1;
for(i = 0; i < 10; ++i) { for (i = 0; i < 10; ++i)
rco_tab[i] = p; {
rco_tab[i] = p;
p = (p << 1) ^ (p & 0x80 ? 0x1b : 0); p = (p << 1) ^ (p & 0x80 ? 0x1b : 0);
} }
/* note that the affine byte transformation matrix in */ /* note that the affine byte transformation matrix in */
/* rijndael specification is in big endian format with */ /* rijndael specification is in big endian format with */
/* bit 0 as the most significant bit. In the remainder */ /* bit 0 as the most significant bit. In the remainder */
/* of the specification the bits are numbered from the */ /* of the specification the bits are numbered from the */
/* least significant end of a byte. */ /* least significant end of a byte. */
for(i = 0; i < 256; ++i) { for (i = 0; i < 256; ++i)
p = (i ? pow_tab[255 - log_tab[i]] : 0); q = p; {
q = (q >> 7) | (q << 1); p ^= q; p = (i ? pow_tab[255 - log_tab[i]] : 0);
q = (q >> 7) | (q << 1); p ^= q; q = p;
q = (q >> 7) | (q << 1); p ^= q; q = (q >> 7) | (q << 1);
q = (q >> 7) | (q << 1); p ^= q ^ 0x63; p ^= q;
sbx_tab[i] = (u1byte)p; isb_tab[p] = (u1byte)i; q = (q >> 7) | (q << 1);
p ^= q;
q = (q >> 7) | (q << 1);
p ^= q;
q = (q >> 7) | (q << 1);
p ^= q ^ 0x63;
sbx_tab[i] = (u1byte) p;
isb_tab[p] = (u1byte) i;
} }
for(i = 0; i < 256; ++i) { for (i = 0; i < 256; ++i)
p = sbx_tab[i]; {
p = sbx_tab[i];
#ifdef LARGE_TABLES #ifdef LARGE_TABLES
t = p; fl_tab[0][i] = t; t = p;
fl_tab[1][i] = rotl(t, 8); fl_tab[0][i] = t;
fl_tab[1][i] = rotl(t, 8);
fl_tab[2][i] = rotl(t, 16); fl_tab[2][i] = rotl(t, 16);
fl_tab[3][i] = rotl(t, 24); fl_tab[3][i] = rotl(t, 24);
#endif #endif
t = ((u4byte)ff_mult(2, p)) | t = ((u4byte) ff_mult(2, p)) |
((u4byte)p << 8) | ((u4byte) p << 8) |
((u4byte)p << 16) | ((u4byte) p << 16) |
((u4byte)ff_mult(3, p) << 24); ((u4byte) ff_mult(3, p) << 24);
ft_tab[0][i] = t; ft_tab[0][i] = t;
ft_tab[1][i] = rotl(t, 8); ft_tab[1][i] = rotl(t, 8);
ft_tab[2][i] = rotl(t, 16); ft_tab[2][i] = rotl(t, 16);
ft_tab[3][i] = rotl(t, 24); ft_tab[3][i] = rotl(t, 24);
p = isb_tab[i]; p = isb_tab[i];
#ifdef LARGE_TABLES #ifdef LARGE_TABLES
t = p; il_tab[0][i] = t; t = p;
il_tab[1][i] = rotl(t, 8); il_tab[0][i] = t;
il_tab[2][i] = rotl(t, 16); il_tab[1][i] = rotl(t, 8);
il_tab[2][i] = rotl(t, 16);
il_tab[3][i] = rotl(t, 24); il_tab[3][i] = rotl(t, 24);
#endif #endif
t = ((u4byte)ff_mult(14, p)) | t = ((u4byte) ff_mult(14, p)) |
((u4byte)ff_mult( 9, p) << 8) | ((u4byte) ff_mult(9, p) << 8) |
((u4byte)ff_mult(13, p) << 16) | ((u4byte) ff_mult(13, p) << 16) |
((u4byte)ff_mult(11, p) << 24); ((u4byte) ff_mult(11, p) << 24);
it_tab[0][i] = t; it_tab[0][i] = t;
it_tab[1][i] = rotl(t, 8); it_tab[1][i] = rotl(t, 8);
it_tab[2][i] = rotl(t, 16); it_tab[2][i] = rotl(t, 16);
it_tab[3][i] = rotl(t, 24); it_tab[3][i] = rotl(t, 24);
} }
tab_gen = 1; tab_gen = 1;
#endif /* !PRE_CALC_TABLES */ #endif /* !PRE_CALC_TABLES */
} }
#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) #define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
#define imix_col(y,x) \ #define imix_col(y,x) \
u = star_x(x); \ u = star_x(x); \
v = star_x(u); \ v = star_x(u); \
w = star_x(v); \ w = star_x(v); \
t = w ^ (x); \ t = w ^ (x); \
(y) = u ^ v ^ w; \ (y) = u ^ v ^ w; \
(y) ^= rotr(u ^ t, 8) ^ \ (y) ^= rotr(u ^ t, 8) ^ \
rotr(v ^ t, 16) ^ \ rotr(v ^ t, 16) ^ \
rotr(t,24) rotr(t,24)
/* initialise the key schedule from the user supplied key */ /* initialise the key schedule from the user supplied key */
#define loop4(i) \ #define loop4(i) \
do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
t ^= e_key[4 * i]; e_key[4 * i + 4] = t; \ t ^= e_key[4 * i]; e_key[4 * i + 4] = t; \
t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t; \ t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t; \
t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t; \ t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t; \
t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t; \ t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t; \
} while (0) } while (0)
#define loop6(i) \ #define loop6(i) \
do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
t ^= e_key[6 * i]; e_key[6 * i + 6] = t; \ t ^= e_key[6 * i]; e_key[6 * i + 6] = t; \
t ^= e_key[6 * i + 1]; e_key[6 * i + 7] = t; \ t ^= e_key[6 * i + 1]; e_key[6 * i + 7] = t; \
t ^= e_key[6 * i + 2]; e_key[6 * i + 8] = t; \ t ^= e_key[6 * i + 2]; e_key[6 * i + 8] = t; \
t ^= e_key[6 * i + 3]; e_key[6 * i + 9] = t; \ t ^= e_key[6 * i + 3]; e_key[6 * i + 9] = t; \
t ^= e_key[6 * i + 4]; e_key[6 * i + 10] = t; \ t ^= e_key[6 * i + 4]; e_key[6 * i + 10] = t; \
t ^= e_key[6 * i + 5]; e_key[6 * i + 11] = t; \ t ^= e_key[6 * i + 5]; e_key[6 * i + 11] = t; \
} while (0) } while (0)
#define loop8(i) \ #define loop8(i) \
do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ do { t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
t ^= e_key[8 * i]; e_key[8 * i + 8] = t; \ t ^= e_key[8 * i]; e_key[8 * i + 8] = t; \
t ^= e_key[8 * i + 1]; e_key[8 * i + 9] = t; \ t ^= e_key[8 * i + 1]; e_key[8 * i + 9] = t; \
t ^= e_key[8 * i + 2]; e_key[8 * i + 10] = t; \ t ^= e_key[8 * i + 2]; e_key[8 * i + 10] = t; \
t ^= e_key[8 * i + 3]; e_key[8 * i + 11] = t; \ t ^= e_key[8 * i + 3]; e_key[8 * i + 11] = t; \
t = e_key[8 * i + 4] ^ ls_box(t); \ t = e_key[8 * i + 4] ^ ls_box(t); \
e_key[8 * i + 12] = t; \ e_key[8 * i + 12] = t; \
t ^= e_key[8 * i + 5]; e_key[8 * i + 13] = t; \ t ^= e_key[8 * i + 5]; e_key[8 * i + 13] = t; \
t ^= e_key[8 * i + 6]; e_key[8 * i + 14] = t; \ t ^= e_key[8 * i + 6]; e_key[8 * i + 14] = t; \
t ^= e_key[8 * i + 7]; e_key[8 * i + 15] = t; \ t ^= e_key[8 * i + 7]; e_key[8 * i + 15] = t; \
} while (0) } while (0)
rijndael_ctx * rijndael_ctx *
rijndael_set_key(rijndael_ctx *ctx, const u4byte *in_key, const u4byte key_len, rijndael_set_key(rijndael_ctx * ctx, const u4byte * in_key, const u4byte key_len,
int encrypt) int encrypt)
{ {
u4byte i, t, u, v, w; u4byte i,
u4byte *e_key = ctx->e_key; t,
u4byte *d_key = ctx->d_key; u,
v,
w;
u4byte *e_key = ctx->e_key;
u4byte *d_key = ctx->d_key;
ctx->decrypt = !encrypt; ctx->decrypt = !encrypt;
if(!tab_gen) if (!tab_gen)
gen_tabs(); gen_tabs();
ctx->k_len = (key_len + 31) / 32; ctx->k_len = (key_len + 31) / 32;
e_key[0] = io_swap(in_key[0]); e_key[1] = io_swap(in_key[1]); e_key[0] = io_swap(in_key[0]);
e_key[2] = io_swap(in_key[2]); e_key[3] = io_swap(in_key[3]); e_key[1] = io_swap(in_key[1]);
e_key[2] = io_swap(in_key[2]);
switch(ctx->k_len) { e_key[3] = io_swap(in_key[3]);
case 4: t = e_key[3];
for(i = 0; i < 10; ++i)
loop4(i);
break;
case 6: e_key[4] = io_swap(in_key[4]); t = e_key[5] = io_swap(in_key[5]); switch (ctx->k_len)
for(i = 0; i < 8; ++i) {
loop6(i); case 4:
break; t = e_key[3];
for (i = 0; i < 10; ++i)
loop4(i);
break;
case 8: e_key[4] = io_swap(in_key[4]); e_key[5] = io_swap(in_key[5]); case 6:
e_key[6] = io_swap(in_key[6]); t = e_key[7] = io_swap(in_key[7]); e_key[4] = io_swap(in_key[4]);
for(i = 0; i < 7; ++i) t = e_key[5] = io_swap(in_key[5]);
loop8(i); for (i = 0; i < 8; ++i)
break; loop6(i);
break;
case 8:
e_key[4] = io_swap(in_key[4]);
e_key[5] = io_swap(in_key[5]);
e_key[6] = io_swap(in_key[6]);
t = e_key[7] = io_swap(in_key[7]);
for (i = 0; i < 7; ++i)
loop8(i);
break;
} }
if (!encrypt) { if (!encrypt)
d_key[0] = e_key[0]; d_key[1] = e_key[1]; {
d_key[2] = e_key[2]; d_key[3] = e_key[3]; d_key[0] = e_key[0];
d_key[1] = e_key[1];
d_key[2] = e_key[2];
d_key[3] = e_key[3];
for(i = 4; i < 4 * ctx->k_len + 24; ++i) { for (i = 4; i < 4 * ctx->k_len + 24; ++i)
imix_col(d_key[i], e_key[i]); imix_col(d_key[i], e_key[i]);
}
} }
return ctx; return ctx;
} }
/* encrypt a block of text */ /* encrypt a block of text */
#define f_nround(bo, bi, k) \ #define f_nround(bo, bi, k) \
f_rn(bo, bi, 0, k); \ f_rn(bo, bi, 0, k); \
f_rn(bo, bi, 1, k); \ f_rn(bo, bi, 1, k); \
f_rn(bo, bi, 2, k); \ f_rn(bo, bi, 2, k); \
f_rn(bo, bi, 3, k); \ f_rn(bo, bi, 3, k); \
k += 4 k += 4
#define f_lround(bo, bi, k) \ #define f_lround(bo, bi, k) \
f_rl(bo, bi, 0, k); \ f_rl(bo, bi, 0, k); \
f_rl(bo, bi, 1, k); \ f_rl(bo, bi, 1, k); \
f_rl(bo, bi, 2, k); \ f_rl(bo, bi, 2, k); \
f_rl(bo, bi, 3, k) f_rl(bo, bi, 3, k)
void void
rijndael_encrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk) rijndael_encrypt(rijndael_ctx * ctx, const u4byte * in_blk, u4byte * out_blk)
{ {
u4byte k_len = ctx->k_len; u4byte k_len = ctx->k_len;
u4byte *e_key = ctx->e_key; u4byte *e_key = ctx->e_key;
u4byte b0[4], b1[4], *kp; u4byte b0[4],
b1[4],
*kp;
b0[0] = io_swap(in_blk[0]) ^ e_key[0]; b0[0] = io_swap(in_blk[0]) ^ e_key[0];
b0[1] = io_swap(in_blk[1]) ^ e_key[1]; b0[1] = io_swap(in_blk[1]) ^ e_key[1];
@ -362,46 +394,59 @@ rijndael_encrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk)
kp = e_key + 4; kp = e_key + 4;
if(k_len > 6) { if (k_len > 6)
f_nround(b1, b0, kp); f_nround(b0, b1, kp); {
f_nround(b1, b0, kp);
f_nround(b0, b1, kp);
} }
if(k_len > 4) { if (k_len > 4)
f_nround(b1, b0, kp); f_nround(b0, b1, kp); {
f_nround(b1, b0, kp);
f_nround(b0, b1, kp);
} }
f_nround(b1, b0, kp); f_nround(b0, b1, kp); f_nround(b1, b0, kp);
f_nround(b1, b0, kp); f_nround(b0, b1, kp); f_nround(b0, b1, kp);
f_nround(b1, b0, kp); f_nround(b0, b1, kp); f_nround(b1, b0, kp);
f_nround(b1, b0, kp); f_nround(b0, b1, kp); f_nround(b0, b1, kp);
f_nround(b1, b0, kp); f_lround(b0, b1, kp); f_nround(b1, b0, kp);
f_nround(b0, b1, kp);
f_nround(b1, b0, kp);
f_nround(b0, b1, kp);
f_nround(b1, b0, kp);
f_lround(b0, b1, kp);
out_blk[0] = io_swap(b0[0]); out_blk[1] = io_swap(b0[1]); out_blk[0] = io_swap(b0[0]);
out_blk[2] = io_swap(b0[2]); out_blk[3] = io_swap(b0[3]); out_blk[1] = io_swap(b0[1]);
out_blk[2] = io_swap(b0[2]);
out_blk[3] = io_swap(b0[3]);
} }
/* decrypt a block of text */ /* decrypt a block of text */
#define i_nround(bo, bi, k) \ #define i_nround(bo, bi, k) \
i_rn(bo, bi, 0, k); \ i_rn(bo, bi, 0, k); \
i_rn(bo, bi, 1, k); \ i_rn(bo, bi, 1, k); \
i_rn(bo, bi, 2, k); \ i_rn(bo, bi, 2, k); \
i_rn(bo, bi, 3, k); \ i_rn(bo, bi, 3, k); \
k -= 4 k -= 4
#define i_lround(bo, bi, k) \ #define i_lround(bo, bi, k) \
i_rl(bo, bi, 0, k); \ i_rl(bo, bi, 0, k); \
i_rl(bo, bi, 1, k); \ i_rl(bo, bi, 1, k); \
i_rl(bo, bi, 2, k); \ i_rl(bo, bi, 2, k); \
i_rl(bo, bi, 3, k) i_rl(bo, bi, 3, k)
void void
rijndael_decrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk) rijndael_decrypt(rijndael_ctx * ctx, const u4byte * in_blk, u4byte * out_blk)
{ {
u4byte b0[4], b1[4], *kp; u4byte b0[4],
u4byte k_len = ctx->k_len; b1[4],
u4byte *e_key = ctx->e_key; *kp;
u4byte *d_key = ctx->d_key; u4byte k_len = ctx->k_len;
u4byte *e_key = ctx->e_key;
u4byte *d_key = ctx->d_key;
b0[0] = io_swap(in_blk[0]) ^ e_key[4 * k_len + 24]; b0[0] = io_swap(in_blk[0]) ^ e_key[4 * k_len + 24];
b0[1] = io_swap(in_blk[1]) ^ e_key[4 * k_len + 25]; b0[1] = io_swap(in_blk[1]) ^ e_key[4 * k_len + 25];
@ -410,22 +455,33 @@ rijndael_decrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk)
kp = d_key + 4 * (k_len + 5); kp = d_key + 4 * (k_len + 5);
if(k_len > 6) { if (k_len > 6)
i_nround(b1, b0, kp); i_nround(b0, b1, kp); {
i_nround(b1, b0, kp);
i_nround(b0, b1, kp);
} }
if(k_len > 4) { if (k_len > 4)
i_nround(b1, b0, kp); i_nround(b0, b1, kp); {
i_nround(b1, b0, kp);
i_nround(b0, b1, kp);
} }
i_nround(b1, b0, kp); i_nround(b0, b1, kp); i_nround(b1, b0, kp);
i_nround(b1, b0, kp); i_nround(b0, b1, kp); i_nround(b0, b1, kp);
i_nround(b1, b0, kp); i_nround(b0, b1, kp); i_nround(b1, b0, kp);
i_nround(b1, b0, kp); i_nround(b0, b1, kp); i_nround(b0, b1, kp);
i_nround(b1, b0, kp); i_lround(b0, b1, kp); i_nround(b1, b0, kp);
i_nround(b0, b1, kp);
i_nround(b1, b0, kp);
i_nround(b0, b1, kp);
i_nround(b1, b0, kp);
i_lround(b0, b1, kp);
out_blk[0] = io_swap(b0[0]); out_blk[1] = io_swap(b0[1]); out_blk[0] = io_swap(b0[0]);
out_blk[2] = io_swap(b0[2]); out_blk[3] = io_swap(b0[3]); out_blk[1] = io_swap(b0[1]);
out_blk[2] = io_swap(b0[2]);
out_blk[3] = io_swap(b0[3]);
} }
/* /*
@ -435,19 +491,24 @@ rijndael_decrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk)
* should be true for PX. -marko * should be true for PX. -marko
*/ */
void aes_set_key(rijndael_ctx * ctx, const uint8 *key, uint keybits, int enc) void
aes_set_key(rijndael_ctx * ctx, const uint8 *key, uint keybits, int enc)
{ {
uint32 *k; uint32 *k;
k = (uint32*)key;
k = (uint32 *) key;
rijndael_set_key(ctx, k, keybits, enc); rijndael_set_key(ctx, k, keybits, enc);
} }
void aes_ecb_encrypt(rijndael_ctx *ctx, uint8 *data, unsigned len) void
aes_ecb_encrypt(rijndael_ctx * ctx, uint8 *data, unsigned len)
{ {
unsigned bs = 16; unsigned bs = 16;
uint32 *d; uint32 *d;
while (len >= bs) {
d = (uint32*)data; while (len >= bs)
{
d = (uint32 *) data;
rijndael_encrypt(ctx, d, d); rijndael_encrypt(ctx, d, d);
len -= bs; len -= bs;
@ -455,12 +516,15 @@ void aes_ecb_encrypt(rijndael_ctx *ctx, uint8 *data, unsigned len)
} }
} }
void aes_ecb_decrypt(rijndael_ctx *ctx, uint8 *data, unsigned len) void
aes_ecb_decrypt(rijndael_ctx * ctx, uint8 *data, unsigned len)
{ {
unsigned bs = 16; unsigned bs = 16;
uint32 *d; uint32 *d;
while (len >= bs) {
d = (uint32*)data; while (len >= bs)
{
d = (uint32 *) data;
rijndael_decrypt(ctx, d, d); rijndael_decrypt(ctx, d, d);
len -= bs; len -= bs;
@ -468,42 +532,55 @@ void aes_ecb_decrypt(rijndael_ctx *ctx, uint8 *data, unsigned len)
} }
} }
void aes_cbc_encrypt(rijndael_ctx *ctx, uint8 *iva, uint8 *data, unsigned len) void
aes_cbc_encrypt(rijndael_ctx * ctx, uint8 *iva, uint8 *data, unsigned len)
{ {
uint32 *iv = (uint32 *)iva; uint32 *iv = (uint32 *) iva;
uint32 *d = (uint32 *)data; uint32 *d = (uint32 *) data;
unsigned bs = 16; unsigned bs = 16;
while (len >= bs)
{
d[0] ^= iv[0];
d[1] ^= iv[1];
d[2] ^= iv[2];
d[3] ^= iv[3];
while (len >= bs) {
d[0] ^= iv[0]; d[1] ^= iv[1];
d[2] ^= iv[2]; d[3] ^= iv[3];
rijndael_encrypt(ctx, d, d); rijndael_encrypt(ctx, d, d);
iv = d; iv = d;
d += bs/4; d += bs / 4;
len -= bs; len -= bs;
} }
} }
void aes_cbc_decrypt(rijndael_ctx *ctx, uint8 *iva, uint8 *data, unsigned len) void
aes_cbc_decrypt(rijndael_ctx * ctx, uint8 *iva, uint8 *data, unsigned len)
{ {
uint32 *d = (uint32 *)data; uint32 *d = (uint32 *) data;
unsigned bs = 16; unsigned bs = 16;
uint32 buf[4], iv[4]; uint32 buf[4],
iv[4];
memcpy(iv, iva, bs); memcpy(iv, iva, bs);
while (len >= bs) { while (len >= bs)
buf[0] = d[0]; buf[1] = d[1]; {
buf[2] = d[2]; buf[3] = d[3]; buf[0] = d[0];
buf[1] = d[1];
buf[2] = d[2];
buf[3] = d[3];
rijndael_decrypt(ctx, buf, d); rijndael_decrypt(ctx, buf, d);
d[0] ^= iv[0]; d[1] ^= iv[1]; d[0] ^= iv[0];
d[2] ^= iv[2]; d[3] ^= iv[3]; d[1] ^= iv[1];
d[2] ^= iv[2];
iv[0] = buf[0]; iv[1] = buf[1]; d[3] ^= iv[3];
iv[2] = buf[2]; iv[3] = buf[3];
iv[0] = buf[0];
iv[1] = buf[1];
iv[2] = buf[2];
iv[3] = buf[3];
d += 4; d += 4;
len -= bs; len -= bs;
} }
@ -514,15 +591,18 @@ void aes_cbc_decrypt(rijndael_ctx *ctx, uint8 *iva, uint8 *data, unsigned len)
* *
* On i386 lifts 17k from .bss to .rodata * On i386 lifts 17k from .bss to .rodata
* and avoids 1k code and setup time. * and avoids 1k code and setup time.
* -marko * -marko
*/ */
#ifdef PRINT_TABS #ifdef PRINT_TABS
static void show256u8(char *name, uint8 *data) static void
show256u8(char *name, uint8 *data)
{ {
int i; int i;
printf("static const u1byte %s[256] = {\n ", name); printf("static const u1byte %s[256] = {\n ", name);
for (i = 0; i < 256; ) { for (i = 0; i < 256;)
{
printf("%u", pow_tab[i++]); printf("%u", pow_tab[i++]);
if (i < 256) if (i < 256)
printf(i % 16 ? ", " : ",\n "); printf(i % 16 ? ", " : ",\n ");
@ -531,12 +611,17 @@ static void show256u8(char *name, uint8 *data)
} }
static void show4x256u32(char *name, uint32 data[4][256]) static void
show4x256u32(char *name, uint32 data[4][256])
{ {
int i, j; int i,
j;
printf("static const u4byte %s[4][256] = {\n{\n ", name); printf("static const u4byte %s[4][256] = {\n{\n ", name);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++)
for (j = 0; j < 256; ) { {
for (j = 0; j < 256;)
{
printf("0x%08x", data[i][j]); printf("0x%08x", data[i][j]);
j++; j++;
if (j < 256) if (j < 256)
@ -547,11 +632,12 @@ static void show4x256u32(char *name, uint32 data[4][256])
printf("};\n\n"); printf("};\n\n");
} }
int main() int
main()
{ {
int i; int i;
char *hdr = "/* Generated by rijndael.c */\n\n"; char *hdr = "/* Generated by rijndael.c */\n\n";
gen_tabs(); gen_tabs();
printf(hdr); printf(hdr);
@ -559,7 +645,7 @@ int main()
show256u8("log_tab", log_tab); show256u8("log_tab", log_tab);
show256u8("sbx_tab", sbx_tab); show256u8("sbx_tab", sbx_tab);
show256u8("isb_tab", isb_tab); show256u8("isb_tab", isb_tab);
show4x256u32("ft_tab", ft_tab); show4x256u32("ft_tab", ft_tab);
show4x256u32("it_tab", it_tab); show4x256u32("it_tab", it_tab);
#ifdef LARGE_TABLES #ifdef LARGE_TABLES
@ -567,14 +653,15 @@ int main()
show4x256u32("il_tab", il_tab); show4x256u32("il_tab", il_tab);
#endif #endif
printf("static const u4byte rco_tab[10] = {\n "); printf("static const u4byte rco_tab[10] = {\n ");
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++)
{
printf("0x%08x", rco_tab[i]); printf("0x%08x", rco_tab[i]);
if (i < 9) printf(", "); if (i < 9)
if (i == 4) printf("\n "); printf(", ");
if (i == 4)
printf("\n ");
} }
printf("\n};\n\n"); printf("\n};\n\n");
return 0; return 0;
} }
#endif #endif

View File

@ -1,57 +1,57 @@
/* $OpenBSD: rijndael.h,v 1.3 2001/05/09 23:01:32 markus Exp $ */ /* $OpenBSD: rijndael.h,v 1.3 2001/05/09 23:01:32 markus Exp $ */
/* This is an independent implementation of the encryption algorithm: */ /* This is an independent implementation of the encryption algorithm: */
/* */ /* */
/* RIJNDAEL by Joan Daemen and Vincent Rijmen */ /* RIJNDAEL by Joan Daemen and Vincent Rijmen */
/* */ /* */
/* which is a candidate algorithm in the Advanced Encryption Standard */ /* which is a candidate algorithm in the Advanced Encryption Standard */
/* programme of the US National Institute of Standards and Technology. */ /* programme of the US National Institute of Standards and Technology. */
/* */ /* */
/* Copyright in this implementation is held by Dr B R Gladman but I */ /* Copyright in this implementation is held by Dr B R Gladman but I */
/* hereby give permission for its free direct or derivative use subject */ /* hereby give permission for its free direct or derivative use subject */
/* to acknowledgment of its origin and compliance with any conditions */ /* to acknowledgment of its origin and compliance with any conditions */
/* that the originators of the algorithm place on its exploitation. */ /* that the originators of the algorithm place on its exploitation. */
/* */ /* */
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */ /* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
#ifndef _RIJNDAEL_H_ #ifndef _RIJNDAEL_H_
#define _RIJNDAEL_H_ #define _RIJNDAEL_H_
/* 1. Standard types for AES cryptography source code */ /* 1. Standard types for AES cryptography source code */
typedef uint8 u1byte; /* an 8 bit unsigned character type */ typedef uint8 u1byte; /* an 8 bit unsigned character type */
typedef uint16 u2byte; /* a 16 bit unsigned integer type */ typedef uint16 u2byte; /* a 16 bit unsigned integer type */
typedef uint32 u4byte; /* a 32 bit unsigned integer type */ typedef uint32 u4byte; /* a 32 bit unsigned integer type */
typedef int8 s1byte; /* an 8 bit signed character type */ typedef int8 s1byte; /* an 8 bit signed character type */
typedef int16 s2byte; /* a 16 bit signed integer type */ typedef int16 s2byte; /* a 16 bit signed integer type */
typedef int32 s4byte; /* a 32 bit signed integer type */ typedef int32 s4byte; /* a 32 bit signed integer type */
typedef struct _rijndael_ctx { typedef struct _rijndael_ctx
u4byte k_len; {
int decrypt; u4byte k_len;
u4byte e_key[64]; int decrypt;
u4byte d_key[64]; u4byte e_key[64];
} rijndael_ctx; u4byte d_key[64];
} rijndael_ctx;
/* 2. Standard interface for AES cryptographic routines */ /* 2. Standard interface for AES cryptographic routines */
/* These are all based on 32 bit unsigned values and will therefore */ /* These are all based on 32 bit unsigned values and will therefore */
/* require endian conversions for big-endian architectures */ /* require endian conversions for big-endian architectures */
rijndael_ctx * rijndael_ctx *
rijndael_set_key (rijndael_ctx *, const u4byte *, const u4byte, int); rijndael_set_key(rijndael_ctx *, const u4byte *, const u4byte, int);
void rijndael_encrypt (rijndael_ctx *, const u4byte *, u4byte *); void rijndael_encrypt(rijndael_ctx *, const u4byte *, u4byte *);
void rijndael_decrypt (rijndael_ctx *, const u4byte *, u4byte *); void rijndael_decrypt(rijndael_ctx *, const u4byte *, u4byte *);
/* conventional interface */ /* conventional interface */
void aes_set_key(rijndael_ctx * ctx, const uint8 *key, uint keybits, int enc); void aes_set_key(rijndael_ctx * ctx, const uint8 *key, uint keybits, int enc);
void aes_ecb_encrypt(rijndael_ctx *ctx, uint8 *data, unsigned len); void aes_ecb_encrypt(rijndael_ctx * ctx, uint8 *data, unsigned len);
void aes_ecb_decrypt(rijndael_ctx *ctx, uint8 *data, unsigned len); void aes_ecb_decrypt(rijndael_ctx * ctx, uint8 *data, unsigned len);
void aes_cbc_encrypt(rijndael_ctx *ctx, uint8 *iva, uint8 *data, unsigned len); void aes_cbc_encrypt(rijndael_ctx * ctx, uint8 *iva, uint8 *data, unsigned len);
void aes_cbc_decrypt(rijndael_ctx *ctx, uint8 *iva, uint8 *data, unsigned len); void aes_cbc_decrypt(rijndael_ctx * ctx, uint8 *iva, uint8 *data, unsigned len);
#endif /* _RIJNDAEL_H_ */
#endif /* _RIJNDAEL_H_ */

View File

@ -1,4 +1,4 @@
/* $Id: sha1.c,v 1.7 2001/10/25 01:29:37 momjian Exp $ */ /* $Id: sha1.c,v 1.8 2001/10/25 05:49:20 momjian Exp $ */
/* $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $ */ /* $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $ */
/* /*
@ -87,7 +87,7 @@ do { \
static void sha1_step(struct sha1_ctxt *); static void sha1_step(struct sha1_ctxt *);
static void static void
sha1_step(struct sha1_ctxt *ctxt) sha1_step(struct sha1_ctxt * ctxt)
{ {
uint32 a, uint32 a,
b, b,
@ -232,7 +232,7 @@ sha1_step(struct sha1_ctxt *ctxt)
/*------------------------------------------------------------*/ /*------------------------------------------------------------*/
void void
sha1_init(struct sha1_ctxt *ctxt) sha1_init(struct sha1_ctxt * ctxt)
{ {
bzero(ctxt, sizeof(struct sha1_ctxt)); bzero(ctxt, sizeof(struct sha1_ctxt));
H(0) = 0x67452301; H(0) = 0x67452301;
@ -243,7 +243,7 @@ sha1_init(struct sha1_ctxt *ctxt)
} }
void void
sha1_pad(struct sha1_ctxt *ctxt) sha1_pad(struct sha1_ctxt * ctxt)
{ {
size_t padlen; /* pad length in bytes */ size_t padlen; /* pad length in bytes */
size_t padstart; size_t padstart;
@ -286,7 +286,7 @@ sha1_pad(struct sha1_ctxt *ctxt)
} }
void void
sha1_loop(struct sha1_ctxt *ctxt, const uint8 *input0, size_t len) sha1_loop(struct sha1_ctxt * ctxt, const uint8 *input0, size_t len)
{ {
const uint8 *input; const uint8 *input;
size_t gaplen; size_t gaplen;
@ -314,7 +314,7 @@ sha1_loop(struct sha1_ctxt *ctxt, const uint8 *input0, size_t len)
} }
void void
sha1_result(struct sha1_ctxt *ctxt, uint8 *digest0) sha1_result(struct sha1_ctxt * ctxt, uint8 *digest0)
{ {
uint8 *digest; uint8 *digest;

View File

@ -1,4 +1,4 @@
/* $Id: sha1.h,v 1.5 2001/08/21 00:42:41 momjian Exp $ */ /* $Id: sha1.h,v 1.6 2001/10/25 05:49:20 momjian Exp $ */
/* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */ /* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */
/* /*
@ -71,5 +71,4 @@ typedef struct sha1_ctxt SHA1_CTX;
#define SHA1Final(x, y) sha1_result((y), (x)) #define SHA1Final(x, y) sha1_result((y), (x))
#define SHA1_RESULTLEN (160/8) #define SHA1_RESULTLEN (160/8)
#endif /* _NETINET6_SHA1_H_ */ #endif /* _NETINET6_SHA1_H_ */

View File

@ -1,5 +1,5 @@
/* /*
* $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.1 2001/10/01 01:52:38 ishii Exp $ * $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.2 2001/10/25 05:49:20 momjian Exp $
* *
* Copyright (c) 2001 Tatsuo Ishii * Copyright (c) 2001 Tatsuo Ishii
* *
@ -42,90 +42,91 @@ extern Datum pgstattuple(PG_FUNCTION_ARGS);
Datum Datum
pgstattuple(PG_FUNCTION_ARGS) pgstattuple(PG_FUNCTION_ARGS)
{ {
Name p = PG_GETARG_NAME(0); Name p = PG_GETARG_NAME(0);
Relation rel; Relation rel;
HeapScanDesc scan; HeapScanDesc scan;
HeapTuple tuple; HeapTuple tuple;
BlockNumber nblocks; BlockNumber nblocks;
BlockNumber block = InvalidBlockNumber; BlockNumber block = InvalidBlockNumber;
double table_len; double table_len;
uint64 tuple_len = 0; uint64 tuple_len = 0;
uint64 dead_tuple_len = 0; uint64 dead_tuple_len = 0;
uint32 tuple_count = 0; uint32 tuple_count = 0;
uint32 dead_tuple_count = 0; uint32 dead_tuple_count = 0;
double tuple_percent; double tuple_percent;
double dead_tuple_percent; double dead_tuple_percent;
Buffer buffer = InvalidBuffer; Buffer buffer = InvalidBuffer;
uint64 free_space = 0; /* free/reusable space in bytes */ uint64 free_space = 0; /* free/reusable space in bytes */
double free_percent; /* free/reusable space in % */ double free_percent; /* free/reusable space in % */
rel = heap_openr(NameStr(*p), NoLock); rel = heap_openr(NameStr(*p), NoLock);
nblocks = RelationGetNumberOfBlocks(rel); nblocks = RelationGetNumberOfBlocks(rel);
scan = heap_beginscan(rel, false, SnapshotAny, 0, NULL); scan = heap_beginscan(rel, false, SnapshotAny, 0, NULL);
while ((tuple = heap_getnext(scan,0))) while ((tuple = heap_getnext(scan, 0)))
{
if (HeapTupleSatisfiesNow(tuple->t_data))
{ {
tuple_len += tuple->t_len; if (HeapTupleSatisfiesNow(tuple->t_data))
tuple_count++; {
tuple_len += tuple->t_len;
tuple_count++;
}
else
{
dead_tuple_len += tuple->t_len;
dead_tuple_count++;
}
if (!BlockNumberIsValid(block) ||
block != BlockIdGetBlockNumber(&tuple->t_self.ip_blkid))
{
block = BlockIdGetBlockNumber(&tuple->t_self.ip_blkid);
buffer = ReadBuffer(rel, block);
free_space += PageGetFreeSpace((Page) BufferGetPage(buffer));
ReleaseBuffer(buffer);
}
}
heap_endscan(scan);
heap_close(rel, NoLock);
table_len = (double) nblocks *BLCKSZ;
if (nblocks == 0)
{
tuple_percent = 0.0;
dead_tuple_percent = 0.0;
free_percent = 0.0;
} }
else else
{ {
dead_tuple_len += tuple->t_len; tuple_percent = (double) tuple_len *100.0 / table_len;
dead_tuple_count++; dead_tuple_percent = (double) dead_tuple_len *100.0 / table_len;
free_percent = (double) free_space *100.0 / table_len;
} }
if (!BlockNumberIsValid(block) || elog(NOTICE, "physical length: %.2fMB live tuples: %u (%.2fMB, %.2f%%) dead tuples: %u (%.2fMB, %.2f%%) free/reusable space: %.2fMB (%.2f%%) overhead: %.2f%%",
block != BlockIdGetBlockNumber(&tuple->t_self.ip_blkid))
{
block = BlockIdGetBlockNumber(&tuple->t_self.ip_blkid);
buffer = ReadBuffer(rel, block);
free_space += PageGetFreeSpace((Page)BufferGetPage(buffer));
ReleaseBuffer(buffer);
}
}
heap_endscan(scan);
heap_close(rel, NoLock);
table_len = (double)nblocks*BLCKSZ; table_len / 1024 / 1024, /* phsical length in MB */
if (nblocks == 0) tuple_count, /* number of live tuples */
{ (double) tuple_len / 1024 / 1024, /* live tuples in MB */
tuple_percent = 0.0; tuple_percent, /* live tuples in % */
dead_tuple_percent = 0.0;
free_percent = 0.0;
}
else
{
tuple_percent = (double)tuple_len*100.0/table_len;
dead_tuple_percent = (double)dead_tuple_len*100.0/table_len;
free_percent = (double)free_space*100.0/table_len;
}
elog(NOTICE,"physical length: %.2fMB live tuples: %u (%.2fMB, %.2f%%) dead tuples: %u (%.2fMB, %.2f%%) free/reusable space: %.2fMB (%.2f%%) overhead: %.2f%%", dead_tuple_count, /* number of dead tuples */
(double) dead_tuple_len / 1024 / 1024, /* dead tuples in MB */
dead_tuple_percent, /* dead tuples in % */
table_len/1024/1024, /* phsical length in MB */ (double) free_space / 1024 / 1024, /* free/available space in
* MB */
tuple_count, /* number of live tuples */ free_percent, /* free/available space in % */
(double)tuple_len/1024/1024, /* live tuples in MB */
tuple_percent, /* live tuples in % */
dead_tuple_count, /* number of dead tuples */ /* overhead in % */
(double)dead_tuple_len/1024/1024, /* dead tuples in MB */ (nblocks == 0) ? 0.0 : 100.0
dead_tuple_percent, /* dead tuples in % */ - tuple_percent
- dead_tuple_percent
- free_percent);
(double)free_space/1024/1024, /* free/available space in MB */ PG_RETURN_FLOAT8(dead_tuple_percent);
free_percent, /* free/available space in % */
/* overhead in % */
(nblocks == 0)?0.0: 100.0
- tuple_percent
- dead_tuple_percent
- free_percent);
PG_RETURN_FLOAT8(dead_tuple_percent);
} }

View File

@ -24,7 +24,6 @@ Datum _rserv_debug_(PG_FUNCTION_ARGS);
HeapTuple _rserv_log_(void); HeapTuple _rserv_log_(void);
int32 _rserv_sync_(int32); int32 _rserv_sync_(int32);
int32 _rserv_debug_(int32); int32 _rserv_debug_(int32);
#endif #endif
static int debug = 0; static int debug = 0;
@ -44,7 +43,7 @@ _rserv_log_()
char **args; /* argument: argnum */ char **args; /* argument: argnum */
Relation rel; /* triggered relation */ Relation rel; /* triggered relation */
HeapTuple tuple; /* tuple to return */ HeapTuple tuple; /* tuple to return */
HeapTuple newtuple = NULL;/* tuple to return */ HeapTuple newtuple = NULL; /* tuple to return */
TupleDesc tupdesc; /* tuple description */ TupleDesc tupdesc; /* tuple description */
int keynum; int keynum;
char *key; char *key;
@ -88,6 +87,7 @@ _rserv_log_()
newtuple = CurrentTriggerData->tg_newtuple; newtuple = CurrentTriggerData->tg_newtuple;
#ifndef PG_FUNCTION_INFO_V1 #ifndef PG_FUNCTION_INFO_V1
/* /*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger * Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called * functions in queries. Normally, trigger functions have to be called
@ -207,7 +207,6 @@ _rserv_sync_(int32 server)
{ {
#ifdef PG_FUNCTION_INFO_V1 #ifdef PG_FUNCTION_INFO_V1
int32 server = PG_GETARG_INT32(0); int32 server = PG_GETARG_INT32(0);
#endif #endif
char sql[8192]; char sql[8192];
char buf[8192]; char buf[8192];
@ -253,7 +252,6 @@ _rserv_debug_(int32 newval)
{ {
#ifdef PG_FUNCTION_INFO_V1 #ifdef PG_FUNCTION_INFO_V1
int32 newval = PG_GETARG_INT32(0); int32 newval = PG_GETARG_INT32(0);
#endif #endif
int32 oldval = debug; int32 oldval = debug;

View File

@ -1,13 +1,13 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* rtree_gist.c * rtree_gist.c
* pg_amproc entries for GiSTs over 2-D boxes. * pg_amproc entries for GiSTs over 2-D boxes.
* This gives R-tree behavior, with Guttman's poly-time split algorithm. * This gives R-tree behavior, with Guttman's poly-time split algorithm.
* *
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/contrib/rtree_gist/Attic/rtree_gist.c,v 1.3 2001/10/01 17:53:11 tgl Exp $ * $Header: /cvsroot/pgsql/contrib/rtree_gist/Attic/rtree_gist.c,v 1.4 2001/10/25 05:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -20,9 +20,9 @@
#include "utils/geo_decls.h" #include "utils/geo_decls.h"
#include "utils/elog.h" #include "utils/elog.h"
typedef Datum (*RDF)(PG_FUNCTION_ARGS); typedef Datum (*RDF) (PG_FUNCTION_ARGS);
typedef Datum (*BINARY_UNION)(Datum, Datum, int*); typedef Datum (*BINARY_UNION) (Datum, Datum, int *);
typedef float (*SIZE_BOX)(Datum); typedef float (*SIZE_BOX) (Datum);
/* /*
** box ops ** box ops
@ -34,24 +34,24 @@ PG_FUNCTION_INFO_V1(gbox_consistent);
PG_FUNCTION_INFO_V1(gbox_penalty); PG_FUNCTION_INFO_V1(gbox_penalty);
PG_FUNCTION_INFO_V1(gbox_same); PG_FUNCTION_INFO_V1(gbox_same);
Datum gbox_compress(PG_FUNCTION_ARGS); Datum gbox_compress(PG_FUNCTION_ARGS);
Datum gbox_union(PG_FUNCTION_ARGS); Datum gbox_union(PG_FUNCTION_ARGS);
Datum gbox_picksplit(PG_FUNCTION_ARGS); Datum gbox_picksplit(PG_FUNCTION_ARGS);
Datum gbox_consistent(PG_FUNCTION_ARGS); Datum gbox_consistent(PG_FUNCTION_ARGS);
Datum gbox_penalty(PG_FUNCTION_ARGS); Datum gbox_penalty(PG_FUNCTION_ARGS);
Datum gbox_same(PG_FUNCTION_ARGS); Datum gbox_same(PG_FUNCTION_ARGS);
static bool gbox_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy); static bool gbox_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy);
static float size_box( Datum box ); static float size_box(Datum box);
/* /*
** Polygon ops ** Polygon ops
*/ */
PG_FUNCTION_INFO_V1(gpoly_compress); PG_FUNCTION_INFO_V1(gpoly_compress);
PG_FUNCTION_INFO_V1(gpoly_consistent); PG_FUNCTION_INFO_V1(gpoly_consistent);
Datum gpoly_compress(PG_FUNCTION_ARGS); Datum gpoly_compress(PG_FUNCTION_ARGS);
Datum gpoly_consistent(PG_FUNCTION_ARGS); Datum gpoly_consistent(PG_FUNCTION_ARGS);
/* /*
** Common rtree-function (for all ops) ** Common rtree-function (for all ops)
@ -60,7 +60,7 @@ static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strat
PG_FUNCTION_INFO_V1(rtree_decompress); PG_FUNCTION_INFO_V1(rtree_decompress);
Datum rtree_decompress(PG_FUNCTION_ARGS); Datum rtree_decompress(PG_FUNCTION_ARGS);
/************************************************** /**************************************************
* Box ops * Box ops
@ -75,21 +75,21 @@ Datum rtree_decompress(PG_FUNCTION_ARGS);
Datum Datum
gbox_consistent(PG_FUNCTION_ARGS) gbox_consistent(PG_FUNCTION_ARGS)
{ {
GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0); GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
BOX *query = (BOX*) PG_GETARG_POINTER(1); BOX *query = (BOX *) PG_GETARG_POINTER(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* /*
** if entry is not leaf, use gbox_internal_consistent, * * if entry is not leaf, use gbox_internal_consistent, * else use
** else use gbox_leaf_consistent * gbox_leaf_consistent
*/ */
if ( ! (DatumGetPointer(entry->key) != NULL && query) ) if (!(DatumGetPointer(entry->key) != NULL && query))
PG_RETURN_BOOL(FALSE); PG_RETURN_BOOL(FALSE);
if (GIST_LEAF(entry)) if (GIST_LEAF(entry))
PG_RETURN_BOOL(gbox_leaf_consistent((BOX *) DatumGetPointer(entry->key), query, strategy)); PG_RETURN_BOOL(gbox_leaf_consistent((BOX *) DatumGetPointer(entry->key), query, strategy));
else else
PG_RETURN_BOOL(rtree_internal_consistent((BOX *) DatumGetPointer(entry->key), query, strategy)); PG_RETURN_BOOL(rtree_internal_consistent((BOX *) DatumGetPointer(entry->key), query, strategy));
} }
@ -100,30 +100,33 @@ gbox_consistent(PG_FUNCTION_ARGS)
Datum Datum
gbox_union(PG_FUNCTION_ARGS) gbox_union(PG_FUNCTION_ARGS)
{ {
bytea *entryvec = (bytea*) PG_GETARG_POINTER(0); bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
int *sizep = (int*) PG_GETARG_POINTER(1); int *sizep = (int *) PG_GETARG_POINTER(1);
int numranges, i; int numranges,
BOX *cur, *pageunion; i;
BOX *cur,
*pageunion;
numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY); numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
pageunion = (BOX *)palloc( sizeof(BOX) ); pageunion = (BOX *) palloc(sizeof(BOX));
cur = DatumGetBoxP( ((GISTENTRY *) VARDATA(entryvec))[0].key ); cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[0].key);
memcpy( (void*)pageunion, (void*)cur, sizeof( BOX ) ); memcpy((void *) pageunion, (void *) cur, sizeof(BOX));
for (i = 1; i < numranges; i++) {
cur = DatumGetBoxP( ((GISTENTRY *) VARDATA(entryvec))[i].key );
if ( pageunion->high.x < cur->high.x )
pageunion->high.x = cur->high.x;
if ( pageunion->low.x > cur->low.x )
pageunion->low.x = cur->low.x;
if ( pageunion->high.y < cur->high.y )
pageunion->high.y = cur->high.y;
if ( pageunion->low.y > cur->low.y )
pageunion->low.y = cur->low.y;
}
*sizep = sizeof(BOX);
PG_RETURN_POINTER(pageunion); for (i = 1; i < numranges; i++)
{
cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[i].key);
if (pageunion->high.x < cur->high.x)
pageunion->high.x = cur->high.x;
if (pageunion->low.x > cur->low.x)
pageunion->low.x = cur->low.x;
if (pageunion->high.y < cur->high.y)
pageunion->high.y = cur->high.y;
if (pageunion->low.y > cur->low.y)
pageunion->low.y = cur->low.y;
}
*sizep = sizeof(BOX);
PG_RETURN_POINTER(pageunion);
} }
/* /*
@ -143,18 +146,19 @@ gbox_compress(PG_FUNCTION_ARGS)
Datum Datum
gbox_penalty(PG_FUNCTION_ARGS) gbox_penalty(PG_FUNCTION_ARGS)
{ {
GISTENTRY *origentry = (GISTENTRY*) PG_GETARG_POINTER(0); GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *newentry = (GISTENTRY*) PG_GETARG_POINTER(1); GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
float *result = (float*) PG_GETARG_POINTER(2); float *result = (float *) PG_GETARG_POINTER(2);
Datum ud; Datum ud;
float tmp1; float tmp1;
ud = DirectFunctionCall2(rt_box_union, origentry->key, newentry->key);
tmp1 = size_box( ud );
if (DatumGetPointer(ud) != NULL) pfree(DatumGetPointer(ud));
*result = tmp1 - size_box( origentry->key ); ud = DirectFunctionCall2(rt_box_union, origentry->key, newentry->key);
PG_RETURN_POINTER(result); tmp1 = size_box(ud);
if (DatumGetPointer(ud) != NULL)
pfree(DatumGetPointer(ud));
*result = tmp1 - size_box(origentry->key);
PG_RETURN_POINTER(result);
} }
/* /*
@ -165,145 +169,183 @@ gbox_penalty(PG_FUNCTION_ARGS)
Datum Datum
gbox_picksplit(PG_FUNCTION_ARGS) gbox_picksplit(PG_FUNCTION_ARGS)
{ {
bytea *entryvec = (bytea*)PG_GETARG_POINTER(0); bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC*)PG_GETARG_POINTER(1); GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
OffsetNumber i; OffsetNumber i;
OffsetNumber *listL, *listR, *listB, *listT; OffsetNumber *listL,
BOX *unionL,*unionR,*unionB,*unionT; *listR,
int posL, posR, posB, posT; *listB,
BOX pageunion; *listT;
BOX *cur; BOX *unionL,
char direction=' '; *unionR,
bool allisequal=true; *unionB,
OffsetNumber maxoff; *unionT;
int nbytes; int posL,
posR,
posB,
posT;
BOX pageunion;
BOX *cur;
char direction = ' ';
bool allisequal = true;
OffsetNumber maxoff;
int nbytes;
posL = posR = posB = posT = 0; posL = posR = posB = posT = 0;
maxoff = ((VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY)) - 1; maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 1;
cur = DatumGetBoxP( ((GISTENTRY *) VARDATA(entryvec))[FirstOffsetNumber].key );
memcpy( (void*)&pageunion, (void*)cur, sizeof( BOX ) );
/* find MBR */
for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i)) {
cur = DatumGetBoxP( ((GISTENTRY *) VARDATA(entryvec))[i].key );
if ( pageunion.high.x < cur->high.x )
{ allisequal=false; pageunion.high.x = cur->high.x; }
if ( pageunion.low.x > cur->low.x )
{ allisequal=false; pageunion.low.x = cur->low.x; }
if ( pageunion.high.y < cur->high.y )
{ allisequal=false; pageunion.high.y = cur->high.y; }
if ( pageunion.low.y > cur->low.y )
{ allisequal=false; pageunion.low.y = cur->low.y; }
}
nbytes = (maxoff + 2) * sizeof(OffsetNumber); cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[FirstOffsetNumber].key);
listL = (OffsetNumber*)palloc( nbytes ); memcpy((void *) &pageunion, (void *) cur, sizeof(BOX));
listR = (OffsetNumber*)palloc( nbytes );
unionL = (BOX*)palloc( sizeof(BOX) ); /* find MBR */
unionR = (BOX*)palloc( sizeof(BOX) ); for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i))
if ( allisequal ) { {
cur = DatumGetBoxP( ((GISTENTRY *) VARDATA(entryvec))[OffsetNumberNext(FirstOffsetNumber)].key ); cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[i].key);
if ( memcmp( (void*)cur, (void*)&pageunion, sizeof( BOX ) ) == 0 ) { if (pageunion.high.x < cur->high.x)
v->spl_left = listL; {
v->spl_right = listR; allisequal = false;
v->spl_nleft = v->spl_nright = 0; pageunion.high.x = cur->high.x;
memcpy( (void*)unionL, (void*)&pageunion, sizeof( BOX ) ); }
memcpy( (void*)unionR, (void*)&pageunion, sizeof( BOX ) ); if (pageunion.low.x > cur->low.x)
{
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { allisequal = false;
if (i <= (maxoff - FirstOffsetNumber + 1)/2) { pageunion.low.x = cur->low.x;
v->spl_left[ v->spl_nleft ] = i; }
v->spl_nleft++; if (pageunion.high.y < cur->high.y)
} else { {
v->spl_right[ v->spl_nright ] = i; allisequal = false;
v->spl_nright++; pageunion.high.y = cur->high.y;
} }
if (pageunion.low.y > cur->low.y)
{
allisequal = false;
pageunion.low.y = cur->low.y;
} }
v->spl_ldatum = BoxPGetDatum( unionL );
v->spl_rdatum = BoxPGetDatum( unionR );
PG_RETURN_POINTER( v );
} }
}
listB = (OffsetNumber*)palloc( nbytes ); nbytes = (maxoff + 2) * sizeof(OffsetNumber);
listT = (OffsetNumber*)palloc( nbytes ); listL = (OffsetNumber *) palloc(nbytes);
unionB = (BOX*)palloc( sizeof(BOX) ); listR = (OffsetNumber *) palloc(nbytes);
unionT = (BOX*)palloc( sizeof(BOX) ); unionL = (BOX *) palloc(sizeof(BOX));
unionR = (BOX *) palloc(sizeof(BOX));
if (allisequal)
{
cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[OffsetNumberNext(FirstOffsetNumber)].key);
if (memcmp((void *) cur, (void *) &pageunion, sizeof(BOX)) == 0)
{
v->spl_left = listL;
v->spl_right = listR;
v->spl_nleft = v->spl_nright = 0;
memcpy((void *) unionL, (void *) &pageunion, sizeof(BOX));
memcpy((void *) unionR, (void *) &pageunion, sizeof(BOX));
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
{
v->spl_left[v->spl_nleft] = i;
v->spl_nleft++;
}
else
{
v->spl_right[v->spl_nright] = i;
v->spl_nright++;
}
}
v->spl_ldatum = BoxPGetDatum(unionL);
v->spl_rdatum = BoxPGetDatum(unionR);
PG_RETURN_POINTER(v);
}
}
listB = (OffsetNumber *) palloc(nbytes);
listT = (OffsetNumber *) palloc(nbytes);
unionB = (BOX *) palloc(sizeof(BOX));
unionT = (BOX *) palloc(sizeof(BOX));
#define ADDLIST( list, unionD, pos ) do { \ #define ADDLIST( list, unionD, pos ) do { \
if ( pos ) { \ if ( pos ) { \
if ( unionD->high.x < cur->high.x ) unionD->high.x = cur->high.x; \ if ( unionD->high.x < cur->high.x ) unionD->high.x = cur->high.x; \
if ( unionD->low.x > cur->low.x ) unionD->low.x = cur->low.x; \ if ( unionD->low.x > cur->low.x ) unionD->low.x = cur->low.x; \
if ( unionD->high.y < cur->high.y ) unionD->high.y = cur->high.y; \ if ( unionD->high.y < cur->high.y ) unionD->high.y = cur->high.y; \
if ( unionD->low.y > cur->low.y ) unionD->low.y = cur->low.y; \ if ( unionD->low.y > cur->low.y ) unionD->low.y = cur->low.y; \
} else { \ } else { \
memcpy( (void*)unionD, (void*) cur, sizeof( BOX ) ); \ memcpy( (void*)unionD, (void*) cur, sizeof( BOX ) ); \
} \ } \
list[pos] = i; \ list[pos] = i; \
(pos)++; \ (pos)++; \
} while(0) } while(0)
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
cur = DatumGetBoxP( ((GISTENTRY *) VARDATA(entryvec))[i].key ); {
if ( cur->low.x - pageunion.low.x < pageunion.high.x - cur->high.x ) cur = DatumGetBoxP(((GISTENTRY *) VARDATA(entryvec))[i].key);
ADDLIST( listL, unionL, posL ); if (cur->low.x - pageunion.low.x < pageunion.high.x - cur->high.x)
else ADDLIST(listL, unionL, posL);
ADDLIST( listR, unionR, posR ); else
if ( cur->low.y - pageunion.low.y < pageunion.high.y - cur->high.y ) ADDLIST(listR, unionR, posR);
ADDLIST( listB, unionB, posB ); if (cur->low.y - pageunion.low.y < pageunion.high.y - cur->high.y)
else ADDLIST(listB, unionB, posB);
ADDLIST( listT, unionT, posT ); else
} ADDLIST(listT, unionT, posT);
/* which split more optimal? */
if ( Max( posL, posR ) < Max( posB, posT ) ) {
direction = 'x';
} else if ( Max( posL, posR ) > Max( posB, posT ) ) {
direction = 'y';
} else {
Datum interLR = DirectFunctionCall2(rt_box_inter,
BoxPGetDatum(unionL),
BoxPGetDatum(unionR));
Datum interBT = DirectFunctionCall2(rt_box_inter,
BoxPGetDatum(unionB),
BoxPGetDatum(unionT));
float sizeLR, sizeBT;
sizeLR = size_box( interLR );
sizeBT = size_box( interBT );
if ( sizeLR < sizeBT )
direction = 'x';
else
direction = 'y';
} }
if ( direction == 'x' ) { /* which split more optimal? */
pfree( unionB ); pfree( listB );
pfree( unionT ); pfree( listT );
v->spl_left = listL; if (Max(posL, posR) < Max(posB, posT))
v->spl_right = listR; direction = 'x';
v->spl_nleft = posL; else if (Max(posL, posR) > Max(posB, posT))
v->spl_nright = posR; direction = 'y';
v->spl_ldatum = BoxPGetDatum( unionL ); else
v->spl_rdatum = BoxPGetDatum( unionR ); {
} else { Datum interLR = DirectFunctionCall2(rt_box_inter,
pfree( unionR ); pfree( listR ); BoxPGetDatum(unionL),
pfree( unionL ); pfree( listL ); BoxPGetDatum(unionR));
Datum interBT = DirectFunctionCall2(rt_box_inter,
BoxPGetDatum(unionB),
BoxPGetDatum(unionT));
float sizeLR,
sizeBT;
v->spl_left = listB; sizeLR = size_box(interLR);
v->spl_right = listT; sizeBT = size_box(interBT);
v->spl_nleft = posB;
v->spl_nright = posT;
v->spl_ldatum = BoxPGetDatum( unionB );
v->spl_rdatum = BoxPGetDatum( unionT );
}
PG_RETURN_POINTER (v); if (sizeLR < sizeBT)
direction = 'x';
else
direction = 'y';
}
if (direction == 'x')
{
pfree(unionB);
pfree(listB);
pfree(unionT);
pfree(listT);
v->spl_left = listL;
v->spl_right = listR;
v->spl_nleft = posL;
v->spl_nright = posR;
v->spl_ldatum = BoxPGetDatum(unionL);
v->spl_rdatum = BoxPGetDatum(unionR);
}
else
{
pfree(unionR);
pfree(listR);
pfree(unionL);
pfree(listL);
v->spl_left = listB;
v->spl_right = listT;
v->spl_nleft = posB;
v->spl_nright = posT;
v->spl_ldatum = BoxPGetDatum(unionB);
v->spl_rdatum = BoxPGetDatum(unionT);
}
PG_RETURN_POINTER(v);
} }
/* /*
@ -312,66 +354,71 @@ gbox_picksplit(PG_FUNCTION_ARGS)
Datum Datum
gbox_same(PG_FUNCTION_ARGS) gbox_same(PG_FUNCTION_ARGS)
{ {
BOX *b1 = (BOX*) PG_GETARG_POINTER(0); BOX *b1 = (BOX *) PG_GETARG_POINTER(0);
BOX *b2 = (BOX*) PG_GETARG_POINTER(1); BOX *b2 = (BOX *) PG_GETARG_POINTER(1);
bool *result = (bool*) PG_GETARG_POINTER(2); bool *result = (bool *) PG_GETARG_POINTER(2);
if ( b1 && b2 )
*result = DatumGetBool( DirectFunctionCall2( box_same, PointerGetDatum(b1), PointerGetDatum(b2)) ); if (b1 && b2)
else *result = DatumGetBool(DirectFunctionCall2(box_same, PointerGetDatum(b1), PointerGetDatum(b2)));
*result = ( b1==NULL && b2==NULL ) ? TRUE : FALSE; else
PG_RETURN_POINTER(result); *result = (b1 == NULL && b2 == NULL) ? TRUE : FALSE;
PG_RETURN_POINTER(result);
} }
/* /*
** SUPPORT ROUTINES for boxes ** SUPPORT ROUTINES for boxes
*/ */
static bool static bool
gbox_leaf_consistent(BOX *key, gbox_leaf_consistent(BOX *key,
BOX *query, BOX *query,
StrategyNumber strategy) StrategyNumber strategy)
{ {
bool retval; bool retval;
switch(strategy) { switch (strategy)
case RTLeftStrategyNumber: {
retval = DatumGetBool( DirectFunctionCall2( box_left, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTLeftStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_left, PointerGetDatum(key), PointerGetDatum(query)));
case RTOverLeftStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_overleft, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTOverLeftStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_overleft, PointerGetDatum(key), PointerGetDatum(query)));
case RTOverlapStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_overlap, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTOverlapStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query)));
case RTOverRightStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_overright, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTOverRightStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_overright, PointerGetDatum(key), PointerGetDatum(query)));
case RTRightStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_right, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTRightStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_right, PointerGetDatum(key), PointerGetDatum(query)));
case RTSameStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_same, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTSameStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_same, PointerGetDatum(key), PointerGetDatum(query)));
case RTContainsStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_contain, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTContainsStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_contain, PointerGetDatum(key), PointerGetDatum(query)));
case RTContainedByStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_contained, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTContainedByStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_contained, PointerGetDatum(key), PointerGetDatum(query)));
default: break;
retval = FALSE; default:
} retval = FALSE;
return(retval); }
return (retval);
} }
static float static float
size_box( Datum box ) { size_box(Datum box)
if ( DatumGetPointer(box) != NULL ) { {
float size; if (DatumGetPointer(box) != NULL)
{
float size;
DirectFunctionCall2( rt_box_size, DirectFunctionCall2(rt_box_size,
box, PointerGetDatum( &size ) ); box, PointerGetDatum(&size));
return size; return size;
} else }
else
return 0.0; return 0.0;
} }
@ -382,91 +429,97 @@ size_box( Datum box ) {
Datum Datum
gpoly_compress(PG_FUNCTION_ARGS) gpoly_compress(PG_FUNCTION_ARGS)
{ {
GISTENTRY *entry=(GISTENTRY*)PG_GETARG_POINTER(0); GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *retval; GISTENTRY *retval;
if ( entry->leafkey) { if (entry->leafkey)
{
retval = palloc(sizeof(GISTENTRY)); retval = palloc(sizeof(GISTENTRY));
if ( DatumGetPointer(entry->key) != NULL ) { if (DatumGetPointer(entry->key) != NULL)
POLYGON *in; {
BOX *r; POLYGON *in;
BOX *r;
in = (POLYGON *) PG_DETOAST_DATUM(entry->key); in = (POLYGON *) PG_DETOAST_DATUM(entry->key);
r = (BOX *) palloc( sizeof(BOX) ); r = (BOX *) palloc(sizeof(BOX));
memcpy( (void*)r, (void*)&(in->boundbox), sizeof(BOX) ); memcpy((void *) r, (void *) &(in->boundbox), sizeof(BOX));
if ( in != (POLYGON *) DatumGetPointer(entry->key) ) if (in != (POLYGON *) DatumGetPointer(entry->key))
pfree( in ); pfree(in);
gistentryinit(*retval, PointerGetDatum(r), gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, sizeof(BOX), FALSE); entry->offset, sizeof(BOX), FALSE);
} else { }
else
{
gistentryinit(*retval, (Datum) 0, gistentryinit(*retval, (Datum) 0,
entry->rel, entry->page, entry->rel, entry->page,
entry->offset, 0,FALSE); entry->offset, 0, FALSE);
} }
} else {
retval = entry;
} }
PG_RETURN_POINTER( retval ); else
retval = entry;
PG_RETURN_POINTER(retval);
} }
Datum Datum
gpoly_consistent(PG_FUNCTION_ARGS) gpoly_consistent(PG_FUNCTION_ARGS)
{ {
GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0); GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
POLYGON *query = (POLYGON*)PG_DETOAST_DATUM( PG_GETARG_POINTER(1) ); POLYGON *query = (POLYGON *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
bool result; bool result;
/* /*
** if entry is not leaf, use gbox_internal_consistent, * * if entry is not leaf, use gbox_internal_consistent, * else use
** else use gbox_leaf_consistent * gbox_leaf_consistent
*/ */
if ( ! (DatumGetPointer(entry->key) != NULL && query) ) if (!(DatumGetPointer(entry->key) != NULL && query))
PG_RETURN_BOOL(FALSE); PG_RETURN_BOOL(FALSE);
result = rtree_internal_consistent((BOX *) DatumGetPointer(entry->key), result = rtree_internal_consistent((BOX *) DatumGetPointer(entry->key),
&(query->boundbox), strategy); &(query->boundbox), strategy);
PG_FREE_IF_COPY(query,1); PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL( result ); PG_RETURN_BOOL(result);
} }
/***************************************** /*****************************************
* Common rtree-function (for all ops) * Common rtree-function (for all ops)
*****************************************/ *****************************************/
static bool static bool
rtree_internal_consistent(BOX *key, rtree_internal_consistent(BOX *key,
BOX *query, BOX *query,
StrategyNumber strategy) StrategyNumber strategy)
{ {
bool retval; bool retval;
switch(strategy) { switch (strategy)
case RTLeftStrategyNumber: {
case RTOverLeftStrategyNumber: case RTLeftStrategyNumber:
retval = DatumGetBool( DirectFunctionCall2( box_overleft, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTOverLeftStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_overleft, PointerGetDatum(key), PointerGetDatum(query)));
case RTOverlapStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_overlap, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTOverlapStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query)));
case RTOverRightStrategyNumber: break;
case RTRightStrategyNumber: case RTOverRightStrategyNumber:
retval = DatumGetBool( DirectFunctionCall2( box_right, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTRightStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_right, PointerGetDatum(key), PointerGetDatum(query)));
case RTSameStrategyNumber: break;
case RTContainsStrategyNumber: case RTSameStrategyNumber:
retval = DatumGetBool( DirectFunctionCall2( box_contain, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTContainsStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_contain, PointerGetDatum(key), PointerGetDatum(query)));
case RTContainedByStrategyNumber: break;
retval = DatumGetBool( DirectFunctionCall2( box_overlap, PointerGetDatum(key), PointerGetDatum(query) ) ); case RTContainedByStrategyNumber:
break; retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query)));
default: break;
retval = FALSE; default:
} retval = FALSE;
return(retval); }
return (retval);
} }
/* /*

View File

@ -138,7 +138,6 @@ seg_out(SEG * seg)
if (seg->lower == seg->upper && seg->l_ext == seg->u_ext) if (seg->lower == seg->upper && seg->l_ext == seg->u_ext)
{ {
/* /*
* indicates that this interval was built by seg_in off a single * indicates that this interval was built by seg_in off a single
* point * point
@ -219,7 +218,6 @@ gseg_consistent(GISTENTRY *entry,
SEG * query, SEG * query,
StrategyNumber strategy) StrategyNumber strategy)
{ {
/* /*
* * if entry is not leaf, use gseg_internal_consistent, * else use * * if entry is not leaf, use gseg_internal_consistent, * else use
* gseg_leaf_consistent * gseg_leaf_consistent
@ -253,7 +251,7 @@ gseg_union(bytea *entryvec, int *sizep)
for (i = 1; i < numranges; i++) for (i = 1; i < numranges; i++)
{ {
out = gseg_binary_union(tmp, (SEG *) out = gseg_binary_union(tmp, (SEG *)
DatumGetPointer(((GISTENTRY *) VARDATA(entryvec))[i].key), DatumGetPointer(((GISTENTRY *) VARDATA(entryvec))[i].key),
sizep); sizep);
if (i > 1) if (i > 1)
pfree(tmp); pfree(tmp);
@ -267,13 +265,13 @@ gseg_union(bytea *entryvec, int *sizep)
** GiST Compress and Decompress methods for segments ** GiST Compress and Decompress methods for segments
** do not do anything. ** do not do anything.
*/ */
GISTENTRY * GISTENTRY *
gseg_compress(GISTENTRY *entry) gseg_compress(GISTENTRY *entry)
{ {
return (entry); return (entry);
} }
GISTENTRY * GISTENTRY *
gseg_decompress(GISTENTRY *entry) gseg_decompress(GISTENTRY *entry)
{ {
return (entry); return (entry);
@ -415,7 +413,6 @@ gseg_picksplit(bytea *entryvec,
maxoff = OffsetNumberNext(maxoff); maxoff = OffsetNumberNext(maxoff);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{ {
/* /*
* If we've already decided where to place this item, just put it * If we've already decided where to place this item, just put it
* on the right list. Otherwise, we need to figure out which page * on the right list. Otherwise, we need to figure out which page
@ -614,7 +611,7 @@ seg_overlap(SEG * a, SEG * b)
((a->upper >= b->upper) && (a->lower <= b->upper)) ((a->upper >= b->upper) && (a->lower <= b->upper))
|| ||
((b->upper >= a->upper) && (b->lower <= a->upper)) ((b->upper >= a->upper) && (b->lower <= a->upper))
); );
} }
/* seg_overleft -- is the right edge of (a) located to the left of the right edge of (b)? /* seg_overleft -- is the right edge of (a) located to the left of the right edge of (b)?
@ -757,7 +754,6 @@ seg_size(SEG * a)
int32 int32
seg_cmp(SEG * a, SEG * b) seg_cmp(SEG * a, SEG * b)
{ {
/* /*
* First compare on lower boundary position * First compare on lower boundary position
*/ */
@ -968,7 +964,6 @@ restore(char *result, float val, int n)
{ {
if (abs(exp) <= 4) if (abs(exp) <= 4)
{ {
/* /*
* remove the decimal point from the mantyssa and write the * remove the decimal point from the mantyssa and write the
* digits to the buf array * digits to the buf array
@ -989,7 +984,6 @@ restore(char *result, float val, int n)
{ {
if (dp - 10 + exp >= n) if (dp - 10 + exp >= n)
{ {
/* /*
* the decimal point is behind the last significant * the decimal point is behind the last significant
* digit; the digits in between must be converted to * digit; the digits in between must be converted to

View File

@ -52,7 +52,7 @@ check_primary_key(PG_FUNCTION_ARGS)
HeapTuple tuple = NULL; /* tuple to return */ HeapTuple tuple = NULL; /* tuple to return */
TupleDesc tupdesc; /* tuple description */ TupleDesc tupdesc; /* tuple description */
EPlan *plan; /* prepared plan */ EPlan *plan; /* prepared plan */
Oid *argtypes = NULL;/* key types to prepare execution plan */ Oid *argtypes = NULL; /* key types to prepare execution plan */
bool isnull; /* to know is some column NULL or not */ bool isnull; /* to know is some column NULL or not */
char ident[2 * NAMEDATALEN]; /* to identify myself */ char ident[2 * NAMEDATALEN]; /* to identify myself */
int ret; int ret;
@ -235,10 +235,10 @@ check_foreign_key(PG_FUNCTION_ARGS)
char *relname; /* referencing relation name */ char *relname; /* referencing relation name */
Relation rel; /* triggered relation */ Relation rel; /* triggered relation */
HeapTuple trigtuple = NULL; /* tuple to being changed */ HeapTuple trigtuple = NULL; /* tuple to being changed */
HeapTuple newtuple = NULL;/* tuple to return */ HeapTuple newtuple = NULL; /* tuple to return */
TupleDesc tupdesc; /* tuple description */ TupleDesc tupdesc; /* tuple description */
EPlan *plan; /* prepared plan(s) */ EPlan *plan; /* prepared plan(s) */
Oid *argtypes = NULL;/* key types to prepare execution plan */ Oid *argtypes = NULL; /* key types to prepare execution plan */
bool isnull; /* to know is some column NULL or not */ bool isnull; /* to know is some column NULL or not */
bool isequal = true; /* are keys in both tuples equal (in bool isequal = true; /* are keys in both tuples equal (in
* UPDATE) */ * UPDATE) */
@ -402,11 +402,11 @@ check_foreign_key(PG_FUNCTION_ARGS)
/*--------- /*---------
* For 'R'estrict action we construct SELECT query: * For 'R'estrict action we construct SELECT query:
* *
* SELECT 1 * SELECT 1
* FROM _referencing_relation_ * FROM _referencing_relation_
* WHERE Fkey1 = $1 [AND Fkey2 = $2 [...]] * WHERE Fkey1 = $1 [AND Fkey2 = $2 [...]]
* *
* to check is tuple referenced or not. * to check is tuple referenced or not.
*--------- *---------
*/ */
if (action == 'r') if (action == 'r')
@ -537,7 +537,6 @@ check_foreign_key(PG_FUNCTION_ARGS)
*/ */
for (r = 0; r < nrefs; r++) for (r = 0; r < nrefs; r++)
{ {
/* /*
* For 'R'estrict we may to execute plan for one tuple only, for * For 'R'estrict we may to execute plan for one tuple only, for
* other actions - for all tuples. * other actions - for all tuples.

View File

@ -359,7 +359,6 @@ c_charin(unsigned char *str)
{ {
return (string_input(str, 1, 0, NULL)); return (string_input(str, 1, 0, NULL));
} }
#endif #endif
/* end of file */ /* end of file */

View File

@ -13,7 +13,6 @@ struct varlena *c_textin(unsigned char *str);
int32 * int32 *
c_charin(unsigned char *str) c_charin(unsigned char *str)
#endif #endif
#endif #endif
/* /*

View File

@ -87,15 +87,17 @@ static const unsigned int crc32tab[256] = {
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
}; };
unsigned int crc32_sz(char * buf, int size){ unsigned int
crc32_sz(char *buf, int size)
{
unsigned int crc = ~0; unsigned int crc = ~0;
char *p ; char *p;
int len, nr; int len,
nr;
len = 0 ; len = 0;
nr=size; nr = size;
for (len += nr, p = buf; nr--; ++p) { for (len += nr, p = buf; nr--; ++p)
_CRC32_(crc, *p) ; _CRC32_(crc, *p);
}
return ~crc; return ~crc;
} }

View File

@ -2,9 +2,8 @@
#define _CRC32_H #define _CRC32_H
/* Returns crc32 of data block */ /* Returns crc32 of data block */
extern unsigned int crc32_sz(char * buf, int size); extern unsigned int crc32_sz(char *buf, int size);
/* Returns crc32 of null-terminated string */ /* Returns crc32 of null-terminated string */
#define crc32(buf) crc32_sz((buf),strlen(buf)) #define crc32(buf) crc32_sz((buf),strlen(buf))
#endif #endif

View File

@ -12,12 +12,12 @@
#define HOST 6 #define HOST 6
#define FLOAT 7 #define FLOAT 7
#define FINT 8 #define FINT 8
#define PARTWORD 9 #define PARTWORD 9
#define NONLATINPARTWORD 10 #define NONLATINPARTWORD 10
#define LATPARTWORD 11 #define LATPARTWORD 11
#define SPACE 12 #define SPACE 12
#define SYMTAG 13 #define SYMTAG 13
#define HTTP 14 #define HTTP 14
#define DEFISWORD 15 #define DEFISWORD 15
#define DEFISLATWORD 16 #define DEFISLATWORD 16
#define DEFISNONLATINWORD 17 #define DEFISNONLATINWORD 17
@ -25,6 +25,4 @@
#define FILEPATH 19 #define FILEPATH 19
extern const char *descr[]; extern const char *descr[];
#endif #endif

View File

@ -9,7 +9,8 @@
* signature defines * signature defines
*/ */
#define BITBYTE 8 #define BITBYTE 8
#define SIGLENINT 64 /* >121 => key will toast, so it will not work !!! */ #define SIGLENINT 64 /* >121 => key will toast, so it will not
* work !!! */
#define SIGLEN ( sizeof(int4)*SIGLENINT ) #define SIGLEN ( sizeof(int4)*SIGLENINT )
#define SIGLENBIT (SIGLEN*BITBYTE) #define SIGLENBIT (SIGLEN*BITBYTE)
@ -21,9 +22,9 @@ typedef char *BITVECP;
a;\ a;\
} }
#define LOOPBIT(a) \ #define LOOPBIT(a) \
for(i=0;i<SIGLENBIT;i++) {\ for(i=0;i<SIGLENBIT;i++) {\
a;\ a;\
} }
#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) ) #define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
#define GETBITBYTE(x,i) ( ((char)(x)) >> i & 0x01 ) #define GETBITBYTE(x,i) ( ((char)(x)) >> i & 0x01 )
@ -38,27 +39,27 @@ typedef char *BITVECP;
/* /*
* type of index key * type of index key
*/ */
typedef struct { typedef struct
int4 len; {
int4 flag; int4 len;
char data[1]; int4 flag;
} GISTTYPE; char data[1];
} GISTTYPE;
#define ARRKEY 0x01 #define ARRKEY 0x01
#define SIGNKEY 0x02 #define SIGNKEY 0x02
#define ALLISTRUE 0x04 #define ALLISTRUE 0x04
#define ISARRKEY(x) ( ((GISTTYPE*)x)->flag & ARRKEY ) #define ISARRKEY(x) ( ((GISTTYPE*)x)->flag & ARRKEY )
#define ISSIGNKEY(x) ( ((GISTTYPE*)x)->flag & SIGNKEY ) #define ISSIGNKEY(x) ( ((GISTTYPE*)x)->flag & SIGNKEY )
#define ISALLTRUE(x) ( ((GISTTYPE*)x)->flag & ALLISTRUE ) #define ISALLTRUE(x) ( ((GISTTYPE*)x)->flag & ALLISTRUE )
#define GTHDRSIZE ( sizeof(int4)*2 ) #define GTHDRSIZE ( sizeof(int4)*2 )
#define CALCGTSIZE(flag, len) ( GTHDRSIZE + ( ( (flag) & ARRKEY ) ? ((len)*sizeof(int4)) : (((flag) & ALLISTRUE) ? 0 : SIGLEN) ) ) #define CALCGTSIZE(flag, len) ( GTHDRSIZE + ( ( (flag) & ARRKEY ) ? ((len)*sizeof(int4)) : (((flag) & ALLISTRUE) ? 0 : SIGLEN) ) )
#define GETSIGN(x) ( (BITVECP)( (char*)x+GTHDRSIZE ) ) #define GETSIGN(x) ( (BITVECP)( (char*)x+GTHDRSIZE ) )
#define GETARR(x) ( (int4*)( (char*)x+GTHDRSIZE ) ) #define GETARR(x) ( (int4*)( (char*)x+GTHDRSIZE ) )
#define ARRNELEM(x) ( ( ((GISTTYPE*)x)->len - GTHDRSIZE )/sizeof(int4) ) #define ARRNELEM(x) ( ( ((GISTTYPE*)x)->len - GTHDRSIZE )/sizeof(int4) )
#endif #endif

View File

@ -3,7 +3,7 @@
* New dictionary is include in dict.h. For languages which * New dictionary is include in dict.h. For languages which
* use latin charset it may be need to modify mapdict table. * use latin charset it may be need to modify mapdict table.
* Teodor Sigaev <teodor@stack.net> * Teodor Sigaev <teodor@stack.net>
*/ */
#include "postgres.h" #include "postgres.h"
#include "utils/elog.h" #include "utils/elog.h"
@ -20,157 +20,183 @@
* All of this methods are optional, but * All of this methods are optional, but
* if all methods are NULL, then dictionary does nothing :) * if all methods are NULL, then dictionary does nothing :)
* Return value of lemmatize must be palloced or the same. * Return value of lemmatize must be palloced or the same.
* Return value of init must be malloced in other case * Return value of init must be malloced in other case
* it will be free in end of transaction! * it will be free in end of transaction!
*/ */
typedef struct { typedef struct
char localename[LOCALE_NAME_BUFLEN]; {
char localename[LOCALE_NAME_BUFLEN];
/* init dictionary */ /* init dictionary */
void* (*init)(void); void *(*init) (void);
/* close dictionary */ /* close dictionary */
void (*close)(void*); void (*close) (void *);
/* find in dictionary */ /* find in dictionary */
char* (*lemmatize)(void*,char*,int*); char *(*lemmatize) (void *, char *, int *);
int (*is_stoplemm)(void*,char*,int); int (*is_stoplemm) (void *, char *, int);
int (*is_stemstoplemm)(void*,char*,int); int (*is_stemstoplemm) (void *, char *, int);
} DICT; } DICT;
/* insert all dictionaries */ /* insert all dictionaries */
#define DICT_BODY #define DICT_BODY
#include "dict.h" #include "dict.h"
#undef DICT_BODY #undef DICT_BODY
/* fill dictionary's structure */ /* fill dictionary's structure */
#define DICT_TABLE #define DICT_TABLE
DICT dicts[] = { DICT dicts[] = {
{ {
"C",NULL,NULL,NULL,NULL,NULL /* fake dictionary */ "C", NULL, NULL, NULL, NULL, NULL /* fake dictionary */
} }
#include "dict.h" #include "dict.h"
}; };
#undef DICT_TABLE #undef DICT_TABLE
/* array for storing dictinary's objects (if needed) */ /* array for storing dictinary's objects (if needed) */
void* dictobjs[ lengthof(dicts) ]; void *dictobjs[
lengthof(dicts)];
#define STOPLEXEM -2 #define STOPLEXEM -2
#define BYLOCALE -1 #define BYLOCALE -1
#define NODICT 0 #define NODICT 0
#define DEFAULTDICT 1 #define DEFAULTDICT 1
#define MAXNDICT 2 #define MAXNDICT 2
typedef int2 MAPDICT[MAXNDICT]; typedef int2 MAPDICT[MAXNDICT];
#define GETDICT(x,i) *( ((int2*)(x)) + (i) ) #define GETDICT(x,i) *( ((int2*)(x)) + (i) )
/* map dictionaries for lexem type */ /* map dictionaries for lexem type */
static MAPDICT mapdict[] = { static MAPDICT mapdict[] = {
{NODICT, NODICT}, /* not used */ {NODICT, NODICT}, /* not used */
{DEFAULTDICT, NODICT}, /* LATWORD */ {DEFAULTDICT, NODICT}, /* LATWORD */
{BYLOCALE, NODICT}, /* NONLATINWORD */ {BYLOCALE, NODICT}, /* NONLATINWORD */
{BYLOCALE, DEFAULTDICT}, /* UWORD */ {BYLOCALE, DEFAULTDICT}, /* UWORD */
{NODICT, NODICT}, /* EMAIL */ {NODICT, NODICT}, /* EMAIL */
{NODICT, NODICT}, /* FURL */ {NODICT, NODICT}, /* FURL */
{NODICT, NODICT}, /* HOST */ {NODICT, NODICT}, /* HOST */
{NODICT, NODICT}, /* FLOAT */ {NODICT, NODICT}, /* FLOAT */
{NODICT, NODICT}, /* FINT */ {NODICT, NODICT}, /* FINT */
{BYLOCALE, DEFAULTDICT}, /* PARTWORD */ {BYLOCALE, DEFAULTDICT}, /* PARTWORD */
{BYLOCALE, NODICT}, /* NONLATINPARTWORD */ {BYLOCALE, NODICT}, /* NONLATINPARTWORD */
{DEFAULTDICT, NODICT}, /* LATPARTWORD */ {DEFAULTDICT, NODICT}, /* LATPARTWORD */
{STOPLEXEM, NODICT}, /* SPACE */ {STOPLEXEM, NODICT}, /* SPACE */
{STOPLEXEM, NODICT}, /* SYMTAG */ {STOPLEXEM, NODICT}, /* SYMTAG */
{STOPLEXEM, NODICT}, /* HTTP */ {STOPLEXEM, NODICT}, /* HTTP */
{BYLOCALE, DEFAULTDICT}, /* DEFISWORD */ {BYLOCALE, DEFAULTDICT}, /* DEFISWORD */
{DEFAULTDICT, NODICT}, /* DEFISLATWORD */ {DEFAULTDICT, NODICT}, /* DEFISLATWORD */
{BYLOCALE, NODICT}, /* DEFISNONLATINWORD */ {BYLOCALE, NODICT}, /* DEFISNONLATINWORD */
{NODICT, NODICT}, /* URI */ {NODICT, NODICT}, /* URI */
{NODICT, NODICT} /* FILEPATH */ {NODICT, NODICT} /* FILEPATH */
}; };
static bool inited=false; static bool inited = false;
void
initmorph(void)
{
int i,
j,
k;
MAPDICT *md;
bool needinit[lengthof(dicts)];
void initmorph(void) {
int i,j,k;
MAPDICT *md;
bool needinit[ lengthof(dicts) ];
#ifdef USE_LOCALE #ifdef USE_LOCALE
PG_LocaleCategories lc; PG_LocaleCategories lc;
int bylocaledict = NODICT; int bylocaledict = NODICT;
#endif #endif
if ( inited ) return; if (inited)
for(i=1; i<lengthof(dicts);i++) return;
for (i = 1; i < lengthof(dicts); i++)
needinit[i] = false; needinit[i] = false;
#ifdef USE_LOCALE #ifdef USE_LOCALE
PGLC_current(&lc); PGLC_current(&lc);
for(i=1;i<lengthof(dicts);i++) for (i = 1; i < lengthof(dicts); i++)
if (strcmp( dicts[i].localename, lc.lang ) == 0) { if (strcmp(dicts[i].localename, lc.lang) == 0)
{
bylocaledict = i; bylocaledict = i;
break; break;
} }
PGLC_free_categories(&lc); PGLC_free_categories(&lc);
#endif #endif
for(i=1; i<lengthof(mapdict);i++) { for (i = 1; i < lengthof(mapdict); i++)
k=0; {
k = 0;
md = &mapdict[i]; md = &mapdict[i];
for(j=0;j<MAXNDICT;j++) { for (j = 0; j < MAXNDICT; j++)
GETDICT(md,k) = GETDICT(md,j); {
if ( GETDICT(md,k) == NODICT ) { GETDICT(md, k) = GETDICT(md, j);
if (GETDICT(md, k) == NODICT)
break; break;
} else if ( GETDICT(md,k) == BYLOCALE ) { else if (GETDICT(md, k) == BYLOCALE)
{
#ifdef USE_LOCALE #ifdef USE_LOCALE
if ( bylocaledict == NODICT ) if (bylocaledict == NODICT)
continue; continue;
GETDICT(md,k) = bylocaledict; GETDICT(md, k) = bylocaledict;
#else #else
continue; continue;
#endif #endif
} }
if ( GETDICT(md,k) >= (int2)lengthof(dicts) ) if (GETDICT(md, k) >= (int2) lengthof(dicts))
continue; continue;
needinit[ GETDICT(md,k) ] = true; needinit[GETDICT(md, k)] = true;
k++; k++;
} }
for(;k<MAXNDICT;k++) for (; k < MAXNDICT; k++)
if ( GETDICT(md,k) != STOPLEXEM ) if (GETDICT(md, k) != STOPLEXEM)
GETDICT(md,k) = NODICT; GETDICT(md, k) = NODICT;
} }
for(i=1; i<lengthof(dicts);i++) for (i = 1; i < lengthof(dicts); i++)
if ( needinit[i] && dicts[i].init ) if (needinit[i] && dicts[i].init)
dictobjs[i] = (*(dicts[i].init))(); dictobjs[i] = (*(dicts[i].init)) ();
inited = true; inited = true;
return; return;
} }
char* lemmatize( char* word, int *len, int type ) { char *
int2 nd; lemmatize(char *word, int *len, int type)
int i; {
DICT *dict; int2 nd;
int i;
DICT *dict;
for(i=0;i<MAXNDICT;i++) { for (i = 0; i < MAXNDICT; i++)
nd = GETDICT( &mapdict[type], i ); {
if ( nd == NODICT ) { nd = GETDICT(&mapdict[type], i);
/* there is no dictionary */ if (nd == NODICT)
{
/* there is no dictionary */
return word; return word;
} else if ( nd == STOPLEXEM ) { }
else if (nd == STOPLEXEM)
{
/* word is stopword */ /* word is stopword */
return NULL; return NULL;
} else { }
dict = &dicts[ nd ]; else
if ( dict->is_stoplemm && (*(dict->is_stoplemm))(dictobjs[nd], word, *len) ) {
dict = &dicts[nd];
if (dict->is_stoplemm && (*(dict->is_stoplemm)) (dictobjs[nd], word, *len))
return NULL; return NULL;
if ( dict->lemmatize ) { if (dict->lemmatize)
int oldlen = *len; {
char *newword = (*(dict->lemmatize))(dictobjs[nd], word, len); int oldlen = *len;
char *newword = (*(dict->lemmatize)) (dictobjs[nd], word, len);
/* word is recognized by distionary */ /* word is recognized by distionary */
if ( newword != word || *len != oldlen ) { if (newword != word || *len != oldlen)
if ( dict->is_stemstoplemm && {
(*(dict->is_stemstoplemm))(dictobjs[nd], word, *len) ) { if (dict->is_stemstoplemm &&
if ( newword != word && newword) (*(dict->is_stemstoplemm)) (dictobjs[nd], word, *len))
{
if (newword != word && newword)
pfree(newword); pfree(newword);
return NULL; return NULL;
} }
@ -183,6 +209,8 @@ char* lemmatize( char* word, int *len, int type ) {
return word; return word;
} }
bool is_stoptype(int type) { bool
return ( GETDICT( &mapdict[type], 0 ) == STOPLEXEM ) ? true : false; is_stoptype(int type)
{
return (GETDICT(&mapdict[type], 0) == STOPLEXEM) ? true : false;
} }

View File

@ -1,9 +1,9 @@
#ifndef __MORPH_H__ #ifndef __MORPH_H__
#define __MORPH_H__ #define __MORPH_H__
void initmorph(void); void initmorph(void);
char* lemmatize( char* word, int *len, int type ); char *lemmatize(char *word, int *len, int type);
bool is_stoptype(int type); bool is_stoptype(int type);
#endif #endif

View File

@ -1,11 +1,10 @@
#ifndef __PARSER_H__ #ifndef __PARSER_H__
#define __PARSER_H__ #define __PARSER_H__
char *token; char *token;
int tokenlen; int tokenlen;
int tsearch_yylex(void); int tsearch_yylex(void);
void start_parse_str(char*, int); void start_parse_str(char *, int);
void start_parse_fh(FILE*, int); void start_parse_fh(FILE *, int);
void end_parse(void); void end_parse(void);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -9,41 +9,43 @@
* item in polish notation with back link * item in polish notation with back link
* to left operand * to left operand
*/ */
typedef struct ITEM { typedef struct ITEM
int2 type; {
int2 left; int2 type;
int4 val; int2 left;
int4 val;
/* user-friendly value */ /* user-friendly value */
uint16 distance; uint16 distance;
uint16 length; uint16 length;
} ITEM; } ITEM;
/* /*
*Storage: *Storage:
* (len)(size)(array of ITEM)(array of operand in user-friendly form) * (len)(size)(array of ITEM)(array of operand in user-friendly form)
*/ */
typedef struct { typedef struct
int4 len; {
int4 size; int4 len;
char data[1]; int4 size;
} QUERYTYPE; char data[1];
} QUERYTYPE;
#define HDRSIZEQT ( 2*sizeof(int4) ) #define HDRSIZEQT ( 2*sizeof(int4) )
#define COMPUTESIZE(size,lenofoperand) ( HDRSIZEQT + size * sizeof(ITEM) + lenofoperand ) #define COMPUTESIZE(size,lenofoperand) ( HDRSIZEQT + size * sizeof(ITEM) + lenofoperand )
#define GETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT ) #define GETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
#define GETOPERAND(x) ( (char*)GETQUERY(x) + ((QUERYTYPE*)x)->size * sizeof(ITEM) ) #define GETOPERAND(x) ( (char*)GETQUERY(x) + ((QUERYTYPE*)x)->size * sizeof(ITEM) )
#define ISOPERATOR(x) ( (x)=='!' || (x)=='&' || (x)=='|' || (x)=='(' || (x)==')' ) #define ISOPERATOR(x) ( (x)=='!' || (x)=='&' || (x)=='|' || (x)=='(' || (x)==')' )
#define END 0 #define END 0
#define ERR 1 #define ERR 1
#define VAL 2 #define VAL 2
#define OPR 3 #define OPR 3
#define OPEN 4 #define OPEN 4
#define CLOSE 5 #define CLOSE 5
#define VALTRUE 6 /* for stop words */ #define VALTRUE 6 /* for stop words */
#define VALFALSE 7 #define VALFALSE 7
bool execute( ITEM* curitem, void *checkval, bool execute(ITEM * curitem, void *checkval,
bool calcnot, bool (*chkcond)(void *checkval, ITEM* val )); bool calcnot, bool (*chkcond) (void *checkval, ITEM * val));
#endif #endif

View File

@ -19,52 +19,63 @@
#include "query.h" #include "query.h"
#include "rewrite.h" #include "rewrite.h"
typedef struct NODE { typedef struct NODE
struct NODE *left; {
struct NODE *left;
struct NODE *right; struct NODE *right;
ITEM* valnode; ITEM *valnode;
} NODE; } NODE;
/* /*
* make query tree from plain view of query * make query tree from plain view of query
*/ */
static NODE* static NODE *
maketree(ITEM *in) { maketree(ITEM * in)
NODE *node = (NODE*)palloc(sizeof(NODE)); {
NODE *node = (NODE *) palloc(sizeof(NODE));
node->valnode = in; node->valnode = in;
node->right = node->left = NULL; node->right = node->left = NULL;
if ( in->type == OPR ) { if (in->type == OPR)
node->right = maketree( in + 1 ); {
if ( in->val != (int4)'!' ) node->right = maketree(in + 1);
node->left = maketree( in + in->left ); if (in->val != (int4) '!')
node->left = maketree(in + in->left);
} }
return node; return node;
} }
typedef struct { typedef struct
ITEM* ptr; {
int4 len; ITEM *ptr;
int4 cur; int4 len;
} PLAINTREE; int4 cur;
} PLAINTREE;
static void static void
plainnode(PLAINTREE *state, NODE* node) { plainnode(PLAINTREE * state, NODE * node)
if ( state->cur == state->len ) { {
if (state->cur == state->len)
{
state->len *= 2; state->len *= 2;
state->ptr=(ITEM*)repalloc( (void*)state->ptr, state->len*sizeof(ITEM) ); state->ptr = (ITEM *) repalloc((void *) state->ptr, state->len * sizeof(ITEM));
} }
memcpy( (void*)&(state->ptr[state->cur]), (void*)node->valnode, sizeof(ITEM) ); memcpy((void *) &(state->ptr[state->cur]), (void *) node->valnode, sizeof(ITEM));
if ( node->valnode->type == VAL ) { if (node->valnode->type == VAL)
state->cur++; state->cur++;
} else if ( node->valnode->val == (int4)'!' ) { else if (node->valnode->val == (int4) '!')
state->ptr[state->cur].left=1; {
state->ptr[state->cur].left = 1;
state->cur++; state->cur++;
plainnode(state, node->right); plainnode(state, node->right);
} else { }
int4 cur = state->cur; else
{
int4 cur = state->cur;
state->cur++; state->cur++;
plainnode(state, node->right); plainnode(state, node->right);
state->ptr[cur].left = state->cur - cur; state->ptr[cur].left = state->cur - cur;
plainnode(state, node->left); plainnode(state, node->left);
} }
pfree(node); pfree(node);
@ -73,75 +84,96 @@ plainnode(PLAINTREE *state, NODE* node) {
/* /*
* make plain view of tree from 'normal' view of tree * make plain view of tree from 'normal' view of tree
*/ */
static ITEM* static ITEM *
plaintree(NODE *root, int4 *len) { plaintree(NODE * root, int4 *len)
{
PLAINTREE pl; PLAINTREE pl;
pl.cur=0;
pl.len=16; pl.cur = 0;
if ( root && (root->valnode->type == VAL || root->valnode->type == OPR) ) { pl.len = 16;
pl.ptr = (ITEM*)palloc( pl.len*sizeof(ITEM) ); if (root && (root->valnode->type == VAL || root->valnode->type == OPR))
{
pl.ptr = (ITEM *) palloc(pl.len * sizeof(ITEM));
plainnode(&pl, root); plainnode(&pl, root);
} else {
pl.ptr = NULL;
} }
else
pl.ptr = NULL;
*len = pl.cur; *len = pl.cur;
return pl.ptr; return pl.ptr;
} }
static void static void
freetree(NODE *node) { freetree(NODE * node)
if ( !node ) return; {
if ( node->left ) freetree(node->left); if (!node)
if ( node->right ) freetree(node->right); return;
pfree( node ); if (node->left)
freetree(node->left);
if (node->right)
freetree(node->right);
pfree(node);
} }
/* /*
* clean tree for ! operator. * clean tree for ! operator.
* It's usefull for debug, but in * It's usefull for debug, but in
* other case, such view is used with search in index. * other case, such view is used with search in index.
* Operator ! always return TRUE * Operator ! always return TRUE
*/ */
static NODE* static NODE *
clean_NOT_intree( NODE* node ) { clean_NOT_intree(NODE * node)
if ( node->valnode->type == VAL ) {
if (node->valnode->type == VAL)
return node; return node;
if ( node->valnode->val == (int4)'!' ) { if (node->valnode->val == (int4) '!')
{
freetree(node); freetree(node);
return NULL; return NULL;
} }
/* operator & or | */ /* operator & or | */
if ( node->valnode->val == (int4)'|' ) { if (node->valnode->val == (int4) '|')
if ( (node->left=clean_NOT_intree(node->left)) == NULL || {
(node->right=clean_NOT_intree(node->right)) == NULL ) { if ((node->left = clean_NOT_intree(node->left)) == NULL ||
(node->right = clean_NOT_intree(node->right)) == NULL)
{
freetree(node); freetree(node);
return NULL; return NULL;
} }
} else { }
NODE *res = node; else
node->left=clean_NOT_intree(node->left); {
node->right=clean_NOT_intree(node->right); NODE *res = node;
if ( node->left == NULL && node->right == NULL ) {
node->left = clean_NOT_intree(node->left);
node->right = clean_NOT_intree(node->right);
if (node->left == NULL && node->right == NULL)
{
pfree(node); pfree(node);
res = NULL; res = NULL;
} else if ( node->left == NULL ) { }
else if (node->left == NULL)
{
res = node->right; res = node->right;
pfree(node); pfree(node);
} else if ( node->right == NULL ) { }
else if (node->right == NULL)
{
res = node->left; res = node->left;
pfree(node); pfree(node);
} }
return res; return res;
} }
return node; return node;
} }
ITEM* ITEM *
clean_NOT(ITEM* ptr, int4 *len) { clean_NOT(ITEM * ptr, int4 *len)
NODE *root = maketree( ptr ); {
return plaintree(clean_NOT_intree(root), len); NODE *root = maketree(ptr);
return plaintree(clean_NOT_intree(root), len);
} }
#define V_UNKNOWN 0 #define V_UNKNOWN 0
@ -149,86 +181,112 @@ clean_NOT(ITEM* ptr, int4 *len) {
#define V_FALSE 2 #define V_FALSE 2
/* /*
* Clean query tree from values which is always in * Clean query tree from values which is always in
* text (stopword) * text (stopword)
*/ */
static NODE* static NODE *
clean_fakeval_intree( NODE* node, char *result ) { clean_fakeval_intree(NODE * node, char *result)
char lresult = V_UNKNOWN, rresult = V_UNKNOWN; {
if ( node->valnode->type == VAL ) char lresult = V_UNKNOWN,
rresult = V_UNKNOWN;
if (node->valnode->type == VAL)
return node; return node;
else if ( node->valnode->type == VALTRUE ) { else if (node->valnode->type == VALTRUE)
pfree( node ); {
pfree(node);
*result = V_TRUE; *result = V_TRUE;
return NULL; return NULL;
}
if ( node->valnode->val == (int4)'!' ) {
node->right = clean_fakeval_intree( node->right, &rresult );
if ( ! node->right ) {
*result = ( rresult == V_TRUE ) ? V_FALSE : V_TRUE;
freetree(node);
return NULL;
}
} else if ( node->valnode->val == (int4)'|' ) {
NODE *res = node;
node->left =clean_fakeval_intree(node->left, &lresult);
node->right=clean_fakeval_intree(node->right,&rresult);
if ( lresult == V_TRUE || rresult == V_TRUE ) {
freetree(node);
*result=V_TRUE;
return NULL;
} else if ( lresult == V_FALSE && rresult == V_FALSE ) {
freetree(node);
*result=V_FALSE;
return NULL;
} else if ( lresult == V_FALSE ) {
res = node->right;
pfree(node);
} else if ( rresult == V_FALSE ) {
res = node->left;
pfree(node);
}
return res;
} else {
NODE *res = node;
node->left =clean_fakeval_intree(node->left, &lresult);
node->right=clean_fakeval_intree(node->right,&rresult);
if ( lresult == V_FALSE || rresult == V_FALSE ) {
freetree(node);
*result=V_FALSE;
return NULL;
} else if ( lresult == V_TRUE && rresult == V_TRUE ) {
freetree(node);
*result=V_TRUE;
return NULL;
} else if ( lresult == V_TRUE ) {
res = node->right;
pfree(node);
} else if ( rresult == V_TRUE ) {
res = node->left;
pfree(node);
}
return res;
} }
return node;
if (node->valnode->val == (int4) '!')
{
node->right = clean_fakeval_intree(node->right, &rresult);
if (!node->right)
{
*result = (rresult == V_TRUE) ? V_FALSE : V_TRUE;
freetree(node);
return NULL;
}
}
else if (node->valnode->val == (int4) '|')
{
NODE *res = node;
node->left = clean_fakeval_intree(node->left, &lresult);
node->right = clean_fakeval_intree(node->right, &rresult);
if (lresult == V_TRUE || rresult == V_TRUE)
{
freetree(node);
*result = V_TRUE;
return NULL;
}
else if (lresult == V_FALSE && rresult == V_FALSE)
{
freetree(node);
*result = V_FALSE;
return NULL;
}
else if (lresult == V_FALSE)
{
res = node->right;
pfree(node);
}
else if (rresult == V_FALSE)
{
res = node->left;
pfree(node);
}
return res;
}
else
{
NODE *res = node;
node->left = clean_fakeval_intree(node->left, &lresult);
node->right = clean_fakeval_intree(node->right, &rresult);
if (lresult == V_FALSE || rresult == V_FALSE)
{
freetree(node);
*result = V_FALSE;
return NULL;
}
else if (lresult == V_TRUE && rresult == V_TRUE)
{
freetree(node);
*result = V_TRUE;
return NULL;
}
else if (lresult == V_TRUE)
{
res = node->right;
pfree(node);
}
else if (rresult == V_TRUE)
{
res = node->left;
pfree(node);
}
return res;
}
return node;
} }
ITEM* ITEM *
clean_fakeval(ITEM* ptr, int4 *len) { clean_fakeval(ITEM * ptr, int4 *len)
NODE *root = maketree( ptr ); {
char result = V_UNKNOWN; NODE *root = maketree(ptr);
NODE *resroot; char result = V_UNKNOWN;
NODE *resroot;
resroot = clean_fakeval_intree(root, &result); resroot = clean_fakeval_intree(root, &result);
if ( result != V_UNKNOWN ) { if (result != V_UNKNOWN)
elog(ERROR,"Your query contained only stopword(s), ignored"); {
elog(ERROR, "Your query contained only stopword(s), ignored");
*len = 0; *len = 0;
return NULL; return NULL;
} }
return plaintree(resroot, len); return plaintree(resroot, len);
} }

View File

@ -1,7 +1,6 @@
#ifndef __REWRITE_H__ #ifndef __REWRITE_H__
#define __REWRITE_H__ #define __REWRITE_H__
ITEM* clean_NOT(ITEM* ptr, int4 *len); ITEM *clean_NOT(ITEM * ptr, int4 *len);
ITEM* clean_fakeval(ITEM* ptr, int4 *len); ITEM *clean_fakeval(ITEM * ptr, int4 *len);
#endif #endif

View File

@ -17,9 +17,9 @@
#include "utils/pg_locale.h" #include "utils/pg_locale.h"
#include <ctype.h> /* tolower */ #include <ctype.h> /* tolower */
#include "txtidx.h" #include "txtidx.h"
#include "query.h" #include "query.h"
#include "deflex.h" #include "deflex.h"
#include "parser.h" #include "parser.h"
@ -27,51 +27,58 @@
#include "morph.h" #include "morph.h"
PG_FUNCTION_INFO_V1(txtidx_in); PG_FUNCTION_INFO_V1(txtidx_in);
Datum txtidx_in(PG_FUNCTION_ARGS); Datum txtidx_in(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(txtidx_out); PG_FUNCTION_INFO_V1(txtidx_out);
Datum txtidx_out(PG_FUNCTION_ARGS); Datum txtidx_out(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(txt2txtidx); PG_FUNCTION_INFO_V1(txt2txtidx);
Datum txt2txtidx(PG_FUNCTION_ARGS); Datum txt2txtidx(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(tsearch); PG_FUNCTION_INFO_V1(tsearch);
Datum tsearch(PG_FUNCTION_ARGS); Datum tsearch(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(txtidxsize); PG_FUNCTION_INFO_V1(txtidxsize);
Datum txtidxsize(PG_FUNCTION_ARGS); Datum txtidxsize(PG_FUNCTION_ARGS);
/* /*
* in/out text index type * in/out text index type
*/ */
static char *BufferStr; static char *BufferStr;
static int static int
compareentry( const void * a, const void * b ) { compareentry(const void *a, const void *b)
if ( ((WordEntry*)a)->len == ((WordEntry*)b)->len ) { {
return strncmp( if (((WordEntry *) a)->len == ((WordEntry *) b)->len)
&BufferStr[((WordEntry*)a)->pos], {
&BufferStr[((WordEntry*)b)->pos], return strncmp(
((WordEntry*)b)->len ); &BufferStr[((WordEntry *) a)->pos],
&BufferStr[((WordEntry *) b)->pos],
((WordEntry *) b)->len);
} }
return ( ((WordEntry*)a)->len > ((WordEntry*)b)->len ) ? 1 : -1; return (((WordEntry *) a)->len > ((WordEntry *) b)->len) ? 1 : -1;
} }
static int static int
uniqueentry( WordEntry* a, int4 l, char *buf, int4 *outbuflen ) { uniqueentry(WordEntry * a, int4 l, char *buf, int4 *outbuflen)
WordEntry *ptr, *res; {
WordEntry *ptr,
*res;
res = a; res = a;
*outbuflen = res->len; *outbuflen = res->len;
if ( l == 1 ) if (l == 1)
return l; return l;
ptr = a+1; ptr = a + 1;
BufferStr = buf; BufferStr = buf;
qsort((void*)a, l, sizeof(int4), compareentry ); qsort((void *) a, l, sizeof(int4), compareentry);
*outbuflen = res->len; *outbuflen = res->len;
while (ptr - a < l) { while (ptr - a < l)
if ( ! (ptr->len == res->len && {
strncmp(&buf[ ptr->pos ], &buf[ res->pos ],res->len) == 0 ) ) { if (!(ptr->len == res->len &&
strncmp(&buf[ptr->pos], &buf[res->pos], res->len) == 0))
{
res++; res++;
res->len = ptr->len; res->len = ptr->len;
res->pos = ptr->pos; res->pos = ptr->pos;
@ -81,10 +88,10 @@ uniqueentry( WordEntry* a, int4 l, char *buf, int4 *outbuflen ) {
ptr++; ptr++;
} }
return res + 1 - a; return res + 1 - a;
} }
#define WAITWORD 1 #define WAITWORD 1
#define WAITENDWORD 2 #define WAITENDWORD 2
#define WAITNEXTCHAR 3 #define WAITNEXTCHAR 3
#define WAITENDCMPLX 4 #define WAITENDCMPLX 4
@ -92,81 +99,105 @@ uniqueentry( WordEntry* a, int4 l, char *buf, int4 *outbuflen ) {
do { \ do { \
if ( state->curpos - state->word == state->len ) \ if ( state->curpos - state->word == state->len ) \
{ \ { \
int4 clen = state->curpos - state->word; \ int4 clen = state->curpos - state->word; \
state->len *= 2; \ state->len *= 2; \
state->word = (char*)repalloc( (void*)state->word, state->len ); \ state->word = (char*)repalloc( (void*)state->word, state->len ); \
state->curpos = state->word + clen; \ state->curpos = state->word + clen; \
} \ } \
} while (0) } while (0)
int4 int4
gettoken_txtidx( TI_IN_STATE *state ) { gettoken_txtidx(TI_IN_STATE * state)
int4 oldstate = 0; {
int4 oldstate = 0;
state->curpos = state->word; state->curpos = state->word;
state->state = WAITWORD; state->state = WAITWORD;
while( 1 ) { while (1)
if ( state->state == WAITWORD ) { {
if ( *(state->prsbuf) == '\0' ) { if (state->state == WAITWORD)
{
if (*(state->prsbuf) == '\0')
return 0; return 0;
} else if ( *(state->prsbuf) == '\'' ) { else if (*(state->prsbuf) == '\'')
state->state = WAITENDCMPLX; state->state = WAITENDCMPLX;
} else if ( *(state->prsbuf) == '\\' ) { else if (*(state->prsbuf) == '\\')
{
state->state = WAITNEXTCHAR; state->state = WAITNEXTCHAR;
oldstate = WAITENDWORD; oldstate = WAITENDWORD;
} else if ( state->oprisdelim && ISOPERATOR( *(state->prsbuf) ) ) { }
else if (state->oprisdelim && ISOPERATOR(*(state->prsbuf)))
elog(ERROR, "Syntax error"); elog(ERROR, "Syntax error");
} else if ( *(state->prsbuf) != ' ' ) { else if (*(state->prsbuf) != ' ')
{
*(state->curpos) = *(state->prsbuf); *(state->curpos) = *(state->prsbuf);
state->curpos++; state->curpos++;
state->state = WAITENDWORD; state->state = WAITENDWORD;
} }
} else if ( state->state == WAITNEXTCHAR ) { }
if ( *(state->prsbuf) == '\0' ) { else if (state->state == WAITNEXTCHAR)
elog(ERROR,"There is no escaped character"); {
} else { if (*(state->prsbuf) == '\0')
elog(ERROR, "There is no escaped character");
else
{
RESIZEPRSBUF; RESIZEPRSBUF;
*(state->curpos) = *(state->prsbuf); *(state->curpos) = *(state->prsbuf);
state->curpos++; state->curpos++;
state->state = oldstate; state->state = oldstate;
} }
} else if ( state->state == WAITENDWORD ) { }
if ( *(state->prsbuf) == '\\' ) { else if (state->state == WAITENDWORD)
{
if (*(state->prsbuf) == '\\')
{
state->state = WAITNEXTCHAR; state->state = WAITNEXTCHAR;
oldstate = WAITENDWORD; oldstate = WAITENDWORD;
} else if ( *(state->prsbuf) == ' ' || *(state->prsbuf) == '\0' || }
( state->oprisdelim && ISOPERATOR( *(state->prsbuf) ) ) ) { else if (*(state->prsbuf) == ' ' || *(state->prsbuf) == '\0' ||
(state->oprisdelim && ISOPERATOR(*(state->prsbuf))))
{
RESIZEPRSBUF; RESIZEPRSBUF;
if ( state->curpos == state->word ) if (state->curpos == state->word)
elog(ERROR, "Syntax error"); elog(ERROR, "Syntax error");
*(state->curpos) = '\0'; *(state->curpos) = '\0';
return 1; return 1;
} else { }
else
{
RESIZEPRSBUF; RESIZEPRSBUF;
*(state->curpos) = *(state->prsbuf); *(state->curpos) = *(state->prsbuf);
state->curpos++; state->curpos++;
} }
} else if ( state->state == WAITENDCMPLX ) { }
if ( *(state->prsbuf) == '\'' ) { else if (state->state == WAITENDCMPLX)
{
if (*(state->prsbuf) == '\'')
{
RESIZEPRSBUF; RESIZEPRSBUF;
*(state->curpos) = '\0'; *(state->curpos) = '\0';
if ( state->curpos == state->word ) if (state->curpos == state->word)
elog(ERROR, "Syntax error"); elog(ERROR, "Syntax error");
state->prsbuf++; state->prsbuf++;
return 1; return 1;
} else if ( *(state->prsbuf) == '\\' ) { }
else if (*(state->prsbuf) == '\\')
{
state->state = WAITNEXTCHAR; state->state = WAITNEXTCHAR;
oldstate = WAITENDCMPLX; oldstate = WAITENDCMPLX;
} else if ( *(state->prsbuf) == '\0' ) { }
elog(ERROR,"Syntax error"); else if (*(state->prsbuf) == '\0')
} else { elog(ERROR, "Syntax error");
else
{
RESIZEPRSBUF; RESIZEPRSBUF;
*(state->curpos) = *(state->prsbuf); *(state->curpos) = *(state->prsbuf);
state->curpos++; state->curpos++;
} }
} else { }
else
elog(ERROR, "Inner bug :("); elog(ERROR, "Inner bug :(");
}
state->prsbuf++; state->prsbuf++;
} }
@ -174,92 +205,111 @@ gettoken_txtidx( TI_IN_STATE *state ) {
} }
Datum Datum
txtidx_in(PG_FUNCTION_ARGS) { txtidx_in(PG_FUNCTION_ARGS)
char *buf = (char*)PG_GETARG_POINTER(0); {
char *buf = (char *) PG_GETARG_POINTER(0);
TI_IN_STATE state; TI_IN_STATE state;
WordEntry *arr; WordEntry *arr;
int4 len=0, totallen = 64; int4 len = 0,
txtidx *in; totallen = 64;
char *tmpbuf, *cur; txtidx *in;
int4 i,buflen = 256; char *tmpbuf,
*cur;
int4 i,
buflen = 256;
state.prsbuf = buf; state.prsbuf = buf;
state.len=32; state.len = 32;
state.word = (char*)palloc( state.len ); state.word = (char *) palloc(state.len);
state.oprisdelim = false; state.oprisdelim = false;
arr = (WordEntry*)palloc( sizeof(WordEntry) * totallen ); arr = (WordEntry *) palloc(sizeof(WordEntry) * totallen);
cur = tmpbuf = (char*)palloc( buflen ); cur = tmpbuf = (char *) palloc(buflen);
while( gettoken_txtidx( &state ) ) { while (gettoken_txtidx(&state))
if ( len == totallen ) { {
if (len == totallen)
{
totallen *= 2; totallen *= 2;
arr = (WordEntry*)repalloc( (void*)arr, sizeof(int4)*totallen ); arr = (WordEntry *) repalloc((void *) arr, sizeof(int4) * totallen);
} }
while ( cur-tmpbuf + state.curpos - state.word >= buflen ) { while (cur - tmpbuf + state.curpos - state.word >= buflen)
int4 dist = cur-tmpbuf; {
int4 dist = cur - tmpbuf;
buflen *= 2; buflen *= 2;
tmpbuf = (char*)repalloc( (void*)tmpbuf, buflen ); tmpbuf = (char *) repalloc((void *) tmpbuf, buflen);
cur = tmpbuf+dist; cur = tmpbuf + dist;
} }
if ( state.curpos - state.word > 0xffff ) if (state.curpos - state.word > 0xffff)
elog(ERROR,"Word is too long"); elog(ERROR, "Word is too long");
arr[len].len = state.curpos - state.word; arr[len].len = state.curpos - state.word;
if ( cur - tmpbuf > 0xffff ) if (cur - tmpbuf > 0xffff)
elog(ERROR,"Too long value"); elog(ERROR, "Too long value");
arr[len].pos = cur - tmpbuf; arr[len].pos = cur - tmpbuf;
memcpy( (void*)cur, (void*)state.word, arr[len].len ); memcpy((void *) cur, (void *) state.word, arr[len].len);
cur += arr[len].len; cur += arr[len].len;
len++; len++;
} }
pfree(state.word); pfree(state.word);
if ( !len ) if (!len)
elog(ERROR,"Void value"); elog(ERROR, "Void value");
len = uniqueentry( arr, len, tmpbuf, &buflen ); len = uniqueentry(arr, len, tmpbuf, &buflen);
totallen = CALCDATASIZE( len, buflen ); totallen = CALCDATASIZE(len, buflen);
in = (txtidx*)palloc( totallen ); in = (txtidx *) palloc(totallen);
in->len = totallen; in->len = totallen;
in->size = len; in->size = len;
cur = STRPTR(in); cur = STRPTR(in);
for(i=0;i<len;i++) { for (i = 0; i < len; i++)
memcpy( (void*)cur, (void*)&tmpbuf[ arr[i].pos ], arr[i].len ); {
memcpy((void *) cur, (void *) &tmpbuf[arr[i].pos], arr[i].len);
arr[i].pos = cur - STRPTR(in); arr[i].pos = cur - STRPTR(in);
cur += arr[i].len; cur += arr[i].len;
} }
pfree(tmpbuf); pfree(tmpbuf);
memcpy( (void*)ARRPTR(in), (void*)arr, sizeof(int4)*len ); memcpy((void *) ARRPTR(in), (void *) arr, sizeof(int4) * len);
pfree( arr ); pfree(arr);
PG_RETURN_POINTER( in ); PG_RETURN_POINTER(in);
} }
Datum Datum
txtidxsize(PG_FUNCTION_ARGS) { txtidxsize(PG_FUNCTION_ARGS)
txtidx *in=(txtidx*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); {
int4 ret = in->size; txtidx *in = (txtidx *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
PG_FREE_IF_COPY(in,0); int4 ret = in->size;
PG_RETURN_INT32( ret );
PG_FREE_IF_COPY(in, 0);
PG_RETURN_INT32(ret);
} }
Datum Datum
txtidx_out(PG_FUNCTION_ARGS) { txtidx_out(PG_FUNCTION_ARGS)
txtidx *out=(txtidx*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); {
char *outbuf; txtidx *out = (txtidx *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
int4 i,j,lenbuf = STRSIZE(out) + 1 /* \0 */ + out->size*2 /* '' */ + out->size - 1 /* space */; char *outbuf;
WordEntry *ptr = ARRPTR(out); int4 i,
char *curin, *curout; j,
lenbuf = STRSIZE(out) + 1 /* \0 */ + out->size * 2 /* '' */ + out->size - 1 /* space */ ;
WordEntry *ptr = ARRPTR(out);
char *curin,
*curout;
curout = outbuf = (char*) palloc( lenbuf ); curout = outbuf = (char *) palloc(lenbuf);
for(i=0;i<out->size;i++) { for (i = 0; i < out->size; i++)
{
curin = STRPTR(out) + ptr->pos; curin = STRPTR(out) + ptr->pos;
if ( i!= 0 ) if (i != 0)
*curout++ = ' '; *curout++ = ' ';
*curout++ = '\''; *curout++ = '\'';
j = ptr->len; j = ptr->len;
while( j-- ) { while (j--)
if ( *curin == '\'' ) { {
int4 pos = curout - outbuf; if (*curin == '\'')
outbuf = (char*)repalloc((void*)outbuf, ++lenbuf ); {
int4 pos = curout - outbuf;
outbuf = (char *) repalloc((void *) outbuf, ++lenbuf);
curout = outbuf + pos; curout = outbuf + pos;
*curout++ = '\\'; *curout++ = '\\';
} }
@ -268,171 +318,198 @@ txtidx_out(PG_FUNCTION_ARGS) {
*curout++ = '\''; *curout++ = '\'';
ptr++; ptr++;
} }
outbuf[ lenbuf-1 ] = '\0'; outbuf[lenbuf - 1] = '\0';
PG_FREE_IF_COPY(out,0); PG_FREE_IF_COPY(out, 0);
PG_RETURN_POINTER( outbuf ); PG_RETURN_POINTER(outbuf);
} }
typedef struct { typedef struct
uint16 len; {
char* word; uint16 len;
} WORD; char *word;
} WORD;
typedef struct { typedef struct
WORD *words; {
int4 lenwords; WORD *words;
int4 curwords; int4 lenwords;
} PRSTEXT; int4 curwords;
} PRSTEXT;
/* /*
* Parse text to lexems * Parse text to lexems
*/ */
static void static void
parsetext( PRSTEXT *prs, char *buf, int4 buflen ) { parsetext(PRSTEXT * prs, char *buf, int4 buflen)
int type,lenlemm; {
char *ptr,*ptrw; int type,
char *lemm; lenlemm;
char *ptr,
*ptrw;
char *lemm;
start_parse_str( buf, buflen ); start_parse_str(buf, buflen);
while( (type=tsearch_yylex()) != 0 ) { while ((type = tsearch_yylex()) != 0)
if ( prs->curwords == prs->lenwords ) { {
if (prs->curwords == prs->lenwords)
{
prs->lenwords *= 2; prs->lenwords *= 2;
prs->words = (WORD*)repalloc( (void*)prs->words, prs->lenwords * sizeof(WORD) ); prs->words = (WORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(WORD));
} }
if ( tokenlen>0xffff ) { if (tokenlen > 0xffff)
{
end_parse(); end_parse();
elog(ERROR, "Word is too long"); elog(ERROR, "Word is too long");
} }
lenlemm = tokenlen; lenlemm = tokenlen;
lemm = lemmatize( token, &lenlemm, type ); lemm = lemmatize(token, &lenlemm, type);
if ( ! lemm ) if (!lemm)
continue; continue;
if ( lemm != token ) { if (lemm != token)
prs->words[ prs->curwords ].len = lenlemm; {
prs->words[ prs->curwords ].word = lemm; prs->words[prs->curwords].len = lenlemm;
} else { prs->words[prs->curwords].word = lemm;
prs->words[ prs->curwords ].len = lenlemm; }
ptrw = prs->words[ prs->curwords ].word = (char*)palloc( lenlemm ); else
{
prs->words[prs->curwords].len = lenlemm;
ptrw = prs->words[prs->curwords].word = (char *) palloc(lenlemm);
ptr = token; ptr = token;
while( ptr-token < lenlemm ) { while (ptr - token < lenlemm)
*ptrw = tolower( (unsigned char) *ptr ); {
ptr++; ptrw++; *ptrw = tolower((unsigned char) *ptr);
ptr++;
ptrw++;
} }
} }
prs->curwords++; prs->curwords++;
} }
end_parse(); end_parse();
} }
static int static int
compareWORD( const void * a, const void * b ) { compareWORD(const void *a, const void *b)
if ( ((WORD*)a)->len == ((WORD*)b)->len ) {
return strncmp( if (((WORD *) a)->len == ((WORD *) b)->len)
((WORD*)a)->word, return strncmp(
((WORD*)b)->word, ((WORD *) a)->word,
((WORD*)b)->len ); ((WORD *) b)->word,
return ( ((WORD*)a)->len > ((WORD*)b)->len ) ? 1 : -1; ((WORD *) b)->len);
return (((WORD *) a)->len > ((WORD *) b)->len) ? 1 : -1;
} }
static int static int
uniqueWORD( WORD* a, int4 l ) { uniqueWORD(WORD * a, int4 l)
WORD *ptr, *res; {
WORD *ptr,
*res;
if ( l == 1 ) if (l == 1)
return l; return l;
res = a; res = a;
ptr = a + 1; ptr = a + 1;
qsort((void*)a, l, sizeof(WORD), compareWORD ); qsort((void *) a, l, sizeof(WORD), compareWORD);
while (ptr - a < l) { while (ptr - a < l)
if ( ! (ptr->len == res->len && {
strncmp(ptr->word, res->word ,res->len) == 0 ) ) { if (!(ptr->len == res->len &&
strncmp(ptr->word, res->word, res->len) == 0))
{
res++; res++;
res->len = ptr->len; res->len = ptr->len;
res->word = ptr->word; res->word = ptr->word;
} else {
pfree(ptr->word);
} }
else
pfree(ptr->word);
ptr++; ptr++;
} }
return res + 1 - a; return res + 1 - a;
} }
/* /*
* make value of txtidx * make value of txtidx
*/ */
static txtidx * static txtidx *
makevalue( PRSTEXT *prs ) { makevalue(PRSTEXT * prs)
int4 i, lenstr=0, totallen; {
txtidx *in; int4 i,
WordEntry *ptr; lenstr = 0,
char *str,*cur; totallen;
txtidx *in;
WordEntry *ptr;
char *str,
*cur;
prs->curwords = uniqueWORD( prs->words, prs->curwords ); prs->curwords = uniqueWORD(prs->words, prs->curwords);
for(i=0;i<prs->curwords;i++) for (i = 0; i < prs->curwords; i++)
lenstr += prs->words[i].len; lenstr += prs->words[i].len;
totallen = CALCDATASIZE( prs->curwords, lenstr ); totallen = CALCDATASIZE(prs->curwords, lenstr);
in = (txtidx*)palloc( totallen ); in = (txtidx *) palloc(totallen);
in->len = totallen; in->len = totallen;
in->size = prs->curwords; in->size = prs->curwords;
ptr = ARRPTR(in); ptr = ARRPTR(in);
cur = str = STRPTR(in); cur = str = STRPTR(in);
for(i=0;i<prs->curwords;i++) { for (i = 0; i < prs->curwords; i++)
{
ptr->len = prs->words[i].len; ptr->len = prs->words[i].len;
if ( cur-str > 0xffff ) if (cur - str > 0xffff)
elog(ERROR,"Value is too big"); elog(ERROR, "Value is too big");
ptr->pos = cur-str; ptr->pos = cur - str;
ptr++; ptr++;
memcpy( (void*)cur, (void*)prs->words[i].word, prs->words[i].len ); memcpy((void *) cur, (void *) prs->words[i].word, prs->words[i].len);
pfree(prs->words[i].word); pfree(prs->words[i].word);
cur += prs->words[i].len; cur += prs->words[i].len;
} }
pfree(prs->words); pfree(prs->words);
return in; return in;
} }
Datum Datum
txt2txtidx(PG_FUNCTION_ARGS) { txt2txtidx(PG_FUNCTION_ARGS)
text *in = (text*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); {
PRSTEXT prs; text *in = (text *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
txtidx *out = NULL; PRSTEXT prs;
txtidx *out = NULL;
prs.lenwords = 32;
prs.curwords = 0; prs.lenwords = 32;
prs.words = (WORD*)palloc(sizeof(WORD)*prs.lenwords); prs.curwords = 0;
prs.words = (WORD *) palloc(sizeof(WORD) * prs.lenwords);
initmorph(); initmorph();
parsetext( &prs, VARDATA(in), VARSIZE(in) - VARHDRSZ ); parsetext(&prs, VARDATA(in), VARSIZE(in) - VARHDRSZ);
PG_FREE_IF_COPY(in,0); PG_FREE_IF_COPY(in, 0);
if ( prs.curwords ) { if (prs.curwords)
out = makevalue( &prs ); {
PG_RETURN_POINTER( out ); out = makevalue(&prs);
PG_RETURN_POINTER(out);
} }
pfree(prs.words); pfree(prs.words);
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
/* /*
* Trigger * Trigger
*/ */
Datum Datum
tsearch(PG_FUNCTION_ARGS) { tsearch(PG_FUNCTION_ARGS)
{
TriggerData *trigdata; TriggerData *trigdata;
Trigger *trigger; Trigger *trigger;
Relation rel; Relation rel;
HeapTuple rettuple = NULL; HeapTuple rettuple = NULL;
int numidxattr,i; int numidxattr,
PRSTEXT prs; i;
Datum datum = (Datum)0; PRSTEXT prs;
Datum datum = (Datum) 0;
if (!CALLED_AS_TRIGGER(fcinfo)) if (!CALLED_AS_TRIGGER(fcinfo))
@ -448,63 +525,69 @@ tsearch(PG_FUNCTION_ARGS) {
rettuple = trigdata->tg_trigtuple; rettuple = trigdata->tg_trigtuple;
else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
rettuple = trigdata->tg_newtuple; rettuple = trigdata->tg_newtuple;
else else
elog(ERROR, "TSearch: Unknown event"); elog(ERROR, "TSearch: Unknown event");
trigger = trigdata->tg_trigger; trigger = trigdata->tg_trigger;
rel = trigdata->tg_relation; rel = trigdata->tg_relation;
if ( trigger->tgnargs < 2 ) if (trigger->tgnargs < 2)
elog(ERROR,"TSearch: format tsearch(txtidx_field, text_field1,...)"); elog(ERROR, "TSearch: format tsearch(txtidx_field, text_field1,...)");
numidxattr = SPI_fnumber(rel->rd_att, trigger->tgargs[0]); numidxattr = SPI_fnumber(rel->rd_att, trigger->tgargs[0]);
if ( numidxattr < 0 ) if (numidxattr < 0)
elog(ERROR,"TSearch: Can not find txtidx_field"); elog(ERROR, "TSearch: Can not find txtidx_field");
prs.lenwords = 32; prs.lenwords = 32;
prs.curwords = 0; prs.curwords = 0;
prs.words = (WORD*)palloc(sizeof(WORD)*prs.lenwords); prs.words = (WORD *) palloc(sizeof(WORD) * prs.lenwords);
initmorph(); initmorph();
/* find all words in indexable column */ /* find all words in indexable column */
for(i=1; i<trigger->tgnargs; i++) { for (i = 1; i < trigger->tgnargs; i++)
int4 numattr; {
text *txt_toasted, *txt; int4 numattr;
bool isnull; text *txt_toasted,
Oid oidtype; *txt;
bool isnull;
Oid oidtype;
numattr = SPI_fnumber(rel->rd_att, trigger->tgargs[i]); numattr = SPI_fnumber(rel->rd_att, trigger->tgargs[i]);
oidtype = SPI_gettypeid(rel->rd_att, numattr); oidtype = SPI_gettypeid(rel->rd_att, numattr);
if ( numattr<0 || ( ! ( oidtype==TEXTOID || oidtype==VARCHAROID ) ) ) { if (numattr < 0 || (!(oidtype == TEXTOID || oidtype == VARCHAROID)))
{
elog(NOTICE, "TSearch: can not find field '%s'", trigger->tgargs[i]); elog(NOTICE, "TSearch: can not find field '%s'", trigger->tgargs[i]);
continue; continue;
} }
txt_toasted = (text*)DatumGetPointer( SPI_getbinval(rettuple, rel->rd_att, numattr, &isnull ) ); txt_toasted = (text *) DatumGetPointer(SPI_getbinval(rettuple, rel->rd_att, numattr, &isnull));
if ( isnull ) if (isnull)
continue; continue;
txt = (text*)DatumGetPointer( PG_DETOAST_DATUM( PointerGetDatum ( txt_toasted ) ) ); txt = (text *) DatumGetPointer(PG_DETOAST_DATUM(PointerGetDatum(txt_toasted)));
parsetext( &prs, VARDATA(txt), VARSIZE(txt) - VARHDRSZ ); parsetext(&prs, VARDATA(txt), VARSIZE(txt) - VARHDRSZ);
if ( txt != txt_toasted ) if (txt != txt_toasted)
pfree(txt); pfree(txt);
} }
/* make txtidx value */ /* make txtidx value */
if (prs.curwords) { if (prs.curwords)
datum = PointerGetDatum( makevalue( &prs ) ); {
rettuple = SPI_modifytuple( rel, rettuple, 1, &numidxattr, datum = PointerGetDatum(makevalue(&prs));
&datum, NULL ); rettuple = SPI_modifytuple(rel, rettuple, 1, &numidxattr,
&datum, NULL);
pfree(DatumGetPointer(datum)); pfree(DatumGetPointer(datum));
} else {
char nulls = 'n';
pfree( prs.words );
rettuple = SPI_modifytuple( rel, rettuple, 1, &numidxattr,
&datum, &nulls );
} }
else
{
char nulls = 'n';
pfree(prs.words);
rettuple = SPI_modifytuple(rel, rettuple, 1, &numidxattr,
&datum, &nulls);
}
if (rettuple == NULL) if (rettuple == NULL)
elog(ERROR, "TSearch: %d returned by SPI_modifytuple", SPI_result); elog(ERROR, "TSearch: %d returned by SPI_modifytuple", SPI_result);
return PointerGetDatum( rettuple ); return PointerGetDatum(rettuple);
} }

View File

@ -14,33 +14,34 @@
#include "utils/builtins.h" #include "utils/builtins.h"
#include "storage/bufpage.h" #include "storage/bufpage.h"
typedef struct { typedef struct
uint16 len; {
uint16 pos; uint16 len;
} WordEntry; uint16 pos;
} WordEntry;
typedef struct { typedef struct
int4 len; {
int4 size; int4 len;
char data[1]; int4 size;
} txtidx; char data[1];
} txtidx;
#define DATAHDRSIZE (sizeof(int4)*2) #define DATAHDRSIZE (sizeof(int4)*2)
#define CALCDATASIZE(x, lenstr) ( x * sizeof(WordEntry) + DATAHDRSIZE + lenstr ) #define CALCDATASIZE(x, lenstr) ( x * sizeof(WordEntry) + DATAHDRSIZE + lenstr )
#define ARRPTR(x) ( (WordEntry*) ( (char*)x + DATAHDRSIZE ) ) #define ARRPTR(x) ( (WordEntry*) ( (char*)x + DATAHDRSIZE ) )
#define STRPTR(x) ( (char*)x + DATAHDRSIZE + ( sizeof(WordEntry) * ((txtidx*)x)->size ) ) #define STRPTR(x) ( (char*)x + DATAHDRSIZE + ( sizeof(WordEntry) * ((txtidx*)x)->size ) )
#define STRSIZE(x) ( ((txtidx*)x)->len - DATAHDRSIZE - ( sizeof(WordEntry) * ((txtidx*)x)->size ) ) #define STRSIZE(x) ( ((txtidx*)x)->len - DATAHDRSIZE - ( sizeof(WordEntry) * ((txtidx*)x)->size ) )
typedef struct { typedef struct
char *prsbuf; {
char *word; char *prsbuf;
char *curpos; char *word;
int4 len; char *curpos;
int4 state; int4 len;
bool oprisdelim; int4 state;
} TI_IN_STATE; bool oprisdelim;
} TI_IN_STATE;
int4 gettoken_txtidx( TI_IN_STATE *state );
int4 gettoken_txtidx(TI_IN_STATE * state);
#endif #endif

View File

@ -8,7 +8,6 @@ int user_write_unlock(unsigned int id1, unsigned int id2);
int user_write_lock_oid(Oid oid); int user_write_lock_oid(Oid oid);
int user_write_unlock_oid(Oid oid); int user_write_unlock_oid(Oid oid);
int user_unlock_all(void); int user_unlock_all(void);
#endif #endif
/* /*

View File

@ -14,32 +14,39 @@ XML_Memory_Handling_Suite mhs;
/* passthrough functions (palloc is a macro) */ /* passthrough functions (palloc is a macro) */
static void *pgxml_palloc(size_t size) static void *
pgxml_palloc(size_t size)
{ {
return palloc(size); return palloc(size);
} }
static void *pgxml_repalloc(void *ptr, size_t size) static void *
pgxml_repalloc(void *ptr, size_t size)
{ {
return repalloc(ptr,size); return repalloc(ptr, size);
} }
static void pgxml_pfree(void *ptr) static void
pgxml_pfree(void *ptr)
{ {
return pfree(ptr); return pfree(ptr);
} }
static void pgxml_mhs_init() static void
pgxml_mhs_init()
{ {
mhs.malloc_fcn = pgxml_palloc; mhs.malloc_fcn = pgxml_palloc;
mhs.realloc_fcn = pgxml_repalloc; mhs.realloc_fcn = pgxml_repalloc;
mhs.free_fcn = pgxml_pfree; mhs.free_fcn = pgxml_pfree;
} }
static void pgxml_handler_init() static void
pgxml_handler_init()
{ {
/* This code should set up the relevant handlers from user-supplied /*
settings. Quite how these settings are made is another matter :) */ * This code should set up the relevant handlers from user-supplied
* settings. Quite how these settings are made is another matter :)
*/
} }
/* Returns true if document is well-formed */ /* Returns true if document is well-formed */
@ -49,31 +56,35 @@ PG_FUNCTION_INFO_V1(pgxml_parse);
Datum Datum
pgxml_parse(PG_FUNCTION_ARGS) pgxml_parse(PG_FUNCTION_ARGS)
{ {
/* called as pgxml_parse(document) */ /* called as pgxml_parse(document) */
XML_Parser p; XML_Parser p;
text *t = PG_GETARG_TEXT_P(0); /*document buffer */ text *t = PG_GETARG_TEXT_P(0); /* document buffer */
int32 docsize = VARSIZE(t) - VARHDRSZ; int32 docsize = VARSIZE(t) - VARHDRSZ;
pgxml_mhs_init(); pgxml_mhs_init();
pgxml_handler_init(); pgxml_handler_init();
p = XML_ParserCreate_MM(NULL,&mhs,NULL); p = XML_ParserCreate_MM(NULL, &mhs, NULL);
if (! p) { if (!p)
elog(ERROR, "pgxml: Could not create expat parser"); {
PG_RETURN_NULL(); /* seems appropriate if we couldn't parse */ elog(ERROR, "pgxml: Could not create expat parser");
} PG_RETURN_NULL(); /* seems appropriate if we couldn't parse */
}
if (! XML_Parse(p, (char *)VARDATA(t) , docsize, 1)) { if (!XML_Parse(p, (char *) VARDATA(t), docsize, 1))
/* elog(NOTICE, "Parse error at line %d:%s", {
XML_GetCurrentLineNumber(p), /*
XML_ErrorString(XML_GetErrorCode(p))); */ * elog(NOTICE, "Parse error at line %d:%s",
XML_ParserFree(p); * XML_GetCurrentLineNumber(p),
PG_RETURN_BOOL(false); * XML_ErrorString(XML_GetErrorCode(p)));
} */
XML_ParserFree(p);
PG_RETURN_BOOL(false);
}
XML_ParserFree(p); XML_ParserFree(p);
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
} }
/* XPath handling functions */ /* XPath handling functions */
@ -81,83 +92,88 @@ pgxml_parse(PG_FUNCTION_ARGS)
/* XPath support here is for a very skeletal kind of XPath! /* XPath support here is for a very skeletal kind of XPath!
It was easy to program though... */ It was easy to program though... */
/* This first is the core function that builds a result set. The /* This first is the core function that builds a result set. The
actual functions called by the user manipulate that result set actual functions called by the user manipulate that result set
in various ways. in various ways.
*/ */
static XPath_Results *build_xpath_results(text *doc, text *pathstr) static XPath_Results *
build_xpath_results(text *doc, text *pathstr)
{ {
XPath_Results *xpr; XPath_Results *xpr;
char *res; char *res;
pgxml_udata *udata; pgxml_udata *udata;
XML_Parser p; XML_Parser p;
int32 docsize; int32 docsize;
xpr = (XPath_Results *) palloc((sizeof(XPath_Results))); xpr = (XPath_Results *) palloc((sizeof(XPath_Results)));
memset((void *)xpr, 0, sizeof(XPath_Results)); memset((void *) xpr, 0, sizeof(XPath_Results));
xpr->rescount=0; xpr->rescount = 0;
docsize=VARSIZE(doc)-VARHDRSZ; docsize = VARSIZE(doc) - VARHDRSZ;
/* res isn't going to be the real return type, it is just a buffer */ /* res isn't going to be the real return type, it is just a buffer */
res = (char *) palloc(docsize); res = (char *) palloc(docsize);
memset((void *)res, 0, docsize); memset((void *) res, 0, docsize);
xpr->resbuf = res; xpr->resbuf = res;
udata = (pgxml_udata *) palloc((sizeof(pgxml_udata))); udata = (pgxml_udata *) palloc((sizeof(pgxml_udata)));
memset((void *)udata,0,sizeof(pgxml_udata)); memset((void *) udata, 0, sizeof(pgxml_udata));
udata->currentpath[0]='\0'; udata->currentpath[0] = '\0';
udata->textgrab=0; udata->textgrab = 0;
udata->path= (char *) palloc(VARSIZE(pathstr)); udata->path = (char *) palloc(VARSIZE(pathstr));
memcpy(udata->path, VARDATA(pathstr), VARSIZE(pathstr)-VARHDRSZ); memcpy(udata->path, VARDATA(pathstr), VARSIZE(pathstr) - VARHDRSZ);
udata->path[VARSIZE(pathstr)-VARHDRSZ]='\0'; udata->path[VARSIZE(pathstr) - VARHDRSZ] = '\0';
udata->resptr = res; udata->resptr = res;
udata->reslen = 0; udata->reslen = 0;
udata->xpres = xpr; udata->xpres = xpr;
/* Now fire up the parser */ /* Now fire up the parser */
pgxml_mhs_init(); pgxml_mhs_init();
p = XML_ParserCreate_MM(NULL,&mhs,NULL); p = XML_ParserCreate_MM(NULL, &mhs, NULL);
if (! p) { if (!p)
elog(ERROR, "pgxml: Could not create expat parser"); {
pfree(xpr); elog(ERROR, "pgxml: Could not create expat parser");
pfree(udata->path); pfree(xpr);
pfree(udata); pfree(udata->path);
pfree(res); pfree(udata);
return NULL; pfree(res);
} return NULL;
XML_SetUserData(p, (void *)udata); }
XML_SetUserData(p, (void *) udata);
/* Set the handlers */ /* Set the handlers */
XML_SetElementHandler(p, pgxml_starthandler, pgxml_endhandler); XML_SetElementHandler(p, pgxml_starthandler, pgxml_endhandler);
XML_SetCharacterDataHandler(p, pgxml_charhandler); XML_SetCharacterDataHandler(p, pgxml_charhandler);
if (! XML_Parse(p, (char *)VARDATA(doc) , docsize, 1)) { if (!XML_Parse(p, (char *) VARDATA(doc), docsize, 1))
/* elog(NOTICE, "Parse error at line %d:%s", {
XML_GetCurrentLineNumber(p), /*
XML_ErrorString(XML_GetErrorCode(p))); */ * elog(NOTICE, "Parse error at line %d:%s",
XML_ParserFree(p); * XML_GetCurrentLineNumber(p),
pfree(xpr); * XML_ErrorString(XML_GetErrorCode(p)));
pfree(udata->path); */
pfree(udata); XML_ParserFree(p);
pfree(xpr);
pfree(udata->path);
pfree(udata);
return NULL; return NULL;
} }
pfree(udata->path); pfree(udata->path);
pfree(udata); pfree(udata);
XML_ParserFree(p); XML_ParserFree(p);
return xpr; return xpr;
} }
@ -166,145 +182,166 @@ PG_FUNCTION_INFO_V1(pgxml_xpath);
Datum Datum
pgxml_xpath(PG_FUNCTION_ARGS) pgxml_xpath(PG_FUNCTION_ARGS)
{ {
/* called as pgxml_xpath(document,pathstr, index) for the moment*/ /* called as pgxml_xpath(document,pathstr, index) for the moment */
XPath_Results *xpresults; XPath_Results *xpresults;
text *restext; text *restext;
text *t = PG_GETARG_TEXT_P(0); /*document buffer */ text *t = PG_GETARG_TEXT_P(0); /* document buffer */
text *t2= PG_GETARG_TEXT_P(1); text *t2 = PG_GETARG_TEXT_P(1);
int32 ind = PG_GETARG_INT32(2) - 1; int32 ind = PG_GETARG_INT32(2) - 1;
xpresults = build_xpath_results(t,t2); xpresults = build_xpath_results(t, t2);
/* This needs to be changed depending on the mechanism for returning /*
our set of results. */ * This needs to be changed depending on the mechanism for returning
* our set of results.
*/
if (xpresults==NULL) /*parse error (not WF or parser failure) */ if (xpresults == NULL) /* parse error (not WF or parser failure) */
{ PG_RETURN_NULL();
PG_RETURN_NULL();
}
if (ind >= (xpresults->rescount)) if (ind >= (xpresults->rescount))
{ PG_RETURN_NULL();
PG_RETURN_NULL();
}
restext = (text *) palloc(xpresults->reslens[ind]+VARHDRSZ);
memcpy(VARDATA(restext),xpresults->results[ind],xpresults->reslens[ind]);
VARATT_SIZEP(restext) = xpresults->reslens[ind]+VARHDRSZ; restext = (text *) palloc(xpresults->reslens[ind] + VARHDRSZ);
memcpy(VARDATA(restext), xpresults->results[ind], xpresults->reslens[ind]);
pfree(xpresults->resbuf); VARATT_SIZEP(restext) = xpresults->reslens[ind] + VARHDRSZ;
pfree(xpresults);
PG_RETURN_TEXT_P(restext); pfree(xpresults->resbuf);
pfree(xpresults);
PG_RETURN_TEXT_P(restext);
} }
static void pgxml_pathcompare(void *userData) static void
pgxml_pathcompare(void *userData)
{ {
char *matchpos; char *matchpos;
matchpos=strstr(UD->currentpath, UD->path); matchpos = strstr(UD->currentpath, UD->path);
if (matchpos == NULL) { /* Should we have more logic here ? */ if (matchpos == NULL)
if (UD->textgrab) { { /* Should we have more logic here ? */
UD->textgrab=0; if (UD->textgrab)
pgxml_finalisegrabbedtext(userData); {
} UD->textgrab = 0;
return; pgxml_finalisegrabbedtext(userData);
} }
/* OK, we have a match of some sort. Now we need to check that return;
our match is anchored to the *end* of the string AND
that it is immediately preceded by a '/'*/
/* This test wouldn't work if strlen (UD->path) overran the length
of the currentpath, but that's not possible because we got a match! */
if ((matchpos + strlen(UD->path))[0]=='\0')
{
if ((UD->path)[0]=='/') {
if (matchpos == UD->currentpath) {
UD->textgrab=1;
} }
} else {
if ((matchpos-1)[0]=='/') { /*
UD->textgrab=1; * OK, we have a match of some sort. Now we need to check that our
* match is anchored to the *end* of the string AND that it is
* immediately preceded by a '/'
*/
/*
* This test wouldn't work if strlen (UD->path) overran the length of
* the currentpath, but that's not possible because we got a match!
*/
if ((matchpos + strlen(UD->path))[0] == '\0')
{
if ((UD->path)[0] == '/')
{
if (matchpos == UD->currentpath)
UD->textgrab = 1;
}
else
{
if ((matchpos - 1)[0] == '/')
UD->textgrab = 1;
}
} }
}
}
} }
static void pgxml_starthandler(void *userData, const XML_Char *name, static void
const XML_Char **atts) pgxml_starthandler(void *userData, const XML_Char * name,
const XML_Char ** atts)
{ {
char sepstr[]="/"; char sepstr[] = "/";
if ((strlen(name)+strlen(UD->currentpath))>MAXPATHLENGTH-2) { if ((strlen(name) + strlen(UD->currentpath)) > MAXPATHLENGTH - 2)
elog(NOTICE,"Path too long"); elog(NOTICE, "Path too long");
} else { else
strncat(UD->currentpath,sepstr,1); {
strcat(UD->currentpath, name); strncat(UD->currentpath, sepstr, 1);
} strcat(UD->currentpath, name);
if (UD->textgrab) }
{ if (UD->textgrab)
/* Depending on user preference, should we "reconstitute" {
the element into the result text? /*
*/ * Depending on user preference, should we "reconstitute" the
} else { * element into the result text?
pgxml_pathcompare(userData); */
} }
else
pgxml_pathcompare(userData);
} }
static void pgxml_endhandler(void *userData, const XML_Char *name) static void
pgxml_endhandler(void *userData, const XML_Char * name)
{ {
/* Start by removing the current element off the end of the /*
currentpath */ * Start by removing the current element off the end of the
* currentpath
*/
char *sepptr; char *sepptr;
sepptr=strrchr(UD->currentpath,'/'); sepptr = strrchr(UD->currentpath, '/');
if (sepptr==NULL) { if (sepptr == NULL)
elog(ERROR,"There's a problem..."); {
sepptr=UD->currentpath; elog(ERROR, "There's a problem...");
} sepptr = UD->currentpath;
if (strcmp(name, sepptr+1) !=0) { }
elog(NOTICE,"Wanted [%s], got [%s]",sepptr,name); if (strcmp(name, sepptr + 1) != 0)
/* unmatched entry, so do nothing */ {
} else { elog(NOTICE, "Wanted [%s], got [%s]", sepptr, name);
sepptr[0]='\0'; /* Chop that element off the end */ /* unmatched entry, so do nothing */
} }
else
{
sepptr[0] = '\0'; /* Chop that element off the end */
}
if (UD->textgrab) { if (UD->textgrab)
pgxml_pathcompare(userData); pgxml_pathcompare(userData);
}
} }
static void pgxml_charhandler(void *userData, const XML_Char *s, int len) static void
pgxml_charhandler(void *userData, const XML_Char * s, int len)
{ {
if (UD->textgrab) { if (UD->textgrab)
if (len>0) { {
memcpy(UD->resptr,s,len); if (len > 0)
UD->resptr += len; {
UD->reslen += len; memcpy(UD->resptr, s, len);
} UD->resptr += len;
} UD->reslen += len;
}
}
} }
/* Should I be using PG list types here? */ /* Should I be using PG list types here? */
static void pgxml_finalisegrabbedtext(void *userData) static void
pgxml_finalisegrabbedtext(void *userData)
{ {
/* In res/reslen, we have a single result. */ /* In res/reslen, we have a single result. */
UD->xpres->results[UD->xpres->rescount]= UD->resptr - UD->reslen; UD->xpres->results[UD->xpres->rescount] = UD->resptr - UD->reslen;
UD->xpres->reslens[UD->xpres->rescount]= UD->reslen; UD->xpres->reslens[UD->xpres->rescount] = UD->reslen;
UD->reslen=0; UD->reslen = 0;
UD->xpres->rescount++; UD->xpres->rescount++;
/* This effectively concatenates all the results together but we /*
do know where one ends and the next begins */ * This effectively concatenates all the results together but we do
* know where one ends and the next begins
*/
} }

View File

@ -5,12 +5,12 @@ static void *pgxml_repalloc(void *ptr, size_t size);
static void pgxml_pfree(void *ptr); static void pgxml_pfree(void *ptr);
static void pgxml_mhs_init(); static void pgxml_mhs_init();
static void pgxml_handler_init(); static void pgxml_handler_init();
Datum pgxml_parse(PG_FUNCTION_ARGS); Datum pgxml_parse(PG_FUNCTION_ARGS);
Datum pgxml_xpath(PG_FUNCTION_ARGS); Datum pgxml_xpath(PG_FUNCTION_ARGS);
static void pgxml_starthandler(void *userData, const XML_Char *name, static void pgxml_starthandler(void *userData, const XML_Char * name,
const XML_Char **atts); const XML_Char ** atts);
static void pgxml_endhandler(void *userData, const XML_Char *name); static void pgxml_endhandler(void *userData, const XML_Char * name);
static void pgxml_charhandler(void *userData, const XML_Char *s, int len); static void pgxml_charhandler(void *userData, const XML_Char * s, int len);
static void pgxml_pathcompare(void *userData); static void pgxml_pathcompare(void *userData);
static void pgxml_finalisegrabbedtext(void *userData); static void pgxml_finalisegrabbedtext(void *userData);
@ -18,43 +18,25 @@ static void pgxml_finalisegrabbedtext(void *userData);
#define MAXRESULTS 100 #define MAXRESULTS 100
typedef struct { typedef struct
int rescount; {
char *results[MAXRESULTS]; int rescount;
int32 reslens[MAXRESULTS]; char *results[MAXRESULTS];
char *resbuf; /* pointer to the result buffer for pfree */ int32 reslens[MAXRESULTS];
} XPath_Results; char *resbuf; /* pointer to the result buffer for pfree */
} XPath_Results;
typedef struct { typedef struct
char currentpath[MAXPATHLENGTH]; {
char *path; char currentpath[MAXPATHLENGTH];
int textgrab; char *path;
char *resptr; int textgrab;
int32 reslen; char *resptr;
XPath_Results *xpres; int32 reslen;
} pgxml_udata; XPath_Results *xpres;
} pgxml_udata;
#define UD ((pgxml_udata *) userData) #define UD ((pgxml_udata *) userData)

View File

@ -15,50 +15,57 @@
static void *pgxml_palloc(size_t size); static void *pgxml_palloc(size_t size);
static void *pgxml_repalloc(void *ptr, size_t size); static void *pgxml_repalloc(void *ptr, size_t size);
static void pgxml_pfree(void *ptr); static void pgxml_pfree(void *ptr);
static char *pgxml_pstrdup(const char* string); static char *pgxml_pstrdup(const char *string);
static void pgxml_parser_init(); static void pgxml_parser_init();
static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset, xmlDocPtr doc, static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset, xmlDocPtr doc,
xmlChar *toptagname, xmlChar *septagname, xmlChar * toptagname, xmlChar * septagname,
int format); int format);
static xmlChar *pgxml_texttoxmlchar(text *textstring); static xmlChar *pgxml_texttoxmlchar(text *textstring);
Datum pgxml_parse(PG_FUNCTION_ARGS); Datum pgxml_parse(PG_FUNCTION_ARGS);
Datum pgxml_xpath(PG_FUNCTION_ARGS); Datum pgxml_xpath(PG_FUNCTION_ARGS);
/* memory handling passthrough functions (e.g. palloc, pstrdup are /* memory handling passthrough functions (e.g. palloc, pstrdup are
currently macros, and the others might become so...) */ currently macros, and the others might become so...) */
static void *pgxml_palloc(size_t size) static void *
pgxml_palloc(size_t size)
{ {
return palloc(size); return palloc(size);
} }
static void *pgxml_repalloc(void *ptr, size_t size) static void *
pgxml_repalloc(void *ptr, size_t size)
{ {
return repalloc(ptr,size); return repalloc(ptr, size);
} }
static void pgxml_pfree(void *ptr) static void
pgxml_pfree(void *ptr)
{ {
return pfree(ptr); return pfree(ptr);
} }
static char *pgxml_pstrdup(const char *string) static char *
pgxml_pstrdup(const char *string)
{ {
return pstrdup(string); return pstrdup(string);
} }
static void pgxml_parser_init() static void
pgxml_parser_init()
{ {
/* This code should also set parser settings from user-supplied /*
info. Quite how these settings are made is another matter :) */ * This code should also set parser settings from user-supplied info.
* Quite how these settings are made is another matter :)
*/
xmlMemSetup(pgxml_pfree, pgxml_palloc, pgxml_repalloc, pgxml_pstrdup); xmlMemSetup(pgxml_pfree, pgxml_palloc, pgxml_repalloc, pgxml_pstrdup);
xmlInitParser(); xmlInitParser();
} }
@ -70,86 +77,98 @@ PG_FUNCTION_INFO_V1(pgxml_parse);
Datum Datum
pgxml_parse(PG_FUNCTION_ARGS) pgxml_parse(PG_FUNCTION_ARGS)
{ {
/* called as pgxml_parse(document) */ /* called as pgxml_parse(document) */
xmlDocPtr doctree; xmlDocPtr doctree;
text *t = PG_GETARG_TEXT_P(0); /*document buffer */ text *t = PG_GETARG_TEXT_P(0); /* document buffer */
int32 docsize = VARSIZE(t) - VARHDRSZ; int32 docsize = VARSIZE(t) - VARHDRSZ;
pgxml_parser_init(); pgxml_parser_init();
doctree = xmlParseMemory((char *) VARDATA(t), docsize); doctree = xmlParseMemory((char *) VARDATA(t), docsize);
if (doctree == NULL) { if (doctree == NULL)
/* xmlCleanupParser(); */ {
PG_RETURN_BOOL(false); /* i.e. not well-formed */ /* xmlCleanupParser(); */
} PG_RETURN_BOOL(false); /* i.e. not well-formed */
/* xmlCleanupParser(); */ }
xmlFreeDoc(doctree); /* xmlCleanupParser(); */
PG_RETURN_BOOL(true); xmlFreeDoc(doctree);
PG_RETURN_BOOL(true);
} }
static xmlChar static xmlChar
*pgxmlNodeSetToText(xmlNodeSetPtr nodeset, *
xmlDocPtr doc, pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
xmlChar *toptagname, xmlDocPtr doc,
xmlChar *septagname, xmlChar * toptagname,
int format) xmlChar * septagname,
int format)
{ {
/* Function translates a nodeset into a text representation */ /* Function translates a nodeset into a text representation */
/* iterates over each node in the set and calls xmlNodeDump to write
it to an xmlBuffer -from which an xmlChar * string is returned. */
/* each representation is surrounded by <tagname> ... </tagname> */
/* if format==0, add a newline between nodes?? */
xmlBufferPtr buf; /*
xmlChar *result; * iterates over each node in the set and calls xmlNodeDump to write
int i; * it to an xmlBuffer -from which an xmlChar * string is returned.
*/
/* each representation is surrounded by <tagname> ... </tagname> */
/* if format==0, add a newline between nodes?? */
buf =xmlBufferCreate(); xmlBufferPtr buf;
xmlChar *result;
if ((toptagname != NULL) && (xmlStrlen(toptagname)>0)) { int i;
xmlBufferWriteChar(buf,"<");
xmlBufferWriteCHAR(buf,toptagname);
xmlBufferWriteChar(buf,">");
}
if (nodeset != NULL) {
for (i=0; i < nodeset->nodeNr; i++) {
if ((septagname != NULL) && (xmlStrlen(septagname)>0)) {
xmlBufferWriteChar(buf,"<");
xmlBufferWriteCHAR(buf,septagname);
xmlBufferWriteChar(buf,">");
}
xmlNodeDump(buf, doc, nodeset->nodeTab[i],1,(format==2));
if ((septagname != NULL) && (xmlStrlen(septagname)>0)) {
xmlBufferWriteChar(buf,"</");
xmlBufferWriteCHAR(buf,septagname);
xmlBufferWriteChar(buf,">");
}
if (format) {
xmlBufferWriteChar(buf,"\n");
}
}
}
if ((toptagname != NULL) && (xmlStrlen(toptagname)>0)) { buf = xmlBufferCreate();
xmlBufferWriteChar(buf,"</");
xmlBufferWriteCHAR(buf,toptagname); if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))
xmlBufferWriteChar(buf,">"); {
} xmlBufferWriteChar(buf, "<");
result = xmlStrdup(buf->content); xmlBufferWriteCHAR(buf, toptagname);
xmlBufferFree(buf); xmlBufferWriteChar(buf, ">");
return result; }
if (nodeset != NULL)
{
for (i = 0; i < nodeset->nodeNr; i++)
{
if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
{
xmlBufferWriteChar(buf, "<");
xmlBufferWriteCHAR(buf, septagname);
xmlBufferWriteChar(buf, ">");
}
xmlNodeDump(buf, doc, nodeset->nodeTab[i], 1, (format == 2));
if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
{
xmlBufferWriteChar(buf, "</");
xmlBufferWriteCHAR(buf, septagname);
xmlBufferWriteChar(buf, ">");
}
if (format)
xmlBufferWriteChar(buf, "\n");
}
}
if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))
{
xmlBufferWriteChar(buf, "</");
xmlBufferWriteCHAR(buf, toptagname);
xmlBufferWriteChar(buf, ">");
}
result = xmlStrdup(buf->content);
xmlBufferFree(buf);
return result;
} }
static xmlChar *pgxml_texttoxmlchar(text *textstring) { static xmlChar *
xmlChar *res; pgxml_texttoxmlchar(text *textstring)
int32 txsize; {
xmlChar *res;
int32 txsize;
txsize=VARSIZE(textstring)-VARHDRSZ; txsize = VARSIZE(textstring) - VARHDRSZ;
res = (xmlChar *) palloc(txsize+1); res = (xmlChar *) palloc(txsize + 1);
memcpy((char *)res, VARDATA(textstring), txsize); memcpy((char *) res, VARDATA(textstring), txsize);
res[txsize]='\0'; res[txsize] = '\0';
return res; return res;
} }
@ -158,81 +177,86 @@ PG_FUNCTION_INFO_V1(pgxml_xpath);
Datum Datum
pgxml_xpath(PG_FUNCTION_ARGS) pgxml_xpath(PG_FUNCTION_ARGS)
{ {
xmlDocPtr doctree; xmlDocPtr doctree;
xmlXPathContextPtr ctxt; xmlXPathContextPtr ctxt;
xmlXPathObjectPtr res; xmlXPathObjectPtr res;
xmlChar *xpath, *xpresstr, *toptag, *septag; xmlChar *xpath,
xmlXPathCompExprPtr comppath; *xpresstr,
*toptag,
*septag;
xmlXPathCompExprPtr comppath;
int32 docsize,ressize; int32 docsize,
text *t, *xpres; ressize;
text *t,
*xpres;
t = PG_GETARG_TEXT_P(0); /*document buffer */ t = PG_GETARG_TEXT_P(0); /* document buffer */
xpath = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(1)); /* XPath expression */ xpath = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(1)); /* XPath expression */
toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2)); toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3)); septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3));
docsize = VARSIZE(t) - VARHDRSZ;
pgxml_parser_init(); docsize = VARSIZE(t) - VARHDRSZ;
doctree = xmlParseMemory((char *) VARDATA(t), docsize); pgxml_parser_init();
if (doctree == NULL) { /* not well-formed */
PG_RETURN_NULL();
}
ctxt = xmlXPathNewContext(doctree); doctree = xmlParseMemory((char *) VARDATA(t), docsize);
ctxt->node = xmlDocGetRootElement(doctree); if (doctree == NULL)
{ /* not well-formed */
PG_RETURN_NULL();
}
/* compile the path */ ctxt = xmlXPathNewContext(doctree);
comppath = xmlXPathCompile(xpath); ctxt->node = xmlDocGetRootElement(doctree);
if (comppath == NULL) {
elog(NOTICE, "XPath syntax error");
xmlFreeDoc(doctree);
pfree((void *) xpath);
PG_RETURN_NULL();
}
/* Now evaluate the path expression. */ /* compile the path */
res = xmlXPathCompiledEval(comppath,ctxt); comppath = xmlXPathCompile(xpath);
xmlXPathFreeCompExpr(comppath); if (comppath == NULL)
{
elog(NOTICE, "XPath syntax error");
xmlFreeDoc(doctree);
pfree((void *) xpath);
PG_RETURN_NULL();
}
if (res==NULL) { /* Now evaluate the path expression. */
xmlFreeDoc(doctree); res = xmlXPathCompiledEval(comppath, ctxt);
pfree((void *)xpath); xmlXPathFreeCompExpr(comppath);
PG_RETURN_NULL(); /* seems appropriate */
}
/* now we dump this node, ?surrounding by tags? */
/* To do this, we look first at the type */
switch(res->type) {
case XPATH_NODESET:
xpresstr = pgxmlNodeSetToText(res->nodesetval,
doctree,
toptag, septag, 0);
break;
case XPATH_STRING:
xpresstr = xmlStrdup(res->stringval);
break;
default:
elog(NOTICE,"Unsupported XQuery result: %d",res->type);
xpresstr = xmlStrdup("<unsupported/>");
}
/* Now convert this result back to text */ if (res == NULL)
ressize = strlen(xpresstr); {
xpres = (text *) palloc(ressize+VARHDRSZ); xmlFreeDoc(doctree);
memcpy(VARDATA(xpres),xpresstr,ressize); pfree((void *) xpath);
VARATT_SIZEP(xpres)=ressize + VARHDRSZ; PG_RETURN_NULL(); /* seems appropriate */
}
/* now we dump this node, ?surrounding by tags? */
/* To do this, we look first at the type */
switch (res->type)
{
case XPATH_NODESET:
xpresstr = pgxmlNodeSetToText(res->nodesetval,
doctree,
toptag, septag, 0);
break;
case XPATH_STRING:
xpresstr = xmlStrdup(res->stringval);
break;
default:
elog(NOTICE, "Unsupported XQuery result: %d", res->type);
xpresstr = xmlStrdup("<unsupported/>");
}
/* Free various storage */
xmlFreeDoc(doctree);
pfree((void *) xpath);
xmlFree(xpresstr);
PG_RETURN_TEXT_P(xpres); /* Now convert this result back to text */
ressize = strlen(xpresstr);
xpres = (text *) palloc(ressize + VARHDRSZ);
memcpy(VARDATA(xpres), xpresstr, ressize);
VARATT_SIZEP(xpres) = ressize + VARHDRSZ;
/* Free various storage */
xmlFreeDoc(doctree);
pfree((void *) xpath);
xmlFree(xpresstr);
PG_RETURN_TEXT_P(xpres);
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.73 2001/08/23 23:06:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.74 2001/10/25 05:49:20 momjian Exp $
* *
* NOTES * NOTES
* The old interface functions have been converted to macros * The old interface functions have been converted to macros
@ -241,7 +241,6 @@ nocachegetattr(HeapTuple tuple,
} }
else else
{ {
/* /*
* there's a null somewhere in the tuple * there's a null somewhere in the tuple
*/ */
@ -347,7 +346,6 @@ nocachegetattr(HeapTuple tuple,
(HeapTupleNoNulls(tuple) || !att_isnull(j, bp)) && (HeapTupleNoNulls(tuple) || !att_isnull(j, bp)) &&
(HeapTupleAllFixed(tuple) || att[j]->attlen > 0)); j++) (HeapTupleAllFixed(tuple) || att[j]->attlen > 0)); j++)
{ {
/* /*
* Fix me when going to a machine with more than a four-byte * Fix me when going to a machine with more than a four-byte
* word! * word!
@ -546,7 +544,6 @@ heap_deformtuple(HeapTuple tuple,
nulls[i] = ' '; nulls[i] = ' ';
} }
} }
#endif #endif
/* ---------------- /* ----------------
@ -739,7 +736,7 @@ heap_freetuple(HeapTuple htup)
* *
* This routine forms a HeapTuple by copying the given structure (tuple * This routine forms a HeapTuple by copying the given structure (tuple
* data) and adding a generic header. Note that the tuple data is * data) and adding a generic header. Note that the tuple data is
* presumed to contain no null fields. It is typically only useful * presumed to contain no null fields. It is typically only useful
* for null-free system tables. * for null-free system tables.
* ---------------- * ----------------
*/ */
@ -771,7 +768,7 @@ heap_addheader(int natts, /* max domain index */
td->t_hoff = hoff; td->t_hoff = hoff;
td->t_natts = natts; td->t_natts = natts;
td->t_infomask = HEAP_XMAX_INVALID; /* XXX sufficient? */ td->t_infomask = HEAP_XMAX_INVALID; /* XXX sufficient? */
memcpy((char *) td + hoff, structure, structlen); memcpy((char *) td + hoff, structure, structlen);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.54 2001/03/22 06:16:06 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.55 2001/10/25 05:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -49,7 +49,6 @@ index_formtuple(TupleDesc tupleDescriptor,
#ifdef TOAST_INDEX_HACK #ifdef TOAST_INDEX_HACK
Datum untoasted_value[INDEX_MAX_KEYS]; Datum untoasted_value[INDEX_MAX_KEYS];
bool untoasted_free[INDEX_MAX_KEYS]; bool untoasted_free[INDEX_MAX_KEYS];
#endif #endif
if (numberOfAttributes > INDEX_MAX_KEYS) if (numberOfAttributes > INDEX_MAX_KEYS)
@ -338,7 +337,6 @@ nocache_index_getattr(IndexTuple tup,
for (; j <= attnum; j++) for (; j <= attnum; j++)
{ {
/* /*
* Fix me when going to a machine with more than a four-byte * Fix me when going to a machine with more than a four-byte
* word! * word!

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.59 2001/03/22 06:16:06 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.60 2001/10/25 05:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -197,7 +197,6 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
continue; continue;
if (OidIsValid(thisState->typoutput)) if (OidIsValid(thisState->typoutput))
{ {
/* /*
* If we have a toasted datum, forcibly detoast it here to * If we have a toasted datum, forcibly detoast it here to
* avoid memory leakage inside the type's output routine. * avoid memory leakage inside the type's output routine.
@ -306,7 +305,6 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid, if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
&typoutput, &typelem, &typisvarlena)) &typoutput, &typelem, &typisvarlena))
{ {
/* /*
* If we have a toasted datum, forcibly detoast it here to * If we have a toasted datum, forcibly detoast it here to
* avoid memory leakage inside the type's output routine. * avoid memory leakage inside the type's output routine.
@ -401,7 +399,6 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
/* send # of bytes, and opaque data */ /* send # of bytes, and opaque data */
if (thisState->typisvarlena) if (thisState->typisvarlena)
{ {
/* /*
* If we have a toasted datum, must detoast before sending. * If we have a toasted datum, must detoast before sending.
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.75 2001/06/25 21:11:43 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.76 2001/10/25 05:49:20 momjian Exp $
* *
* NOTES * NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be * some of the executor utility code such as "ExecTypeFromTL" should be
@ -238,9 +238,9 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Form_pg_attribute attr2 = tupdesc2->attrs[i]; Form_pg_attribute attr2 = tupdesc2->attrs[i];
/* /*
* We do not need to check every single field here: we can disregard * We do not need to check every single field here: we can
* attrelid, attnum (it was used to place the row in the attrs array) * disregard attrelid, attnum (it was used to place the row in the
* and everything derived from the column datatype. * attrs array) and everything derived from the column datatype.
*/ */
if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0) if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
return false; return false;
@ -399,7 +399,6 @@ TupleDescInitEntry(TupleDesc desc,
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
/* /*
* here type info does not exist yet so we just fill the attribute * here type info does not exist yet so we just fill the attribute
* with dummy information and return false. * with dummy information and return false.
@ -585,7 +584,6 @@ BuildDescForRelation(List *schema, char *relname)
typenameTypeId(typename), typenameTypeId(typename),
atttypmod, attdim, attisset)) atttypmod, attdim, attisset))
{ {
/* /*
* if TupleDescInitEntry() fails, it means there is no type in * if TupleDescInitEntry() fails, it means there is no type in
* the system catalogs. So now we check if the type name * the system catalogs. So now we check if the type name

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.30 2001/08/22 18:24:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.31 2001/10/25 05:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -251,7 +251,7 @@ gistindex_keytest(IndexTuple tuple,
if (key[0].sk_flags & SK_ISNULL) if (key[0].sk_flags & SK_ISNULL)
return false; return false;
*/ */
gistdentryinit(giststate, key[0].sk_attno-1, &de, gistdentryinit(giststate, key[0].sk_attno - 1, &de,
datum, r, p, offset, datum, r, p, offset,
IndexTupleSize(tuple) - sizeof(IndexTupleData), IndexTupleSize(tuple) - sizeof(IndexTupleData),
FALSE, isNull); FALSE, isNull);
@ -271,9 +271,9 @@ gistindex_keytest(IndexTuple tuple,
ObjectIdGetDatum(key[0].sk_procedure)); ObjectIdGetDatum(key[0].sk_procedure));
} }
if ( de.key != datum && ! isAttByVal( giststate, key[0].sk_attno-1 ) ) if (de.key != datum && !isAttByVal(giststate, key[0].sk_attno - 1))
if ( DatumGetPointer(de.key) != NULL ) if (DatumGetPointer(de.key) != NULL)
pfree( DatumGetPointer(de.key) ); pfree(DatumGetPointer(de.key));
if (DatumGetBool(test) == !!(key[0].sk_flags & SK_NEGATE)) if (DatumGetBool(test) == !!(key[0].sk_flags & SK_NEGATE))
return false; return false;

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.39 2001/08/22 18:24:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.40 2001/10/25 05:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -112,7 +112,7 @@ gistrescan(PG_FUNCTION_ARGS)
s->keyData[i].sk_procedure s->keyData[i].sk_procedure
= RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno, = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno,
s->keyData[i].sk_procedure); s->keyData[i].sk_procedure);
s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno-1]; s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
} }
} }
else else
@ -137,13 +137,13 @@ gistrescan(PG_FUNCTION_ARGS)
/*---------- /*----------
* s->keyData[i].sk_procedure = * s->keyData[i].sk_procedure =
* index_getprocid(s->relation, 1, GIST_CONSISTENT_PROC); * index_getprocid(s->relation, 1, GIST_CONSISTENT_PROC);
*---------- *----------
*/ */
s->keyData[i].sk_procedure s->keyData[i].sk_procedure
= RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno, = RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno,
s->keyData[i].sk_procedure); s->keyData[i].sk_procedure);
s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno-1]; s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
} }
} }
@ -234,8 +234,8 @@ gistendscan(PG_FUNCTION_ARGS)
{ {
gistfreestack(p->s_stack); gistfreestack(p->s_stack);
gistfreestack(p->s_markstk); gistfreestack(p->s_markstk);
if ( p->giststate != NULL ) if (p->giststate != NULL)
freeGISTstate( p->giststate ); freeGISTstate(p->giststate);
pfree(s->opaque); pfree(s->opaque);
} }
@ -383,7 +383,6 @@ adjustiptr(IndexScanDesc s,
} }
else else
{ {
/* /*
* remember that we're before the current * remember that we're before the current
* tuple * tuple

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/gist/Attic/giststrat.c,v 1.17 2001/05/30 19:53:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/gist/Attic/giststrat.c,v 1.18 2001/10/25 05:49:20 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -121,5 +121,4 @@ RelationInvokeGISTStrategy(Relation r,
return (RelationInvokeStrategy(r, &GISTEvaluationData, attnum, s, return (RelationInvokeStrategy(r, &GISTEvaluationData, attnum, s,
left, right)); left, right));
} }
#endif #endif

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.52 2001/07/15 22:48:15 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.53 2001/10/25 05:49:20 momjian Exp $
* *
* NOTES * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
@ -37,11 +37,11 @@ typedef struct
} HashBuildState; } HashBuildState;
static void hashbuildCallback(Relation index, static void hashbuildCallback(Relation index,
HeapTuple htup, HeapTuple htup,
Datum *attdata, Datum *attdata,
char *nulls, char *nulls,
bool tupleIsAlive, bool tupleIsAlive,
void *state); void *state);
/* /*
@ -80,7 +80,7 @@ hashbuild(PG_FUNCTION_ARGS)
/* do the heap scan */ /* do the heap scan */
reltuples = IndexBuildHeapScan(heap, index, indexInfo, reltuples = IndexBuildHeapScan(heap, index, indexInfo,
hashbuildCallback, (void *) &buildstate); hashbuildCallback, (void *) &buildstate);
/* all done */ /* all done */
BuildingHash = false; BuildingHash = false;
@ -121,7 +121,7 @@ hashbuildCallback(Relation index,
bool tupleIsAlive, bool tupleIsAlive,
void *state) void *state)
{ {
HashBuildState *buildstate = (HashBuildState *) state; HashBuildState *buildstate = (HashBuildState *) state;
IndexTuple itup; IndexTuple itup;
HashItem hitem; HashItem hitem;
InsertIndexResult res; InsertIndexResult res;
@ -164,6 +164,7 @@ hashinsert(PG_FUNCTION_ARGS)
Datum *datum = (Datum *) PG_GETARG_POINTER(1); Datum *datum = (Datum *) PG_GETARG_POINTER(1);
char *nulls = (char *) PG_GETARG_POINTER(2); char *nulls = (char *) PG_GETARG_POINTER(2);
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
#endif #endif
@ -176,14 +177,13 @@ hashinsert(PG_FUNCTION_ARGS)
itup->t_tid = *ht_ctid; itup->t_tid = *ht_ctid;
/* /*
* If the single index key is null, we don't insert it into the * If the single index key is null, we don't insert it into the index.
* index. Hash tables support scans on '='. Relational algebra * Hash tables support scans on '='. Relational algebra says that A =
* says that A = B returns null if either A or B is null. This * B returns null if either A or B is null. This means that no
* means that no qualification used in an index scan could ever * qualification used in an index scan could ever return true on a
* return true on a null attribute. It also means that indices * null attribute. It also means that indices can't be used by ISNULL
* can't be used by ISNULL or NOTNULL scans, but that's an * or NOTNULL scans, but that's an artifact of the strategy map
* artifact of the strategy map architecture chosen in 1986, not * architecture chosen in 1986, not of the way nulls are handled here.
* of the way nulls are handled here.
*/ */
if (IndexTupleHasNulls(itup)) if (IndexTupleHasNulls(itup))
{ {
@ -262,7 +262,6 @@ hashrescan(PG_FUNCTION_ARGS)
#ifdef NOT_USED /* XXX surely it's wrong to ignore this? */ #ifdef NOT_USED /* XXX surely it's wrong to ignore this? */
bool fromEnd = PG_GETARG_BOOL(1); bool fromEnd = PG_GETARG_BOOL(1);
#endif #endif
ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2); ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2);
ItemPointer iptr; ItemPointer iptr;
@ -412,7 +411,7 @@ hashbulkdelete(PG_FUNCTION_ARGS)
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1); IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
void *callback_state = (void *) PG_GETARG_POINTER(2); void *callback_state = (void *) PG_GETARG_POINTER(2);
IndexBulkDeleteResult *result; IndexBulkDeleteResult *result;
BlockNumber num_pages; BlockNumber num_pages;
double tuples_removed; double tuples_removed;
double num_index_tuples; double num_index_tuples;
RetrieveIndexResult res; RetrieveIndexResult res;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashinsert.c,v 1.22 2001/03/07 21:20:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashinsert.c,v 1.23 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -133,13 +133,11 @@ _hash_insertonpg(Relation rel,
while (PageGetFreeSpace(page) < itemsz) while (PageGetFreeSpace(page) < itemsz)
{ {
/* /*
* no space on this page; check for an overflow page * no space on this page; check for an overflow page
*/ */
if (BlockNumberIsValid(pageopaque->hasho_nextblkno)) if (BlockNumberIsValid(pageopaque->hasho_nextblkno))
{ {
/* /*
* ovfl page exists; go get it. if it doesn't have room, * ovfl page exists; go get it. if it doesn't have room,
* we'll find out next pass through the loop test above. * we'll find out next pass through the loop test above.
@ -152,7 +150,6 @@ _hash_insertonpg(Relation rel,
} }
else else
{ {
/* /*
* we're at the end of the bucket chain and we haven't found a * we're at the end of the bucket chain and we haven't found a
* page with enough room. allocate a new overflow page. * page with enough room. allocate a new overflow page.
@ -184,7 +181,6 @@ _hash_insertonpg(Relation rel,
if (res != NULL) if (res != NULL)
{ {
/* /*
* Increment the number of keys in the table. We switch lock * Increment the number of keys in the table. We switch lock
* access type just for a moment to allow greater accessibility to * access type just for a moment to allow greater accessibility to

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.30 2001/07/15 22:48:15 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.31 2001/10/25 05:49:21 momjian Exp $
* *
* NOTES * NOTES
* Overflow pages look like ordinary relation pages. * Overflow pages look like ordinary relation pages.
@ -208,7 +208,6 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp)
} }
else else
{ {
/* /*
* Free_bit addresses the last used bit. Bump it to address the * Free_bit addresses the last used bit. Bump it to address the
* first available bit. * first available bit.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.32 2001/07/15 22:48:15 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.33 2001/10/25 05:49:21 momjian Exp $
* *
* NOTES * NOTES
* Postgres hash pages look like ordinary relation pages. The opaque * Postgres hash pages look like ordinary relation pages. The opaque
@ -50,7 +50,7 @@ static void _hash_splitpage(Relation rel, Buffer metabuf, Bucket obucket, Bucket
* system catalogs anyway. * system catalogs anyway.
* *
* Note that our page locks are actual lockmanager locks, not buffer * Note that our page locks are actual lockmanager locks, not buffer
* locks (as are used by btree, for example). This is a good idea because * locks (as are used by btree, for example). This is a good idea because
* the algorithms are not deadlock-free, and we'd better be able to detect * the algorithms are not deadlock-free, and we'd better be able to detect
* and recover from deadlocks. * and recover from deadlocks.
* *
@ -325,7 +325,7 @@ _hash_setpagelock(Relation rel,
{ {
switch (access) switch (access)
{ {
case HASH_WRITE: case HASH_WRITE:
LockPage(rel, blkno, ExclusiveLock); LockPage(rel, blkno, ExclusiveLock);
break; break;
case HASH_READ: case HASH_READ:
@ -349,7 +349,7 @@ _hash_unsetpagelock(Relation rel,
{ {
switch (access) switch (access)
{ {
case HASH_WRITE: case HASH_WRITE:
UnlockPage(rel, blkno, ExclusiveLock); UnlockPage(rel, blkno, ExclusiveLock);
break; break;
case HASH_READ: case HASH_READ:
@ -369,7 +369,7 @@ _hash_unsetpagelock(Relation rel,
* It is safe to delete an item after acquiring a regular WRITE lock on * It is safe to delete an item after acquiring a regular WRITE lock on
* the page, because no other backend can hold a READ lock on the page, * the page, because no other backend can hold a READ lock on the page,
* and that means no other backend currently has an indexscan stopped on * and that means no other backend currently has an indexscan stopped on
* any item of the item being deleted. Our own backend might have such * any item of the item being deleted. Our own backend might have such
* an indexscan (in fact *will*, since that's how VACUUM found the item * an indexscan (in fact *will*, since that's how VACUUM found the item
* in the first place), but _hash_adjscans will fix the scan position. * in the first place), but _hash_adjscans will fix the scan position.
*/ */
@ -532,7 +532,6 @@ _hash_splitpage(Relation rel,
_hash_relbuf(rel, obuf, HASH_WRITE); _hash_relbuf(rel, obuf, HASH_WRITE);
if (!BlockNumberIsValid(oblkno)) if (!BlockNumberIsValid(oblkno))
{ {
/* /*
* the old bucket is completely empty; of course, the new * the old bucket is completely empty; of course, the new
* bucket will be as well, but since it's a base bucket page * bucket will be as well, but since it's a base bucket page
@ -559,7 +558,6 @@ _hash_splitpage(Relation rel,
omaxoffnum = PageGetMaxOffsetNumber(opage); omaxoffnum = PageGetMaxOffsetNumber(opage);
for (;;) for (;;)
{ {
/* /*
* at each iteration through this loop, each of these variables * at each iteration through this loop, each of these variables
* should be up-to-date: obuf opage oopaque ooffnum omaxoffnum * should be up-to-date: obuf opage oopaque ooffnum omaxoffnum
@ -572,7 +570,6 @@ _hash_splitpage(Relation rel,
oblkno = oopaque->hasho_nextblkno; oblkno = oopaque->hasho_nextblkno;
if (BlockNumberIsValid(oblkno)) if (BlockNumberIsValid(oblkno))
{ {
/* /*
* we ran out of tuples on this particular page, but we * we ran out of tuples on this particular page, but we
* have more overflow pages; re-init values. * have more overflow pages; re-init values.
@ -594,7 +591,6 @@ _hash_splitpage(Relation rel,
} }
else else
{ {
/* /*
* we're at the end of the bucket chain, so now we're * we're at the end of the bucket chain, so now we're
* really done with everything. before quitting, call * really done with everything. before quitting, call
@ -618,7 +614,6 @@ _hash_splitpage(Relation rel,
if (bucket == nbucket) if (bucket == nbucket)
{ {
/* /*
* insert the tuple into the new bucket. if it doesn't fit on * insert the tuple into the new bucket. if it doesn't fit on
* the current page in the new bucket, we must allocate a new * the current page in the new bucket, we must allocate a new
@ -695,7 +690,6 @@ _hash_splitpage(Relation rel,
} }
else else
{ {
/* /*
* the tuple stays on this page. we didn't move anything, so * the tuple stays on this page. we didn't move anything, so
* we didn't delete anything and therefore we don't have to * we didn't delete anything and therefore we don't have to

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashsearch.c,v 1.26 2001/03/23 04:49:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashsearch.c,v 1.27 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -36,7 +36,6 @@ _hash_search(Relation rel,
if (scankey == (ScanKey) NULL || if (scankey == (ScanKey) NULL ||
(keyDatum = scankey[0].sk_argument) == (Datum) NULL) (keyDatum = scankey[0].sk_argument) == (Datum) NULL)
{ {
/* /*
* If the scankey argument is NULL, all tuples will satisfy the * If the scankey argument is NULL, all tuples will satisfy the
* scan so we start the scan at the first bucket (bucket 0). * scan so we start the scan at the first bucket (bucket 0).

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/Attic/hashstrat.c,v 1.18 2001/05/30 19:53:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/Attic/hashstrat.c,v 1.19 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -46,7 +46,6 @@ static StrategyEvaluationData HTEvaluationData = {
(StrategyTransformMap) HTNegateCommute, (StrategyTransformMap) HTNegateCommute,
HTEvaluationExpressions HTEvaluationExpressions
}; };
#endif #endif
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
@ -68,7 +67,6 @@ _hash_getstrat(Relation rel,
return strat; return strat;
} }
#endif #endif
#ifdef NOT_USED #ifdef NOT_USED
@ -82,5 +80,4 @@ _hash_invokestrat(Relation rel,
return (RelationInvokeStrategy(rel, &HTEvaluationData, attno, strat, return (RelationInvokeStrategy(rel, &HTEvaluationData, attno, strat,
left, right)); left, right));
} }
#endif #endif

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.125 2001/08/23 23:06:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.126 2001/10/25 05:49:21 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -116,8 +116,8 @@ heapgettup(Relation relation,
{ {
ItemId lpp; ItemId lpp;
Page dp; Page dp;
BlockNumber page; BlockNumber page;
BlockNumber pages; BlockNumber pages;
int lines; int lines;
OffsetNumber lineoff; OffsetNumber lineoff;
int linesleft; int linesleft;
@ -350,7 +350,7 @@ heapgettup(Relation relation,
/* /*
* return NULL if we've exhausted all the pages * return NULL if we've exhausted all the pages
*/ */
if ((dir < 0) ? (page == 0) : (page+1 >= pages)) if ((dir < 0) ? (page == 0) : (page + 1 >= pages))
{ {
if (BufferIsValid(*buffer)) if (BufferIsValid(*buffer))
ReleaseBuffer(*buffer); ReleaseBuffer(*buffer);
@ -429,9 +429,8 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
( (
(Datum) NULL (Datum) NULL
) )
); );
} }
#endif /* defined(DISABLE_COMPLEX_MACRO) */ #endif /* defined(DISABLE_COMPLEX_MACRO) */
@ -1045,12 +1044,13 @@ heap_insert(Relation relation, HeapTuple tup)
if (relation->rd_rel->relhasoids) if (relation->rd_rel->relhasoids)
{ {
/* /*
* If the object id of this tuple has already been assigned, trust the * If the object id of this tuple has already been assigned, trust
* caller. There are a couple of ways this can happen. At initial db * the caller. There are a couple of ways this can happen. At
* creation, the backend program sets oids for tuples. When we define * initial db creation, the backend program sets oids for tuples.
* an index, we set the oid. Finally, in the future, we may allow * When we define an index, we set the oid. Finally, in the
* users to set their own object ids in order to support a persistent * future, we may allow users to set their own object ids in order
* object store (objects need to contain pointers to one another). * to support a persistent object store (objects need to contain
* pointers to one another).
*/ */
if (!OidIsValid(tup->t_data->t_oid)) if (!OidIsValid(tup->t_data->t_oid))
tup->t_data->t_oid = newoid(); tup->t_data->t_oid = newoid();
@ -1478,21 +1478,22 @@ l2:
} }
/* /*
* Now, do we need a new page for the tuple, or not? This is a bit * Now, do we need a new page for the tuple, or not? This is a
* tricky since someone else could have added tuples to the page * bit tricky since someone else could have added tuples to the
* while we weren't looking. We have to recheck the available space * page while we weren't looking. We have to recheck the
* after reacquiring the buffer lock. But don't bother to do that * available space after reacquiring the buffer lock. But don't
* if the former amount of free space is still not enough; it's * bother to do that if the former amount of free space is still
* unlikely there's more free now than before. * not enough; it's unlikely there's more free now than before.
* *
* What's more, if we need to get a new page, we will need to acquire * What's more, if we need to get a new page, we will need to acquire
* buffer locks on both old and new pages. To avoid deadlock against * buffer locks on both old and new pages. To avoid deadlock
* some other backend trying to get the same two locks in the other * against some other backend trying to get the same two locks in
* order, we must be consistent about the order we get the locks in. * the other order, we must be consistent about the order we get
* We use the rule "lock the lower-numbered page of the relation * the locks in. We use the rule "lock the lower-numbered page of
* first". To implement this, we must do RelationGetBufferForTuple * the relation first". To implement this, we must do
* while not holding the lock on the old page, and we must rely on it * RelationGetBufferForTuple while not holding the lock on the old
* to get the locks on both pages in the correct order. * page, and we must rely on it to get the locks on both pages in
* the correct order.
*/ */
if (newtupsize > pagefree) if (newtupsize > pagefree)
{ {
@ -1510,8 +1511,8 @@ l2:
{ {
/* /*
* Rats, it doesn't fit anymore. We must now unlock and * Rats, it doesn't fit anymore. We must now unlock and
* relock to avoid deadlock. Fortunately, this path should * relock to avoid deadlock. Fortunately, this path
* seldom be taken. * should seldom be taken.
*/ */
LockBuffer(buffer, BUFFER_LOCK_UNLOCK); LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
newbuf = RelationGetBufferForTuple(relation, newtup->t_len, newbuf = RelationGetBufferForTuple(relation, newtup->t_len,
@ -1534,9 +1535,9 @@ l2:
pgstat_count_heap_update(&relation->pgstat_info); pgstat_count_heap_update(&relation->pgstat_info);
/* /*
* At this point newbuf and buffer are both pinned and locked, * At this point newbuf and buffer are both pinned and locked, and
* and newbuf has enough space for the new tuple. If they are * newbuf has enough space for the new tuple. If they are the same
* the same buffer, only one pin is held. * buffer, only one pin is held.
*/ */
/* NO ELOG(ERROR) from here till changes are logged */ /* NO ELOG(ERROR) from here till changes are logged */
@ -1865,12 +1866,14 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
* Note: xlhdr is declared to have adequate size and correct alignment * Note: xlhdr is declared to have adequate size and correct alignment
* for an xl_heap_header. However the two tids, if present at all, * for an xl_heap_header. However the two tids, if present at all,
* will be packed in with no wasted space after the xl_heap_header; * will be packed in with no wasted space after the xl_heap_header;
* they aren't necessarily aligned as implied by this struct declaration. * they aren't necessarily aligned as implied by this struct
* declaration.
*/ */
struct { struct
xl_heap_header hdr; {
TransactionId tid1; xl_heap_header hdr;
TransactionId tid2; TransactionId tid1;
TransactionId tid2;
} xlhdr; } xlhdr;
int hsize = SizeOfHeapHeader; int hsize = SizeOfHeapHeader;
xl_heap_update xlrec; xl_heap_update xlrec;
@ -1972,7 +1975,7 @@ heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record)
if (record->xl_len > SizeOfHeapClean) if (record->xl_len > SizeOfHeapClean)
{ {
OffsetNumber unbuf[BLCKSZ/sizeof(OffsetNumber)]; OffsetNumber unbuf[BLCKSZ / sizeof(OffsetNumber)];
OffsetNumber *unused = unbuf; OffsetNumber *unused = unbuf;
char *unend; char *unend;
ItemId lp; ItemId lp;
@ -2084,9 +2087,10 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
if (redo) if (redo)
{ {
struct { struct
{
HeapTupleHeaderData hdr; HeapTupleHeaderData hdr;
char data[MaxTupleSize]; char data[MaxTupleSize];
} tbuf; } tbuf;
HeapTupleHeader htup; HeapTupleHeader htup;
xl_heap_header xlhdr; xl_heap_header xlhdr;
@ -2251,9 +2255,10 @@ newsame:;
if (redo) if (redo)
{ {
struct { struct
{
HeapTupleHeaderData hdr; HeapTupleHeaderData hdr;
char data[MaxTupleSize]; char data[MaxTupleSize];
} tbuf; } tbuf;
xl_heap_header xlhdr; xl_heap_header xlhdr;
int hsize; int hsize;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Id: hio.c,v 1.42 2001/07/13 22:52:58 tgl Exp $ * $Id: hio.c,v 1.43 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -83,7 +83,7 @@ RelationPutHeapTuple(Relation relation,
* NOTE: it is unlikely, but not quite impossible, for otherBuffer to be the * NOTE: it is unlikely, but not quite impossible, for otherBuffer to be the
* same buffer we select for insertion of the new tuple (this could only * same buffer we select for insertion of the new tuple (this could only
* happen if space is freed in that page after heap_update finds there's not * happen if space is freed in that page after heap_update finds there's not
* enough there). In that case, the page will be pinned and locked only once. * enough there). In that case, the page will be pinned and locked only once.
* *
* Note that we use LockPage(rel, 0) to lock relation for extension. * Note that we use LockPage(rel, 0) to lock relation for extension.
* We can do this as long as in all other places we use page-level locking * We can do this as long as in all other places we use page-level locking
@ -115,17 +115,19 @@ RelationGetBufferForTuple(Relation relation, Size len,
if (otherBuffer != InvalidBuffer) if (otherBuffer != InvalidBuffer)
otherBlock = BufferGetBlockNumber(otherBuffer); otherBlock = BufferGetBlockNumber(otherBuffer);
else else
otherBlock = InvalidBlockNumber; /* just to keep compiler quiet */ otherBlock = InvalidBlockNumber; /* just to keep compiler
* quiet */
/* /*
* We first try to put the tuple on the same page we last inserted a * We first try to put the tuple on the same page we last inserted a
* tuple on, as cached in the relcache entry. If that doesn't work, * tuple on, as cached in the relcache entry. If that doesn't work,
* we ask the shared Free Space Map to locate a suitable page. Since * we ask the shared Free Space Map to locate a suitable page. Since
* the FSM's info might be out of date, we have to be prepared to loop * the FSM's info might be out of date, we have to be prepared to loop
* around and retry multiple times. (To insure this isn't an infinite * around and retry multiple times. (To insure this isn't an infinite
* loop, we must update the FSM with the correct amount of free space on * loop, we must update the FSM with the correct amount of free space
* each page that proves not to be suitable.) If the FSM has no record of * on each page that proves not to be suitable.) If the FSM has no
* a page with enough free space, we give up and extend the relation. * record of a page with enough free space, we give up and extend the
* relation.
*/ */
targetBlock = relation->rd_targblock; targetBlock = relation->rd_targblock;
@ -137,6 +139,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
* target. * target.
*/ */
targetBlock = GetPageWithFreeSpace(&relation->rd_node, len); targetBlock = GetPageWithFreeSpace(&relation->rd_node, len);
/* /*
* If the FSM knows nothing of the rel, try the last page before * If the FSM knows nothing of the rel, try the last page before
* we give up and extend. This avoids one-tuple-per-page syndrome * we give up and extend. This avoids one-tuple-per-page syndrome
@ -144,7 +147,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
*/ */
if (targetBlock == InvalidBlockNumber) if (targetBlock == InvalidBlockNumber)
{ {
BlockNumber nblocks = RelationGetNumberOfBlocks(relation); BlockNumber nblocks = RelationGetNumberOfBlocks(relation);
if (nblocks > 0) if (nblocks > 0)
targetBlock = nblocks - 1; targetBlock = nblocks - 1;
@ -154,9 +157,9 @@ RelationGetBufferForTuple(Relation relation, Size len,
while (targetBlock != InvalidBlockNumber) while (targetBlock != InvalidBlockNumber)
{ {
/* /*
* Read and exclusive-lock the target block, as well as the * Read and exclusive-lock the target block, as well as the other
* other block if one was given, taking suitable care with * block if one was given, taking suitable care with lock ordering
* lock ordering and the possibility they are the same block. * and the possibility they are the same block.
*/ */
if (otherBuffer == InvalidBuffer) if (otherBuffer == InvalidBuffer)
{ {
@ -184,9 +187,10 @@ RelationGetBufferForTuple(Relation relation, Size len,
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE);
} }
/* /*
* Now we can check to see if there's enough free space here. * Now we can check to see if there's enough free space here. If
* If so, we're done. * so, we're done.
*/ */
pageHeader = (Page) BufferGetPage(buffer); pageHeader = (Page) BufferGetPage(buffer);
pageFreeSpace = PageGetFreeSpace(pageHeader); pageFreeSpace = PageGetFreeSpace(pageHeader);
@ -196,22 +200,22 @@ RelationGetBufferForTuple(Relation relation, Size len,
relation->rd_targblock = targetBlock; relation->rd_targblock = targetBlock;
return buffer; return buffer;
} }
/* /*
* Not enough space, so we must give up our page locks and * Not enough space, so we must give up our page locks and pin (if
* pin (if any) and prepare to look elsewhere. We don't care * any) and prepare to look elsewhere. We don't care which order
* which order we unlock the two buffers in, so this can be * we unlock the two buffers in, so this can be slightly simpler
* slightly simpler than the code above. * than the code above.
*/ */
LockBuffer(buffer, BUFFER_LOCK_UNLOCK); LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
if (otherBuffer == InvalidBuffer) if (otherBuffer == InvalidBuffer)
{
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
}
else if (otherBlock != targetBlock) else if (otherBlock != targetBlock)
{ {
LockBuffer(otherBuffer, BUFFER_LOCK_UNLOCK); LockBuffer(otherBuffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
} }
/* /*
* Update FSM as to condition of this page, and ask for another * Update FSM as to condition of this page, and ask for another
* page to try. * page to try.
@ -225,9 +229,9 @@ RelationGetBufferForTuple(Relation relation, Size len,
/* /*
* Have to extend the relation. * Have to extend the relation.
* *
* We have to use a lock to ensure no one else is extending the * We have to use a lock to ensure no one else is extending the rel at
* rel at the same time, else we will both try to initialize the * the same time, else we will both try to initialize the same new
* same new page. * page.
*/ */
if (!relation->rd_myxactonly) if (!relation->rd_myxactonly)
LockPage(relation, 0, ExclusiveLock); LockPage(relation, 0, ExclusiveLock);
@ -236,20 +240,21 @@ RelationGetBufferForTuple(Relation relation, Size len,
* XXX This does an lseek - rather expensive - but at the moment it is * XXX This does an lseek - rather expensive - but at the moment it is
* the only way to accurately determine how many blocks are in a * the only way to accurately determine how many blocks are in a
* relation. Is it worth keeping an accurate file length in shared * relation. Is it worth keeping an accurate file length in shared
* memory someplace, rather than relying on the kernel to do it for us? * memory someplace, rather than relying on the kernel to do it for
* us?
*/ */
buffer = ReadBuffer(relation, P_NEW); buffer = ReadBuffer(relation, P_NEW);
/* /*
* Release the file-extension lock; it's now OK for someone else * Release the file-extension lock; it's now OK for someone else to
* to extend the relation some more. * extend the relation some more.
*/ */
if (!relation->rd_myxactonly) if (!relation->rd_myxactonly)
UnlockPage(relation, 0, ExclusiveLock); UnlockPage(relation, 0, ExclusiveLock);
/* /*
* We can be certain that locking the otherBuffer first is OK, * We can be certain that locking the otherBuffer first is OK, since
* since it must have a lower page number. * it must have a lower page number.
*/ */
if (otherBuffer != InvalidBuffer) if (otherBuffer != InvalidBuffer)
LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE);
@ -273,7 +278,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
* *
* XXX should we enter the new page into the free space map immediately, * XXX should we enter the new page into the free space map immediately,
* or just keep it for this backend's exclusive use in the short run * or just keep it for this backend's exclusive use in the short run
* (until VACUUM sees it)? Seems to depend on whether you expect the * (until VACUUM sees it)? Seems to depend on whether you expect the
* current backend to make more insertions or not, which is probably a * current backend to make more insertions or not, which is probably a
* good bet most of the time. So for now, don't add it to FSM yet. * good bet most of the time. So for now, don't add it to FSM yet.
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/Attic/stats.c,v 1.24 2001/03/22 06:16:07 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/Attic/stats.c,v 1.25 2001/10/25 05:49:21 momjian Exp $
* *
* NOTES * NOTES
* initam should be moved someplace else. * initam should be moved someplace else.
@ -164,7 +164,6 @@ ResetHeapAccessStatistics()
time(&stats->local_reset_timestamp); time(&stats->local_reset_timestamp);
time(&stats->last_request_timestamp); time(&stats->last_request_timestamp);
} }
#endif #endif
#ifdef NOT_USED #ifdef NOT_USED
@ -200,7 +199,6 @@ GetHeapAccessStatistics()
return stats; return stats;
} }
#endif #endif
#ifdef NOT_USED #ifdef NOT_USED
@ -211,7 +209,6 @@ GetHeapAccessStatistics()
void void
PrintHeapAccessStatistics(HeapAccessStatistics stats) PrintHeapAccessStatistics(HeapAccessStatistics stats)
{ {
/* /*
* return nothing if stats aren't valid * return nothing if stats aren't valid
*/ */
@ -302,7 +299,6 @@ PrintHeapAccessStatistics(HeapAccessStatistics stats)
printf("\n"); printf("\n");
} }
#endif #endif
#ifdef NOT_USED #ifdef NOT_USED
@ -317,7 +313,6 @@ PrintAndFreeHeapAccessStatistics(HeapAccessStatistics stats)
if (stats != NULL) if (stats != NULL)
pfree(stats); pfree(stats);
} }
#endif #endif
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
@ -331,7 +326,6 @@ PrintAndFreeHeapAccessStatistics(HeapAccessStatistics stats)
void void
initam(void) initam(void)
{ {
/* /*
* initialize heap statistics. * initialize heap statistics.
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.24 2001/08/10 18:57:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.25 2001/10/25 05:49:21 momjian Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -74,14 +74,13 @@ heap_tuple_toast_attrs(Relation rel, HeapTuple newtup, HeapTuple oldtup)
* external storage (possibly still in compressed format). * external storage (possibly still in compressed format).
* ---------- * ----------
*/ */
varattrib * varattrib *
heap_tuple_fetch_attr(varattrib *attr) heap_tuple_fetch_attr(varattrib *attr)
{ {
varattrib *result; varattrib *result;
if (VARATT_IS_EXTERNAL(attr)) if (VARATT_IS_EXTERNAL(attr))
{ {
/* /*
* This is an external stored plain value * This is an external stored plain value
*/ */
@ -89,7 +88,6 @@ heap_tuple_fetch_attr(varattrib *attr)
} }
else else
{ {
/* /*
* This is a plain value inside of the main tuple - why am I * This is a plain value inside of the main tuple - why am I
* called? * called?
@ -108,7 +106,7 @@ heap_tuple_fetch_attr(varattrib *attr)
* or external storage. * or external storage.
* ---------- * ----------
*/ */
varattrib * varattrib *
heap_tuple_untoast_attr(varattrib *attr) heap_tuple_untoast_attr(varattrib *attr)
{ {
varattrib *result; varattrib *result;
@ -135,7 +133,6 @@ heap_tuple_untoast_attr(varattrib *attr)
} }
else else
{ {
/* /*
* This is an external stored plain value * This is an external stored plain value
*/ */
@ -144,7 +141,6 @@ heap_tuple_untoast_attr(varattrib *attr)
} }
else if (VARATT_IS_COMPRESSED(attr)) else if (VARATT_IS_COMPRESSED(attr))
{ {
/* /*
* This is a compressed value inside of the main tuple * This is a compressed value inside of the main tuple
*/ */
@ -181,8 +177,8 @@ toast_raw_datum_size(Datum value)
if (VARATT_IS_COMPRESSED(attr)) if (VARATT_IS_COMPRESSED(attr))
{ {
/* /*
* va_rawsize shows the original data size, whether the datum * va_rawsize shows the original data size, whether the datum is
* is external or not. * external or not.
*/ */
result = attr->va_content.va_compressed.va_rawsize + VARHDRSZ; result = attr->va_content.va_compressed.va_rawsize + VARHDRSZ;
} }
@ -301,7 +297,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
if (oldtup != NULL) if (oldtup != NULL)
{ {
/* /*
* For UPDATE get the old and new values of this attribute * For UPDATE get the old and new values of this attribute
*/ */
@ -324,7 +319,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
old_value->va_content.va_external.va_toastrelid != old_value->va_content.va_external.va_toastrelid !=
new_value->va_content.va_external.va_toastrelid) new_value->va_content.va_external.va_toastrelid)
{ {
/* /*
* The old external store value isn't needed any more * The old external store value isn't needed any more
* after the update * after the update
@ -334,7 +328,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
} }
else else
{ {
/* /*
* This attribute isn't changed by this update so we * This attribute isn't changed by this update so we
* reuse the original reference to the old value in * reuse the original reference to the old value in
@ -348,7 +341,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
} }
else else
{ {
/* /*
* For INSERT simply get the new value * For INSERT simply get the new value
*/ */
@ -372,7 +364,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
*/ */
if (att[i]->attlen == -1) if (att[i]->attlen == -1)
{ {
/* /*
* If the table's attribute says PLAIN always, force it so. * If the table's attribute says PLAIN always, force it so.
*/ */
@ -400,7 +391,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
} }
else else
{ {
/* /*
* Not a variable size attribute, plain storage always * Not a variable size attribute, plain storage always
*/ */
@ -475,7 +465,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
} }
else else
{ {
/* /*
* incompressible data, ignore on subsequent compression * incompressible data, ignore on subsequent compression
* passes * passes
@ -588,7 +577,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
} }
else else
{ {
/* /*
* incompressible data, ignore on subsequent compression * incompressible data, ignore on subsequent compression
* passes * passes
@ -776,9 +764,10 @@ toast_save_datum(Relation rel, Datum value)
Datum t_values[3]; Datum t_values[3];
char t_nulls[3]; char t_nulls[3];
varattrib *result; varattrib *result;
struct { struct
struct varlena hdr; {
char data[TOAST_MAX_CHUNK_SIZE]; struct varlena hdr;
char data[TOAST_MAX_CHUNK_SIZE];
} chunk_data; } chunk_data;
int32 chunk_size; int32 chunk_size;
int32 chunk_seq = 0; int32 chunk_seq = 0;
@ -851,12 +840,12 @@ toast_save_datum(Relation rel, Datum value)
heap_insert(toastrel, toasttup); heap_insert(toastrel, toasttup);
/* /*
* Create the index entry. We cheat a little here by not using * Create the index entry. We cheat a little here by not using
* FormIndexDatum: this relies on the knowledge that the index * FormIndexDatum: this relies on the knowledge that the index
* columns are the same as the initial columns of the table. * columns are the same as the initial columns of the table.
* *
* Note also that there had better not be any user-created index * Note also that there had better not be any user-created index on
* on the TOAST table, since we don't bother to update anything else. * the TOAST table, since we don't bother to update anything else.
*/ */
idxres = index_insert(toastidx, t_values, t_nulls, idxres = index_insert(toastidx, t_values, t_nulls,
&(toasttup->t_self), &(toasttup->t_self),
@ -916,8 +905,8 @@ toast_delete_datum(Relation rel, Datum value)
toastidx = index_open(toastrel->rd_rel->reltoastidxid); toastidx = index_open(toastrel->rd_rel->reltoastidxid);
/* /*
* Setup a scan key to fetch from the index by va_valueid * Setup a scan key to fetch from the index by va_valueid (we don't
* (we don't particularly care whether we see them in sequence or not) * particularly care whether we see them in sequence or not)
*/ */
ScanKeyEntryInitialize(&toastkey, ScanKeyEntryInitialize(&toastkey,
(bits16) 0, (bits16) 0,
@ -1096,5 +1085,4 @@ toast_fetch_datum(varattrib *attr)
return result; return result;
} }
#endif /* TUPLE_TOASTER_ACTIVE */ #endif /* TUPLE_TOASTER_ACTIVE */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.28 2001/06/22 19:16:21 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.29 2001/10/25 05:49:21 momjian Exp $
* *
* NOTES * NOTES
* many of the old access method routines have been turned into * many of the old access method routines have been turned into
@ -240,5 +240,4 @@ IndexScanRestorePosition(IndexScanDesc scan)
scan->flags = 0x0; /* XXX should have a symbolic name */ scan->flags = 0x0; /* XXX should have a symbolic name */
} }
#endif #endif

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.53 2001/10/06 23:21:43 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.54 2001/10/25 05:49:21 momjian Exp $
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
* index_open - open an index relation by relationId * index_open - open an index relation by relationId
@ -241,9 +241,9 @@ index_beginscan(Relation relation,
pgstat_initstats(&scan->xs_pgstat_info, relation); pgstat_initstats(&scan->xs_pgstat_info, relation);
/* /*
* We want to look up the amgettuple procedure just once per scan, * We want to look up the amgettuple procedure just once per scan, not
* not once per index_getnext call. So do it here and save * once per index_getnext call. So do it here and save the fmgr info
* the fmgr info result in the scan descriptor. * result in the scan descriptor.
*/ */
GET_SCAN_PROCEDURE(beginscan, amgettuple); GET_SCAN_PROCEDURE(beginscan, amgettuple);
fmgr_info(procedure, &scan->fn_getnext); fmgr_info(procedure, &scan->fn_getnext);
@ -342,8 +342,8 @@ index_getnext(IndexScanDesc scan,
pgstat_count_index_scan(&scan->xs_pgstat_info); pgstat_count_index_scan(&scan->xs_pgstat_info);
/* /*
* have the am's gettuple proc do all the work. * have the am's gettuple proc do all the work. index_beginscan
* index_beginscan already set up fn_getnext. * already set up fn_getnext.
*/ */
result = (RetrieveIndexResult) result = (RetrieveIndexResult)
DatumGetPointer(FunctionCall2(&scan->fn_getnext, DatumGetPointer(FunctionCall2(&scan->fn_getnext,
@ -378,8 +378,8 @@ index_bulk_delete(Relation relation,
result = (IndexBulkDeleteResult *) result = (IndexBulkDeleteResult *)
DatumGetPointer(OidFunctionCall3(procedure, DatumGetPointer(OidFunctionCall3(procedure,
PointerGetDatum(relation), PointerGetDatum(relation),
PointerGetDatum((Pointer) callback), PointerGetDatum((Pointer) callback),
PointerGetDatum(callback_state))); PointerGetDatum(callback_state)));
return result; return result;
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.53 2001/10/06 23:21:43 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.54 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -120,9 +120,9 @@ StrategyOperatorIsValid(StrategyOperator operator,
StrategyNumber maxStrategy) StrategyNumber maxStrategy)
{ {
return (bool) return (bool)
(PointerIsValid(operator) && (PointerIsValid(operator) &&
StrategyNumberIsInBounds(operator->strategy, maxStrategy) && StrategyNumberIsInBounds(operator->strategy, maxStrategy) &&
!(operator->flags & ~(SK_NEGATE | SK_COMMUTE))); !(operator->flags & ~(SK_NEGATE | SK_COMMUTE)));
} }
/* ---------------- /* ----------------
@ -196,7 +196,6 @@ StrategyEvaluationIsValid(StrategyEvaluation evaluation)
} }
return true; return true;
} }
#endif #endif
#ifdef NOT_USED #ifdef NOT_USED
@ -255,7 +254,6 @@ StrategyTermEvaluate(StrategyTerm term,
return result; return result;
} }
#endif #endif
/* ---------------- /* ----------------
@ -453,7 +451,6 @@ RelationInvokeStrategy(Relation relation,
/* not reached, just to make compiler happy */ /* not reached, just to make compiler happy */
return FALSE; return FALSE;
} }
#endif #endif
/* ---------------- /* ----------------
@ -552,7 +549,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
{ {
for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++) for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
{ {
Oid opclass = operatorClassObjectId[attIndex]; Oid opclass = operatorClassObjectId[attIndex];
RegProcedure *loc; RegProcedure *loc;
StrategyNumber support; StrategyNumber support;
@ -562,7 +559,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
{ {
tuple = SearchSysCache(AMPROCNUM, tuple = SearchSysCache(AMPROCNUM,
ObjectIdGetDatum(opclass), ObjectIdGetDatum(opclass),
Int16GetDatum(support+1), Int16GetDatum(support + 1),
0, 0); 0, 0);
if (HeapTupleIsValid(tuple)) if (HeapTupleIsValid(tuple))
{ {
@ -581,7 +578,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
/* Now load the strategy information for the index operators */ /* Now load the strategy information for the index operators */
for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++) for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
{ {
Oid opclass = operatorClassObjectId[attIndex]; Oid opclass = operatorClassObjectId[attIndex];
StrategyMap map; StrategyMap map;
StrategyNumber strategy; StrategyNumber strategy;
@ -591,7 +588,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
for (strategy = 1; strategy <= maxStrategyNumber; strategy++) for (strategy = 1; strategy <= maxStrategyNumber; strategy++)
{ {
ScanKey mapentry = StrategyMapGetScanKeyEntry(map, strategy); ScanKey mapentry = StrategyMapGetScanKeyEntry(map, strategy);
tuple = SearchSysCache(AMOPSTRATEGY, tuple = SearchSysCache(AMOPSTRATEGY,
ObjectIdGetDatum(opclass), ObjectIdGetDatum(opclass),
@ -643,5 +640,4 @@ IndexStrategyDisplay(IndexStrategy indexStrategy,
} }
} }
} }
#endif /* defined(ISTRATDEBUG) */ #endif /* defined(ISTRATDEBUG) */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.42 2001/05/03 19:00:36 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.43 2001/10/25 05:49:21 momjian Exp $
* *
* NOTES * NOTES
* *
@ -25,7 +25,7 @@
* NOTE: although any negative int32 is acceptable for reporting "<", * NOTE: although any negative int32 is acceptable for reporting "<",
* and any positive int32 is acceptable for reporting ">", routines * and any positive int32 is acceptable for reporting ">", routines
* that work on 32-bit or wider datatypes can't just return "a - b". * that work on 32-bit or wider datatypes can't just return "a - b".
* That could overflow and give the wrong answer. Also, one should not * That could overflow and give the wrong answer. Also, one should not
* return INT_MIN to report "<", since some callers will negate the result. * return INT_MIN to report "<", since some callers will negate the result.
* *
* NOTE: it is critical that the comparison function impose a total order * NOTE: it is critical that the comparison function impose a total order

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.86 2001/09/29 23:49:51 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.87 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1100,7 +1100,7 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
* If we are not on the leaf level, we will be able to discard the key * If we are not on the leaf level, we will be able to discard the key
* data from the first item that winds up on the right page. * data from the first item that winds up on the right page.
*/ */
if (! state->is_leaf) if (!state->is_leaf)
rightfree += (int) firstrightitemsz - rightfree += (int) firstrightitemsz -
(int) (MAXALIGN(sizeof(BTItemData)) + sizeof(ItemIdData)); (int) (MAXALIGN(sizeof(BTItemData)) + sizeof(ItemIdData));
@ -1115,7 +1115,8 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
{ {
/* /*
* On a rightmost page, try to equalize right free space with * On a rightmost page, try to equalize right free space with
* twice the left free space. See comments for _bt_findsplitloc. * twice the left free space. See comments for
* _bt_findsplitloc.
*/ */
delta = (2 * leftfree) - rightfree; delta = (2 * leftfree) - rightfree;
} }
@ -1618,7 +1619,6 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
for (;;) for (;;)
{ {
/* /*
* Read up to 2 more child pages and look for pointers to them in * Read up to 2 more child pages and look for pointers to them in
* *saved* parent page * *saved* parent page

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.53 2001/07/15 22:48:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.54 2001/10/25 05:49:21 momjian Exp $
* *
* NOTES * NOTES
* Postgres btree pages look like ordinary relation pages. The opaque * Postgres btree pages look like ordinary relation pages. The opaque
@ -153,7 +153,6 @@ _bt_getroot(Relation rel, int access)
*/ */
if (metad->btm_root == P_NONE) if (metad->btm_root == P_NONE)
{ {
/* /*
* Get, initialize, write, and leave a lock of the appropriate * Get, initialize, write, and leave a lock of the appropriate
* type on the new root page. Since this is the first page in * type on the new root page. Since this is the first page in
@ -209,7 +208,6 @@ _bt_getroot(Relation rel, int access)
} }
else else
{ {
/* /*
* Metadata initialized by someone else. In order to * Metadata initialized by someone else. In order to
* guarantee no deadlocks, we have to release the metadata * guarantee no deadlocks, we have to release the metadata
@ -237,7 +235,6 @@ _bt_getroot(Relation rel, int access)
if (!P_ISROOT(rootopaque)) if (!P_ISROOT(rootopaque))
{ {
/* /*
* It happened, but if root page splitter failed to create new * It happened, but if root page splitter failed to create new
* root page then we'll go in loop trying to call _bt_getroot * root page then we'll go in loop trying to call _bt_getroot
@ -402,7 +399,6 @@ _bt_wrtnorelbuf(Relation rel, Buffer buf)
void void
_bt_pageinit(Page page, Size size) _bt_pageinit(Page page, Size size)
{ {
/* /*
* Cargo_cult programming -- don't really need this to be zero, but * Cargo_cult programming -- don't really need this to be zero, but
* creating new pages is an infrequent occurrence and it makes me feel * creating new pages is an infrequent occurrence and it makes me feel

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.82 2001/07/15 22:48:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.83 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -37,6 +37,7 @@ typedef struct
bool haveDead; bool haveDead;
Relation heapRel; Relation heapRel;
BTSpool *spool; BTSpool *spool;
/* /*
* spool2 is needed only when the index is an unique index. Dead * spool2 is needed only when the index is an unique index. Dead
* tuples are put into spool2 instead of spool in order to avoid * tuples are put into spool2 instead of spool in order to avoid
@ -58,11 +59,11 @@ bool FixBTree = true;
static void _bt_restscan(IndexScanDesc scan); static void _bt_restscan(IndexScanDesc scan);
static void btbuildCallback(Relation index, static void btbuildCallback(Relation index,
HeapTuple htup, HeapTuple htup,
Datum *attdata, Datum *attdata,
char *nulls, char *nulls,
bool tupleIsAlive, bool tupleIsAlive,
void *state); void *state);
/* /*
@ -134,6 +135,7 @@ btbuild(PG_FUNCTION_ARGS)
if (buildstate.usefast) if (buildstate.usefast)
{ {
buildstate.spool = _bt_spoolinit(index, indexInfo->ii_Unique); buildstate.spool = _bt_spoolinit(index, indexInfo->ii_Unique);
/* /*
* Different from spool, the uniqueness isn't checked for spool2. * Different from spool, the uniqueness isn't checked for spool2.
*/ */
@ -214,7 +216,7 @@ btbuildCallback(Relation index,
bool tupleIsAlive, bool tupleIsAlive,
void *state) void *state)
{ {
BTBuildState *buildstate = (BTBuildState *) state; BTBuildState *buildstate = (BTBuildState *) state;
IndexTuple itup; IndexTuple itup;
BTItem btitem; BTItem btitem;
InsertIndexResult res; InsertIndexResult res;
@ -226,9 +228,9 @@ btbuildCallback(Relation index,
btitem = _bt_formitem(itup); btitem = _bt_formitem(itup);
/* /*
* if we are doing bottom-up btree build, we insert the index into * if we are doing bottom-up btree build, we insert the index into a
* a spool file for subsequent processing. otherwise, we insert * spool file for subsequent processing. otherwise, we insert into
* into the btree. * the btree.
*/ */
if (buildstate->usefast) if (buildstate->usefast)
{ {
@ -305,7 +307,6 @@ btgettuple(PG_FUNCTION_ARGS)
if (ItemPointerIsValid(&(scan->currentItemData))) if (ItemPointerIsValid(&(scan->currentItemData)))
{ {
/* /*
* Restore scan position using heap TID returned by previous call * Restore scan position using heap TID returned by previous call
* to btgettuple(). _bt_restscan() re-grabs the read lock on the * to btgettuple(). _bt_restscan() re-grabs the read lock on the
@ -321,7 +322,7 @@ btgettuple(PG_FUNCTION_ARGS)
* Save heap TID to use it in _bt_restscan. Then release the read * Save heap TID to use it in _bt_restscan. Then release the read
* lock on the buffer so that we aren't blocking other backends. * lock on the buffer so that we aren't blocking other backends.
* *
* NOTE: we do keep the pin on the buffer! This is essential to ensure * NOTE: we do keep the pin on the buffer! This is essential to ensure
* that someone else doesn't delete the index entry we are stopped on. * that someone else doesn't delete the index entry we are stopped on.
*/ */
if (res) if (res)
@ -362,7 +363,6 @@ btrescan(PG_FUNCTION_ARGS)
#ifdef NOT_USED /* XXX surely it's wrong to ignore this? */ #ifdef NOT_USED /* XXX surely it's wrong to ignore this? */
bool fromEnd = PG_GETARG_BOOL(1); bool fromEnd = PG_GETARG_BOOL(1);
#endif #endif
ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2); ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2);
ItemPointer iptr; ItemPointer iptr;
@ -547,7 +547,7 @@ btbulkdelete(PG_FUNCTION_ARGS)
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1); IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
void *callback_state = (void *) PG_GETARG_POINTER(2); void *callback_state = (void *) PG_GETARG_POINTER(2);
IndexBulkDeleteResult *result; IndexBulkDeleteResult *result;
BlockNumber num_pages; BlockNumber num_pages;
double tuples_removed; double tuples_removed;
double num_index_tuples; double num_index_tuples;
RetrieveIndexResult res; RetrieveIndexResult res;
@ -559,15 +559,16 @@ btbulkdelete(PG_FUNCTION_ARGS)
num_index_tuples = 0; num_index_tuples = 0;
/* /*
* We use a standard IndexScanDesc scan object, but to speed up the loop, * We use a standard IndexScanDesc scan object, but to speed up the
* we skip most of the wrapper layers of index_getnext and instead call * loop, we skip most of the wrapper layers of index_getnext and
* _bt_step directly. This implies holding buffer lock on a target page * instead call _bt_step directly. This implies holding buffer lock
* throughout the loop over the page's tuples. Initially, we have a read * on a target page throughout the loop over the page's tuples.
* lock acquired by _bt_step when we stepped onto the page. If we find * Initially, we have a read lock acquired by _bt_step when we stepped
* a tuple we need to delete, we trade in the read lock for an exclusive * onto the page. If we find a tuple we need to delete, we trade in
* write lock; after that, we hold the write lock until we step off the * the read lock for an exclusive write lock; after that, we hold the
* page (fortunately, _bt_relbuf doesn't care which kind of lock it's * write lock until we step off the page (fortunately, _bt_relbuf
* releasing). This should minimize the amount of work needed per page. * doesn't care which kind of lock it's releasing). This should
* minimize the amount of work needed per page.
*/ */
scan = index_beginscan(rel, false, 0, (ScanKey) NULL); scan = index_beginscan(rel, false, 0, (ScanKey) NULL);
so = (BTScanOpaque) scan->opaque; so = (BTScanOpaque) scan->opaque;
@ -579,7 +580,7 @@ btbulkdelete(PG_FUNCTION_ARGS)
if (res != NULL) if (res != NULL)
{ {
Buffer buf; Buffer buf;
BlockNumber lockedBlock = InvalidBlockNumber; BlockNumber lockedBlock = InvalidBlockNumber;
pfree(res); pfree(res);
/* we have the buffer pinned and locked */ /* we have the buffer pinned and locked */
@ -589,11 +590,11 @@ btbulkdelete(PG_FUNCTION_ARGS)
do do
{ {
Page page; Page page;
BlockNumber blkno; BlockNumber blkno;
OffsetNumber offnum; OffsetNumber offnum;
BTItem btitem; BTItem btitem;
IndexTuple itup; IndexTuple itup;
ItemPointer htup; ItemPointer htup;
/* current is the next index tuple */ /* current is the next index tuple */
blkno = ItemPointerGetBlockNumber(current); blkno = ItemPointerGetBlockNumber(current);
@ -607,9 +608,10 @@ btbulkdelete(PG_FUNCTION_ARGS)
{ {
/* /*
* If this is first deletion on this page, trade in read * If this is first deletion on this page, trade in read
* lock for a really-exclusive write lock. Then, step back * lock for a really-exclusive write lock. Then, step
* one and re-examine the item, because someone else might * back one and re-examine the item, because someone else
* have inserted an item while we weren't holding the lock! * might have inserted an item while we weren't holding
* the lock!
*/ */
if (blkno != lockedBlock) if (blkno != lockedBlock)
{ {
@ -632,8 +634,8 @@ btbulkdelete(PG_FUNCTION_ARGS)
* We need to back up the scan one item so that the next * We need to back up the scan one item so that the next
* cycle will re-examine the same offnum on this page. * cycle will re-examine the same offnum on this page.
* *
* For now, just hack the current-item index. Will need * For now, just hack the current-item index. Will need to
* to be smarter when deletion includes removal of empty * be smarter when deletion includes removal of empty
* index pages. * index pages.
*/ */
current->ip_posid--; current->ip_posid--;

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.68 2001/10/06 23:21:43 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.69 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -589,10 +589,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
/* /*
* At this point we are positioned at the first item >= scan key, or * At this point we are positioned at the first item >= scan key, or
* possibly at the end of a page on which all the existing items are * possibly at the end of a page on which all the existing items are
* greater than the scan key and we know that everything on later pages * greater than the scan key and we know that everything on later
* is less than or equal to scan key. * pages is less than or equal to scan key.
* *
* We could step forward in the latter case, but that'd be a waste of * We could step forward in the latter case, but that'd be a waste of
* time if we want to scan backwards. So, it's now time to examine * time if we want to scan backwards. So, it's now time to examine
* the scan strategy to find the exact place to start the scan. * the scan strategy to find the exact place to start the scan.

View File

@ -35,7 +35,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.60 2001/03/22 03:59:15 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.61 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -108,7 +108,7 @@ static void _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2);
/* /*
* create and initialize a spool structure * create and initialize a spool structure
*/ */
BTSpool * BTSpool *
_bt_spoolinit(Relation index, bool isunique) _bt_spoolinit(Relation index, bool isunique)
{ {
BTSpool *btspool = (BTSpool *) palloc(sizeof(BTSpool)); BTSpool *btspool = (BTSpool *) palloc(sizeof(BTSpool));
@ -354,7 +354,6 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti)
if (pgspc < btisz || pgspc < state->btps_full) if (pgspc < btisz || pgspc < state->btps_full)
{ {
/* /*
* Item won't fit on this page, or we feel the page is full enough * Item won't fit on this page, or we feel the page is full enough
* already. Finish off the page and write it out. * already. Finish off the page and write it out.
@ -544,7 +543,6 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
if (merge) if (merge)
{ {
/* /*
* Another BTSpool for dead tuples exists. Now we have to merge * Another BTSpool for dead tuples exists. Now we have to merge
* btspool and btspool2. * btspool and btspool2.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/Attic/nbtstrat.c,v 1.14 2001/05/30 19:53:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/Attic/nbtstrat.c,v 1.15 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -134,5 +134,4 @@ _bt_invokestrat(Relation rel,
return (RelationInvokeStrategy(rel, &BTEvaluationData, attno, strat, return (RelationInvokeStrategy(rel, &BTEvaluationData, attno, strat,
left, right)); left, right));
} }
#endif #endif

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.46 2001/10/06 23:21:43 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.47 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -221,7 +221,6 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
/* We can short-circuit most of the work if there's just one key */ /* We can short-circuit most of the work if there's just one key */
if (numberOfKeys == 1) if (numberOfKeys == 1)
{ {
/* /*
* We don't use indices for 'A is null' and 'A is not null' * We don't use indices for 'A is null' and 'A is not null'
* currently and 'A < = > <> NULL' will always fail - so qual is * currently and 'A < = > <> NULL' will always fail - so qual is
@ -317,7 +316,6 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
} }
else else
{ {
/* /*
* No "=" for this key, so we're done with required keys * No "=" for this key, so we're done with required keys
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.65 2001/10/06 23:21:43 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.66 2001/10/25 05:49:21 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -58,9 +58,9 @@ typedef struct SPLITVEC
/* for sorting tuples by cost, for picking split */ /* for sorting tuples by cost, for picking split */
typedef struct SPLITCOST typedef struct SPLITCOST
{ {
OffsetNumber offset_number; OffsetNumber offset_number;
float cost_differential; float cost_differential;
bool choose_left; bool choose_left;
} SPLITCOST; } SPLITCOST;
typedef struct RTSTATE typedef struct RTSTATE
@ -79,11 +79,11 @@ typedef struct
/* non-export function prototypes */ /* non-export function prototypes */
static void rtbuildCallback(Relation index, static void rtbuildCallback(Relation index,
HeapTuple htup, HeapTuple htup,
Datum *attdata, Datum *attdata,
char *nulls, char *nulls,
bool tupleIsAlive, bool tupleIsAlive,
void *state); void *state);
static InsertIndexResult rtdoinsert(Relation r, IndexTuple itup, static InsertIndexResult rtdoinsert(Relation r, IndexTuple itup,
RTSTATE *rtstate); RTSTATE *rtstate);
static void rttighten(Relation r, RTSTACK *stk, Datum datum, int att_size, static void rttighten(Relation r, RTSTACK *stk, Datum datum, int att_size,
@ -100,7 +100,7 @@ static OffsetNumber choose(Relation r, Page p, IndexTuple it,
RTSTATE *rtstate); RTSTATE *rtstate);
static int nospace(Page p, IndexTuple it); static int nospace(Page p, IndexTuple it);
static void initRtstate(RTSTATE *rtstate, Relation index); static void initRtstate(RTSTATE *rtstate, Relation index);
static int qsort_comp_splitcost(const void *a, const void *b); static int qsort_comp_splitcost(const void *a, const void *b);
/* /*
@ -178,7 +178,7 @@ rtbuildCallback(Relation index,
bool tupleIsAlive, bool tupleIsAlive,
void *state) void *state)
{ {
RTBuildState *buildstate = (RTBuildState *) state; RTBuildState *buildstate = (RTBuildState *) state;
IndexTuple itup; IndexTuple itup;
InsertIndexResult res; InsertIndexResult res;
@ -194,11 +194,11 @@ rtbuildCallback(Relation index,
} }
/* /*
* Since we already have the index relation locked, we call * Since we already have the index relation locked, we call rtdoinsert
* rtdoinsert directly. Normal access method calls dispatch * directly. Normal access method calls dispatch through rtinsert,
* through rtinsert, which locks the relation for write. This is * which locks the relation for write. This is the right thing to do
* the right thing to do if you're inserting single tups, but not * if you're inserting single tups, but not when you're initializing
* when you're initializing the whole index at once. * the whole index at once.
*/ */
res = rtdoinsert(index, itup, &buildstate->rtState); res = rtdoinsert(index, itup, &buildstate->rtState);
@ -223,6 +223,7 @@ rtinsert(PG_FUNCTION_ARGS)
Datum *datum = (Datum *) PG_GETARG_POINTER(1); Datum *datum = (Datum *) PG_GETARG_POINTER(1);
char *nulls = (char *) PG_GETARG_POINTER(2); char *nulls = (char *) PG_GETARG_POINTER(2);
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
#ifdef NOT_USED #ifdef NOT_USED
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
#endif #endif
@ -249,7 +250,7 @@ rtinsert(PG_FUNCTION_ARGS)
/* /*
* Since rtree is not marked "amconcurrent" in pg_am, caller should * Since rtree is not marked "amconcurrent" in pg_am, caller should
* have acquired exclusive lock on index relation. We need no locking * have acquired exclusive lock on index relation. We need no locking
* here. * here.
*/ */
@ -376,9 +377,8 @@ rttighten(Relation r,
PointerGetDatum(&newd_size)); PointerGetDatum(&newd_size));
/* /*
* If newd_size == 0 we have degenerate rectangles, so we * If newd_size == 0 we have degenerate rectangles, so we don't know
* don't know if there was any change, so we have to * if there was any change, so we have to assume there was.
* assume there was.
*/ */
if ((newd_size == 0) || (newd_size != old_size)) if ((newd_size == 0) || (newd_size != old_size))
{ {
@ -386,7 +386,6 @@ rttighten(Relation r,
if (td->attrs[0]->attlen < 0) if (td->attrs[0]->attlen < 0)
{ {
/* /*
* This is an internal page, so 'oldud' had better be a union * This is an internal page, so 'oldud' had better be a union
* (constant-length) key, too. (See comment below.) * (constant-length) key, too. (See comment below.)
@ -500,10 +499,10 @@ rtdosplit(Relation r,
res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData)); res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
/* /*
* spl_left contains a list of the offset numbers of the * spl_left contains a list of the offset numbers of the tuples that
* tuples that will go to the left page. For each offset * will go to the left page. For each offset number, get the tuple
* number, get the tuple item, then add the item to the * item, then add the item to the left page. Similarly for the right
* left page. Similarly for the right side. * side.
*/ */
/* fill left node */ /* fill left node */
@ -527,7 +526,7 @@ rtdosplit(Relation r,
if (i == newitemoff) if (i == newitemoff)
ItemPointerSet(&(res->pointerData), lbknum, leftoff); ItemPointerSet(&(res->pointerData), lbknum, leftoff);
spl_left++; /* advance in left split vector */ spl_left++; /* advance in left split vector */
} }
/* fill right node */ /* fill right node */
@ -551,7 +550,7 @@ rtdosplit(Relation r,
if (i == newitemoff) if (i == newitemoff)
ItemPointerSet(&(res->pointerData), rbknum, rightoff); ItemPointerSet(&(res->pointerData), rbknum, rightoff);
spl_right++; /* advance in right split vector */ spl_right++; /* advance in right split vector */
} }
/* Make sure we consumed all of the split vectors, and release 'em */ /* Make sure we consumed all of the split vectors, and release 'em */
@ -764,9 +763,10 @@ rtpicksplit(Relation r,
right_avail_space; right_avail_space;
int total_num_tuples, int total_num_tuples,
num_tuples_without_seeds, num_tuples_without_seeds,
max_after_split; /* in Guttman's lingo, (M - m) */ max_after_split; /* in Guttman's lingo, (M - m) */
float diff; /* diff between cost of putting tuple left or right */ float diff; /* diff between cost of putting tuple left
SPLITCOST *cost_vector; * or right */
SPLITCOST *cost_vector;
int n; int n;
/* /*
@ -852,7 +852,6 @@ rtpicksplit(Relation r,
if (firsttime) if (firsttime)
{ {
/* /*
* There is no possible split except to put the new item on its * There is no possible split except to put the new item on its
* own page. Since we still have to compute the union rectangles, * own page. Since we still have to compute the union rectangles,
@ -885,25 +884,25 @@ rtpicksplit(Relation r,
/* /*
* Now split up the regions between the two seeds. * Now split up the regions between the two seeds.
* *
* The cost_vector array will contain hints for determining where * The cost_vector array will contain hints for determining where each
* each tuple should go. Each record in the array will contain * tuple should go. Each record in the array will contain a boolean,
* a boolean, choose_left, that indicates which node the tuple * choose_left, that indicates which node the tuple prefers to be on,
* prefers to be on, and the absolute difference in cost between * and the absolute difference in cost between putting the tuple in
* putting the tuple in its favored node and in the other node. * its favored node and in the other node.
* *
* Later, we will sort the cost_vector in descending order by cost * Later, we will sort the cost_vector in descending order by cost
* difference, and consider the tuples in that order for * difference, and consider the tuples in that order for placement.
* placement. That way, the tuples that *really* want to be in * That way, the tuples that *really* want to be in one node or the
* one node or the other get to choose first, and the tuples that * other get to choose first, and the tuples that don't really care
* don't really care choose last. * choose last.
* *
* First, build the cost_vector array. The new index tuple will * First, build the cost_vector array. The new index tuple will also be
* also be handled in this loop, and represented in the array, * handled in this loop, and represented in the array, with
* with i==newitemoff. * i==newitemoff.
* *
* In the case of variable size tuples it is possible that we only * In the case of variable size tuples it is possible that we only have
* have the two seeds and no other tuples, in which case we don't * the two seeds and no other tuples, in which case we don't do any of
* do any of this cost_vector stuff. * this cost_vector stuff.
*/ */
/* to keep compiler quiet */ /* to keep compiler quiet */
@ -943,21 +942,21 @@ rtpicksplit(Relation r,
} }
/* /*
* Sort the array. The function qsort_comp_splitcost is * Sort the array. The function qsort_comp_splitcost is set up
* set up "backwards", to provided descending order. * "backwards", to provided descending order.
*/ */
qsort(cost_vector, num_tuples_without_seeds, sizeof(SPLITCOST), qsort(cost_vector, num_tuples_without_seeds, sizeof(SPLITCOST),
&qsort_comp_splitcost); &qsort_comp_splitcost);
} }
/* /*
* Now make the final decisions about where each tuple will go, * Now make the final decisions about where each tuple will go, and
* and build the vectors to return in the SPLITVEC record. * build the vectors to return in the SPLITVEC record.
* *
* The cost_vector array contains (descriptions of) all the * The cost_vector array contains (descriptions of) all the tuples, in
* tuples, in the order that we want to consider them, so we * the order that we want to consider them, so we we just iterate
* we just iterate through it and place each tuple in left * through it and place each tuple in left or right nodes, according
* or right nodes, according to the criteria described below. * to the criteria described below.
*/ */
left = v->spl_left; left = v->spl_left;
@ -965,9 +964,9 @@ rtpicksplit(Relation r,
right = v->spl_right; right = v->spl_right;
v->spl_nright = 0; v->spl_nright = 0;
/* Place the seeds first. /*
* left avail space, left union, right avail space, and right * Place the seeds first. left avail space, left union, right avail
* union have already been adjusted for the seeds. * space, and right union have already been adjusted for the seeds.
*/ */
*left++ = seed_1; *left++ = seed_1;
@ -983,8 +982,8 @@ rtpicksplit(Relation r,
choose_left; choose_left;
/* /*
* We need to figure out which page needs the least * We need to figure out which page needs the least enlargement in
* enlargement in order to store the item. * order to store the item.
*/ */
i = cost_vector[n].offset_number; i = cost_vector[n].offset_number;
@ -1019,22 +1018,22 @@ rtpicksplit(Relation r,
* the new item.) * the new item.)
* *
* Guttman's algorithm actually has two factors to consider (in * Guttman's algorithm actually has two factors to consider (in
* order): 1. if one node has so many tuples already assigned to * order): 1. if one node has so many tuples already assigned to
* it that the other needs all the rest in order to satisfy the * it that the other needs all the rest in order to satisfy the
* condition that neither node has fewer than m tuples, then * condition that neither node has fewer than m tuples, then that
* that is decisive; 2. otherwise, choose the page that shows * is decisive; 2. otherwise, choose the page that shows the
* the smaller enlargement of its union area. * smaller enlargement of its union area.
* *
* I have chosen m = M/2, where M is the maximum number of * I have chosen m = M/2, where M is the maximum number of tuples on
* tuples on a page. (Actually, this is only strictly * a page. (Actually, this is only strictly true for fixed size
* true for fixed size tuples. For variable size tuples, * tuples. For variable size tuples, there still might have to be
* there still might have to be only one tuple on a page, * only one tuple on a page, if it is really big. But even with
* if it is really big. But even with variable size * variable size tuples we still try to get m as close as possible
* tuples we still try to get m as close as possible to M/2.) * to M/2.)
* *
* The question of which page shows the smaller enlargement of * The question of which page shows the smaller enlargement of its
* its union area has already been answered, and the answer * union area has already been answered, and the answer stored in
* stored in the choose_left field of the SPLITCOST record. * the choose_left field of the SPLITCOST record.
*/ */
left_feasible = (left_avail_space >= item_1_sz && left_feasible = (left_avail_space >= item_1_sz &&
((left_avail_space - item_1_sz) >= newitemsz || ((left_avail_space - item_1_sz) >= newitemsz ||
@ -1045,10 +1044,10 @@ rtpicksplit(Relation r,
if (left_feasible && right_feasible) if (left_feasible && right_feasible)
{ {
/* /*
* Both feasible, use Guttman's algorithm. * Both feasible, use Guttman's algorithm. First check the m
* First check the m condition described above, and if * condition described above, and if that doesn't apply,
* that doesn't apply, choose the page with the smaller * choose the page with the smaller enlargement of its union
* enlargement of its union area. * area.
*/ */
if (v->spl_nleft > max_after_split) if (v->spl_nleft > max_after_split)
choose_left = false; choose_left = false;
@ -1064,7 +1063,7 @@ rtpicksplit(Relation r,
else else
{ {
elog(ERROR, "rtpicksplit: failed to find a workable page split"); elog(ERROR, "rtpicksplit: failed to find a workable page split");
choose_left = false;/* keep compiler quiet */ choose_left = false; /* keep compiler quiet */
} }
if (choose_left) if (choose_left)
@ -1090,9 +1089,7 @@ rtpicksplit(Relation r,
} }
if (num_tuples_without_seeds > 0) if (num_tuples_without_seeds > 0)
{
pfree(cost_vector); pfree(cost_vector);
}
*left = *right = InvalidOffsetNumber; /* add ending sentinels */ *left = *right = InvalidOffsetNumber; /* add ending sentinels */
@ -1189,7 +1186,7 @@ rtbulkdelete(PG_FUNCTION_ARGS)
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1); IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
void *callback_state = (void *) PG_GETARG_POINTER(2); void *callback_state = (void *) PG_GETARG_POINTER(2);
IndexBulkDeleteResult *result; IndexBulkDeleteResult *result;
BlockNumber num_pages; BlockNumber num_pages;
double tuples_removed; double tuples_removed;
double num_index_tuples; double num_index_tuples;
RetrieveIndexResult res; RetrieveIndexResult res;
@ -1200,7 +1197,7 @@ rtbulkdelete(PG_FUNCTION_ARGS)
/* /*
* Since rtree is not marked "amconcurrent" in pg_am, caller should * Since rtree is not marked "amconcurrent" in pg_am, caller should
* have acquired exclusive lock on index relation. We need no locking * have acquired exclusive lock on index relation. We need no locking
* here. * here.
*/ */
@ -1279,9 +1276,10 @@ initRtstate(RTSTATE *rtstate, Relation index)
static int static int
qsort_comp_splitcost(const void *a, const void *b) qsort_comp_splitcost(const void *a, const void *b)
{ {
float diff = float diff =
((SPLITCOST *)a)->cost_differential - ((SPLITCOST *) a)->cost_differential -
((SPLITCOST *)b)->cost_differential; ((SPLITCOST *) b)->cost_differential;
if (diff < 0) if (diff < 0)
return 1; return 1;
else if (diff > 0) else if (diff > 0)
@ -1342,7 +1340,6 @@ _rtdump(Relation r)
ReleaseBuffer(buf); ReleaseBuffer(buf);
} }
} }
#endif /* defined RTDEBUG */ #endif /* defined RTDEBUG */
void void

Some files were not shown because too many files have changed in this diff Show More