From f8ed839cd93545075a53e7a37d2e3dc96702ef9a Mon Sep 17 00:00:00 2001
From: "serg@serg.mylan" <>
Date: Wed, 16 Mar 2005 08:50:21 +0100
Subject: [PATCH 1/7] WinAMD64 compat fix
---
client/mysql.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/client/mysql.cc b/client/mysql.cc
index 16b26cd745d..b2f75e6f1e4 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -2154,7 +2154,7 @@ print_table_data_xml(MYSQL_RES *result)
for (uint i=0; i < mysql_num_fields(result); i++)
{
tee_fprintf(PAGER, "\t");
xmlencode_print(cur[i], lengths[i]);
tee_fprintf(PAGER, "\n");
From 99e581ecc1ee5537c918ef010ac92a27fa96944d Mon Sep 17 00:00:00 2001
From: "serg@serg.mylan" <>
Date: Wed, 16 Mar 2005 12:45:08 +0100
Subject: [PATCH 2/7] sql/ha_innodb.cc protect prepare-...-commit with a
mutex to ensure that commits in binlog and in the innodb have the same order
store binlog position with the commit
---
innobase/include/trx0trx.h | 5 +++--
sql/ha_innodb.cc | 40 +++++++++++++++++++++++++++-----------
sql/handler.cc | 3 ---
3 files changed, 32 insertions(+), 16 deletions(-)
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 9db69261468..64e9c87fbbd 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -390,8 +390,9 @@ struct trx_struct{
dulint table_id; /* table id if the preceding field is
TRUE */
/*------------------------------*/
- int active_trans; /* whether a transaction in MySQL
- is active */
+ int active_trans; /* 1 - if a transaction in MySQL
+ is active. 2 - if prepare_commit_mutex
+ was taken */
void* mysql_thd; /* MySQL thread handle corresponding
to this trx, or NULL */
char** mysql_query_str;/* pointer to the field in mysqld_thd
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 73d5ac9e94e..bf4acf65a0c 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -45,7 +45,8 @@ have disables the InnoDB inlining in this file. */
#include "ha_innodb.h"
-pthread_mutex_t innobase_mutex;
+pthread_mutex_t innobase_share_mutex, // to protect innobase_open_files
+ prepare_commit_mutex; // to force correct commit order in binlog
bool innodb_inited= 0;
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB
@@ -1266,7 +1267,8 @@ innobase_init(void)
(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
(hash_get_key) innobase_get_key, 0, 0);
- pthread_mutex_init(&innobase_mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
innodb_inited= 1;
/* If this is a replication slave and we needed to do a crash recovery,
@@ -1320,7 +1322,8 @@ innobase_end(void)
hash_free(&innobase_open_tables);
my_free(internal_innobase_data_file_path,
MYF(MY_ALLOW_ZERO_PTR));
- pthread_mutex_destroy(&innobase_mutex);
+ pthread_mutex_destroy(&innobase_share_mutex);
+ pthread_mutex_destroy(&prepare_commit_mutex);
}
DBUG_RETURN(err);
@@ -1478,9 +1481,20 @@ innobase_commit(
/* We were instructed to commit the whole transaction, or
this is an SQL statement end and autocommit is on */
+ /* We need current binlog position for HotBackup to work.
+ Note, the position is current because of prepare_commit_mutex */
+ trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
+ trx->mysql_log_offset =
+ (ib_longlong)mysql_bin_log.get_log_file()->pos_in_file;
+
innobase_commit_low(trx);
+ if (trx->active_trans == 2) {
+
+ pthread_mutex_unlock(&prepare_commit_mutex);
+ }
trx->active_trans = 0;
+
} else {
/* We just mark the SQL statement ended and do not do a
transaction commit */
@@ -5842,7 +5856,7 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
static INNOBASE_SHARE *get_share(const char *table_name)
{
INNOBASE_SHARE *share;
- pthread_mutex_lock(&innobase_mutex);
+ pthread_mutex_lock(&innobase_share_mutex);
uint length=(uint) strlen(table_name);
if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
(mysql_byte*) table_name,
@@ -5856,7 +5870,7 @@ static INNOBASE_SHARE *get_share(const char *table_name)
strmov(share->table_name,table_name);
if (my_hash_insert(&innobase_open_tables, (mysql_byte*) share))
{
- pthread_mutex_unlock(&innobase_mutex);
+ pthread_mutex_unlock(&innobase_share_mutex);
my_free((gptr) share,0);
return 0;
}
@@ -5865,13 +5879,13 @@ static INNOBASE_SHARE *get_share(const char *table_name)
}
}
share->use_count++;
- pthread_mutex_unlock(&innobase_mutex);
+ pthread_mutex_unlock(&innobase_share_mutex);
return share;
}
static void free_share(INNOBASE_SHARE *share)
{
- pthread_mutex_lock(&innobase_mutex);
+ pthread_mutex_lock(&innobase_share_mutex);
if (!--share->use_count)
{
hash_delete(&innobase_open_tables, (mysql_byte*) share);
@@ -5879,7 +5893,7 @@ static void free_share(INNOBASE_SHARE *share)
pthread_mutex_destroy(&share->mutex);
my_free((gptr) share, MYF(0));
}
- pthread_mutex_unlock(&innobase_mutex);
+ pthread_mutex_unlock(&innobase_share_mutex);
}
/*********************************************************************
@@ -6318,15 +6332,19 @@ innobase_xa_prepare(
FALSE - the current SQL statement ended */
{
int error = 0;
- trx_t* trx;
+ trx_t* trx = check_trx_exists(thd);
+
+ if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
+
+ pthread_mutex_lock(&prepare_commit_mutex);
+ trx->active_trans = 2;
+ }
if (!thd->variables.innodb_support_xa) {
return(0);
}
- trx = check_trx_exists(thd);
-
trx->xid=thd->transaction.xid;
/* Release a possible FIFO ticket and search latch. Since we will
diff --git a/sql/handler.cc b/sql/handler.cc
index 67a69201e3d..c7bd65bf24c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -526,7 +526,6 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
/*
RETURN
- -1 - cannot prepare
0 - ok
1 - error, transaction was rolled back
*/
@@ -539,8 +538,6 @@ int ha_prepare(THD *thd)
#ifdef USING_TRANSACTIONS
if (trans->nht)
{
- if (trans->no_2pc)
- DBUG_RETURN(-1);
for (; *ht; ht++)
{
int err;
From f3cf0837d26055ce65c8fa83125c0be24831bdfa Mon Sep 17 00:00:00 2001
From: "serg@serg.mylan" <>
Date: Wed, 16 Mar 2005 23:47:38 +0100
Subject: [PATCH 3/7] log_event.cc: #ifdef USING_TRANSACTIONS ha_innodb.cc:
comment rpl_drop_temp.test, rpl_drop_temp.result: cleanup
---
mysql-test/r/rpl_drop_temp.result | 1 +
mysql-test/t/rpl_drop_temp.test | 2 ++
sql/ha_innodb.cc | 21 ++++++++++++++++++++-
sql/log_event.cc | 2 ++
4 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/mysql-test/r/rpl_drop_temp.result b/mysql-test/r/rpl_drop_temp.result
index e00309cac8f..04fe094ea26 100644
--- a/mysql-test/r/rpl_drop_temp.result
+++ b/mysql-test/r/rpl_drop_temp.result
@@ -10,3 +10,4 @@ create temporary table mysqltest.t2 (n int);
show status like 'Slave_open_temp_tables';
Variable_name Value
Slave_open_temp_tables 0
+drop database mysqltest;
diff --git a/mysql-test/t/rpl_drop_temp.test b/mysql-test/t/rpl_drop_temp.test
index 73d691d9d90..41cd2edd139 100644
--- a/mysql-test/t/rpl_drop_temp.test
+++ b/mysql-test/t/rpl_drop_temp.test
@@ -11,3 +11,5 @@ disconnect master;
connection slave;
--real_sleep 3; # time for DROP to be written
show status like 'Slave_open_temp_tables';
+drop database mysqltest;
+
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 0ccac274d58..072f6866d7a 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1483,7 +1483,7 @@ innobase_commit(
/* We were instructed to commit the whole transaction, or
this is an SQL statement end and autocommit is on */
- /* We need current binlog position for HotBackup to work.
+ /* We need current binlog position for ibbackup to work.
Note, the position is current because of prepare_commit_mutex */
trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
trx->mysql_log_offset =
@@ -6472,6 +6472,25 @@ innobase_xa_prepare(
if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
+ /* For ibbackup to work the order of transactions in binlog
+ and InnoDB must be the same. Consider the situation
+
+ thread1> prepare; write to binlog; ...
+
+ thread2> prepare; write to binlog; commit
+ thread1> ... commit
+
+ To ensure this will not happen we're taking the mutex on
+ prepare, and releasing it on commit.
+
+ Note: only do it for normal commits, done via ha_commit_trans.
+ If 2pc protocol is executed by external transaction
+ coordinator, it will be just a regular MySQL client
+ executing XA PREPARE and XA COMMIT commands.
+ In this case we cannot know how many minutes or hours
+ will be between XA PREPARE and XA COMMIT, and we don't want
+ to block for undefined period of time.
+ */
pthread_mutex_lock(&prepare_commit_mutex);
trx->active_trans = 2;
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 3176cdfd5cb..72fc9185d4c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2012,6 +2012,7 @@ int Format_description_log_event::exec_event(struct st_relay_log_info* rli)
delete rli->relay_log.description_event_for_exec;
rli->relay_log.description_event_for_exec= this;
+#ifdef USING_TRANSACTIONS
/*
As a transaction NEVER spans on 2 or more binlogs:
if we have an active transaction at this point, the master died
@@ -2033,6 +2034,7 @@ int Format_description_log_event::exec_event(struct st_relay_log_info* rli)
"to its binary log.");
end_trans(thd, ROLLBACK);
}
+#endif
/*
If this event comes from ourselves, there is no cleaning task to perform,
we don't call Start_log_event_v3::exec_event() (this was just to update the
From 1400af8841a3665d8a3b2cabd9ebabd6cc161d33 Mon Sep 17 00:00:00 2001
From: "serg@serg.mylan" <>
Date: Wed, 16 Mar 2005 23:56:37 +0100
Subject: [PATCH 4/7] drop database on the right server :)
---
mysql-test/t/rpl_drop_temp.test | 1 +
1 file changed, 1 insertion(+)
diff --git a/mysql-test/t/rpl_drop_temp.test b/mysql-test/t/rpl_drop_temp.test
index 41cd2edd139..cf663367b78 100644
--- a/mysql-test/t/rpl_drop_temp.test
+++ b/mysql-test/t/rpl_drop_temp.test
@@ -11,5 +11,6 @@ disconnect master;
connection slave;
--real_sleep 3; # time for DROP to be written
show status like 'Slave_open_temp_tables';
+connection default;
drop database mysqltest;
From 376a4ee03b84f46fa577e1acdf975a4ee72ec5c2 Mon Sep 17 00:00:00 2001
From: "serg@serg.mylan" <>
Date: Thu, 17 Mar 2005 12:27:45 +0100
Subject: [PATCH 5/7] Field::quote_data(): don't call
escape_string_for_mysql() unnecesary don't overwrite local buffer
escape_string_for_mysql(): take a length of the destination buffer as an
argument
---
include/my_sys.h | 3 +-
libmysql/libmysql.c | 4 +--
mysys/charset.c | 75 +++++++++++++++++++++++++++++----------------
sql/field.cc | 23 ++++++--------
sql/item.cc | 2 +-
sql/sql_prepare.cc | 2 +-
6 files changed, 64 insertions(+), 45 deletions(-)
diff --git a/include/my_sys.h b/include/my_sys.h
index afd2803b75d..c4385cd5fd2 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -845,7 +845,8 @@ extern char *get_charsets_dir(char *buf);
extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
extern my_bool init_compiled_charsets(myf flags);
extern void add_compiled_collation(CHARSET_INFO *cs);
-extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
+extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
const char *from, ulong length);
extern void thd_increment_bytes_sent(ulong length);
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 20a000f1e4d..7e5d9667be2 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1575,14 +1575,14 @@ mysql_hex_string(char *to, const char *from, ulong length)
ulong STDCALL
mysql_escape_string(char *to,const char *from,ulong length)
{
- return escape_string_for_mysql(default_charset_info, to, from, length);
+ return escape_string_for_mysql(default_charset_info, to, 0, from, length);
}
ulong STDCALL
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
ulong length)
{
- return escape_string_for_mysql(mysql->charset, to, from, length);
+ return escape_string_for_mysql(mysql->charset, to, 0, from, length);
}
diff --git a/mysys/charset.c b/mysys/charset.c
index 4b7ad3e59f4..a4a8205a3f9 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -547,10 +547,10 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_PRINT("enter",("name: '%s'", cs_name));
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
-
+
cs_number= get_charset_number(cs_name, cs_flags);
cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
-
+
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN];
@@ -561,21 +561,34 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_RETURN(cs);
}
-
-ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
+/*
+ NOTE
+ to keep old C API, to_length may be 0 to mean "big enough"
+ RETURN
+ the length of the escaped string or ~0 if it did not fit.
+*/
+ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
const char *from, ulong length)
{
const char *to_start= to;
- const char *end;
+ const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
+ my_bool overflow=0;
#ifdef USE_MB
my_bool use_mb_flag= use_mb(charset_info);
#endif
- for (end= from + length; from != end; from++)
+ for (end= from + length; from < end; from++)
{
+ char escape=0;
#ifdef USE_MB
int l;
if (use_mb_flag && (l= my_ismbchar(charset_info, from, end)))
{
+ if (to + l >= to_end)
+ {
+ overflow=1;
+ break;
+ }
while (l--)
*to++= *from++;
from--;
@@ -593,45 +606,53 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \)
*/
if (use_mb_flag && (l= my_mbcharlen(charset_info, *from)) > 1)
- {
- *to++= '\\';
- *to++= *from;
- continue;
- }
+ escape= *from;
+ else
#endif
switch (*from) {
case 0: /* Must be escaped for 'mysql' */
- *to++= '\\';
- *to++= '0';
+ escape= '0';
break;
case '\n': /* Must be escaped for logs */
- *to++= '\\';
- *to++= 'n';
+ escape= 'n';
break;
case '\r':
- *to++= '\\';
- *to++= 'r';
+ escape= 'r';
break;
case '\\':
- *to++= '\\';
- *to++= '\\';
+ escape= '\\';
break;
case '\'':
- *to++= '\\';
- *to++= '\'';
+ escape= '\'';
break;
case '"': /* Better safe than sorry */
- *to++= '\\';
- *to++= '"';
+ escape= '"';
break;
case '\032': /* This gives problems on Win32 */
- *to++= '\\';
- *to++= 'Z';
+ escape= 'Z';
break;
- default:
+ }
+ if (escape)
+ {
+ if (to + 2 >= to_end)
+ {
+ overflow=1;
+ break;
+ }
+ *to++= '\\';
+ *to++= escape;
+ }
+ else
+ {
+ if (to + 1 >= to_end)
+ {
+ overflow=1;
+ break;
+ }
*to++= *from;
}
}
*to= 0;
- return (ulong) (to - to_start);
+ return overflow ? (ulong)~0 : (ulong) (to - to_start);
}
+
diff --git a/sql/field.cc b/sql/field.cc
index b6dd00d62a7..ae9b76e2dc4 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -752,25 +752,22 @@ bool Field::quote_data(String *unquoted_string)
{
char escaped_string[IO_SIZE];
char *unquoted_string_buffer= (char *)(unquoted_string->ptr());
- uint need_quotes;
DBUG_ENTER("Field::quote_data");
- // this is the same call that mysql_real_escape_string() calls
- escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
- unquoted_string->ptr(), unquoted_string->length());
-
- need_quotes= needs_quotes();
-
- if (need_quotes == 0)
+ if (!needs_quotes())
DBUG_RETURN(0);
+ // this is the same call that mysql_real_escape_string() calls
+ if (escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
+ sizeof(escaped_string), unquoted_string->ptr(),
+ unquoted_string->length()) == (ulong)~0)
+ DBUG_RETURN(1);
+
// reset string, then re-append with quotes and escaped values
unquoted_string->length(0);
- if (unquoted_string->append('\''))
- DBUG_RETURN(1);
- if (unquoted_string->append((char *)escaped_string))
- DBUG_RETURN(1);
- if (unquoted_string->append('\''))
+ if (unquoted_string->append('\'') ||
+ unquoted_string->append((char *)escaped_string) ||
+ unquoted_string->append('\''))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
diff --git a/sql/item.cc b/sql/item.cc
index e6be934e334..3489c54286c 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2038,7 +2038,7 @@ const String *Item_param::query_val_str(String* str) const
buf= str->c_ptr_quick();
ptr= buf;
*ptr++= '\'';
- ptr+= escape_string_for_mysql(str_value.charset(), ptr,
+ ptr+= escape_string_for_mysql(str_value.charset(), ptr, 0,
str_value.ptr(), str_value.length());
*ptr++= '\'';
str->length(ptr - buf);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 7862717bb18..1cbc52a2a5a 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -865,7 +865,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
*ptr++= '\'';
ptr+=
escape_string_for_mysql(&my_charset_utf8_general_ci,
- ptr, entry->name.str, entry->name.length);
+ ptr, 0, entry->name.str, entry->name.length);
*ptr++= '\'';
str.length(ptr - buf);
From f66967cf1b05f43ef492a9791f16e303d49b0906 Mon Sep 17 00:00:00 2001
From: "serg@serg.mylan" <>
Date: Thu, 17 Mar 2005 16:58:23 +0100
Subject: [PATCH 6/7] sql/ha_federated.cc: update to new prototype
sql/item_cmpfunc.cc: typo fixed
---
sql/ha_federated.cc | 1 +
sql/item_cmpfunc.cc | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index cddd0fd5927..8000aae180d 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -469,6 +469,7 @@ static int check_foreign_data_source(FEDERATED_SHARE *share)
*/
query.append("SHOW TABLES LIKE '");
escape_string_for_mysql(&my_charset_bin, (char *)escaped_table_base_name,
+ sizeof(escaped_table_base_name),
share->table_base_name,
share->table_base_name_length);
query.append(escaped_table_base_name);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index c0cb0704852..9850b01561e 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1720,7 +1720,7 @@ void Item_func_coalesce::fix_length_and_dec()
decimals= 0;
break;
case ROW_RESULT:
- defaullt:
+ default:
DBUG_ASSERT(0);
}
}
From 54fc6fbfe85775ba5165abff3bf1af661cb06c4d Mon Sep 17 00:00:00 2001
From: "serg@serg.mylan" <>
Date: Fri, 18 Mar 2005 14:59:07 +0100
Subject: [PATCH 7/7] set _XOPEN_SOURCE differently depending on
__STDC_VERSION__ [sigh]
---
include/my_global.h | 27 ++++++++++++++++++++++-----
1 file changed, 22 insertions(+), 5 deletions(-)
diff --git a/include/my_global.h b/include/my_global.h
index 2601c53bb92..7ec04377864 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -121,19 +121,36 @@
#endif
/*
- Solaris include file refers to X/Open document
+ Solaris 9 include file refers to X/Open document
System Interfaces and Headers, Issue 5
- saying we should define _XOPEN_SOURCE=500 to get POSIX.1c prototypes
+ saying we should define _XOPEN_SOURCE=500 to get POSIX.1c prototypes,
but apparently other systems (namely FreeBSD) don't agree.
- Furthermore X/Open has since 2004 "System Interfaces, Issue 6"
- that dictates _XOPEN_SOURCE=600, but Solaris checks for 500.
- So, let's define 500 for solaris only.
+
+ On a newer Solaris 10, the above file recognizes also _XOPEN_SOURCE=600.
+ Furthermore, it tests that if a program requires older standard
+ (_XOPEN_SOURCE<600 or _POSIX_C_SOURCE<200112L) it cannot be
+ run on a new compiler (that defines _STDC_C99) and issues an #error.
+ It's also an #error if a program requires new standard (_XOPEN_SOURCE=600
+ or _POSIX_C_SOURCE=200112L) and a compiler does not define _STDC_C99.
+
+ To add more to this mess, Sun Studio C compiler defines _STDC_C99 while
+ C++ compiler does not!
+
+ So, in a desperate attempt to get correct prototypes for both
+ C and C++ code, we define either _XOPEN_SOURCE=600 or _XOPEN_SOURCE=500
+ depending on the compiler's announced C standard support.
+
+ Cleaner solutions are welcome.
*/
#ifdef __sun
+#if __STDC_VERSION__ - 0 >= 199901L
+#define _XOPEN_SOURCE 600
+#else
#define _XOPEN_SOURCE 500
#endif
+#endif
#if defined(THREAD) && !defined(__WIN__) && !defined(OS2)
#ifndef _POSIX_PTHREAD_SEMANTICS