Commit ed2e1aa1 authored by serg@serg.mylan's avatar serg@serg.mylan

my_gethwaddr() for linux/freebsd

UUID() function
parent e58f1ca7
......@@ -646,3 +646,4 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
mysys/test_gethwaddr
......@@ -739,6 +739,8 @@ extern ulong crc32(ulong crc, const uchar *buf, uint len);
extern uint my_set_max_open_files(uint files);
void my_free_open_file_info(void);
my_bool my_gethwaddr(uchar *to);
/* character sets */
extern uint get_charset_number(const char *cs_name, uint cs_flags);
extern uint get_collation_number(const char *name);
......
......@@ -39,7 +39,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.c \
mf_pack.c mf_unixpath.c mf_strip.c \
mf_wcomp.c mf_wfile.c \
mf_wcomp.c mf_wfile.c my_gethwaddr.c \
mf_qsort.c mf_qsort2.c mf_sort.c \
ptr_cmp.c mf_radix.c queues.c \
tree.c list.c hash.c array.c string.c typelib.c \
......@@ -110,5 +110,10 @@ charset2html$(EXEEXT): charset2html.c $(LIBRARIES)
testhash$(EXEEXT): testhash.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS)
test_gethwaddr$(EXEEXT): my_gethwaddr.c $(LIBRARIES)
$(CP) $(srcdir)/my_gethwaddr.c ./test_gethwaddr.c
$(LINK) $(FLAGS) -DMAIN ./test_gethwaddr.c $(LDADD) $(LIBS)
$(RM) -f ./test_gethwaddr.c
# Don't update the files from bitkeeper
%::SCCS/s.%
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* get hardware address for an interface */
/* if there are many available, any non-zero one can be used */
#include "mysys_priv.h"
#include <m_string.h>
#ifndef MAIN
static my_bool memcpy_and_test(uchar *to, uchar *from, uint len)
{
uint i, res=1;
for (i=0; i < len; i++)
if ((*to++= *from++))
res=0;
return res;
}
#ifdef __FreeBSD__
#include <net/ethernet.h>
#include <sys/sysctl.h>
#include <net/route.h>
#include <net/if.h>
#include <net/if_dl.h>
my_bool my_gethwaddr(uchar *to)
{
size_t len;
uchar *buf, *next, *end, *addr;
struct if_msghdr *ifm;
struct sockaddr_dl *sdl;
int i, res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0};
if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
goto err;
if (!(buf = alloca(len)))
goto err;
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
goto err;
end = buf + len;
for (next = buf ; res && next < end ; next += ifm->ifm_msglen)
{
ifm = (struct if_msghdr *)next;
if (ifm->ifm_type == RTM_IFINFO)
{
sdl = (struct sockaddr_dl *)(ifm + 1);
addr=LLADDR(sdl);
res=memcpy_and_test(to, addr, ETHER_ADDR_LEN);
}
}
err:
return res;
}
#elif __linux__
#include <net/if.h>
#include <sys/ioctl.h>
#include <net/ethernet.h>
my_bool my_gethwaddr(uchar *to)
{
int fd, res=1;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
goto err;
bzero(&ifr, sizeof(ifr));
strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
do {
if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0)
res=memcpy_and_test(to, (uchar *)&ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
} while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6');
close(fd);
err:
return res;
}
#else
/* just fail */
my_bool my_gethwaddr(uchar *to __attribute__((unused)))
{
return 1;
}
#endif
#else MAIN
int main(int argc __attribute__((unused)),char **argv)
{
uchar mac[6];
uint i;
MY_INIT(argv[0]);
if (my_gethwaddr(mac))
{
printf("my_gethwaddr failed with errno %d\n", errno);
exit(1);
}
for (i=0; i < sizeof(mac); i++)
{
if (i) printf(":");
printf("%02x", mac[i]);
}
printf("\n");
return 0;
}
#endif
......@@ -34,14 +34,14 @@ Item *create_func_acos(Item* a)
Item *create_func_aes_encrypt(Item* a, Item* b)
{
return new Item_func_aes_encrypt(a, b);
return new Item_func_aes_encrypt(a, b);
}
Item *create_func_aes_decrypt(Item* a, Item* b)
{
return new Item_func_aes_decrypt(a, b);
}
Item *create_func_ascii(Item* a)
{
return new Item_func_ascii(a);
......@@ -426,6 +426,11 @@ Item *create_func_ucase(Item* a)
return new Item_func_ucase(a);
}
Item *create_func_uuid(void)
{
return new Item_func_uuid();
}
Item *create_func_version(void)
{
return new Item_string(NullS,server_version,
......
......@@ -92,6 +92,7 @@ Item *create_func_time_format(Item *a, Item *b);
Item *create_func_time_to_sec(Item* a);
Item *create_func_to_days(Item* a);
Item *create_func_ucase(Item* a);
Item *create_func_uuid(void);
Item *create_func_version(void);
Item *create_func_weekday(Item* a);
Item *create_load_file(Item* a);
......
......@@ -2632,3 +2632,112 @@ err:
return 0;
}
#endif
/*
UUID, as in
DCE 1.1: Remote Procedure Call,
Open Group Technical Standard Document Number C706, August 1997,
(supersedes C309 DCE: Remote Procedure Call 8/1994,
which was basis for ISO/IEC 11578:1996 specification)
*/
static struct rand_struct uuid_rand;
static uint nanoseq;
static ulonglong uuid_time=0;
static char clock_seq_and_node_str[]="-0000-000000000000";
/* we cannot use _dig_vec[] as letters should be lowercase */
static const char hex[] = "0123456789abcdef";
/* number of 100-nanosecond intervals between
1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00 */
#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * 1000 * 10 )
#define UUID_VERSION 0x1000
#define UUID_VARIANT 0x8000
static ulonglong get_uuid_time()
{
struct timeval tv;
gettimeofday(&tv,NULL);
return (ulonglong)tv.tv_sec*10000000 +
(ulonglong)tv.tv_usec*10 + UUID_TIME_OFFSET + nanoseq;
}
static void tohex(char *to, uint from, uint len)
{
to+= len;
while (len--)
{
*--to= hex[from & 15];
from >>= 4;
}
}
static void set_clock_seq_str()
{
uint16 clock_seq= ((uint)(my_rnd(&uuid_rand)*16383)) | UUID_VARIANT;
tohex(clock_seq_and_node_str+1, clock_seq, 4);
nanoseq= 0;
}
String *Item_func_uuid::val_str(String *str)
{
char *s;
pthread_mutex_lock(&LOCK_uuid_generator);
if (! uuid_time) /* first UUID() call. initializing data */
{
ulong tmp=sql_rnd_with_mutex();
uchar mac[6];
int i;
if (my_gethwaddr(mac))
{
/*
generating random "hardware addr"
and because specs explicitly specify that it should NOT correlate
with a clock_seq value (initialized random below), we use a separate
randominit() here
*/
randominit(&uuid_rand, tmp + (ulong)current_thd, tmp + query_id);
for (i=0; i < sizeof(mac); i++)
mac[i]=(uchar)(my_rnd(&uuid_rand)*255);
}
s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
for (i=sizeof(mac)-1 ; i>=0 ; i--)
{
*--s=hex[mac[i] & 15];
*--s=hex[mac[i] >> 4];
}
randominit(&uuid_rand, tmp + (ulong)start_time, tmp + bytes_sent);
set_clock_seq_str();
}
ulonglong tv=get_uuid_time();
if (unlikely(tv < uuid_time))
set_clock_seq_str();
else
if (unlikely(tv == uuid_time))
{ /* special protection from low-res system clocks */
nanoseq++;
tv++;
}
else
nanoseq=0;
uuid_time=tv;
pthread_mutex_unlock(&LOCK_uuid_generator);
uint32 time_low= tv & 0xFFFFFFFF;
uint16 time_mid= (tv >> 32) & 0xFFFF;
uint16 time_hi_and_version= (tv >> 48) | UUID_VERSION;
str->realloc(UUID_LENGTH+1);
str->length(UUID_LENGTH);
s=(char *) str->ptr();
s[8]=s[13]='-';
tohex(s, time_low, 8);
tohex(s+9, time_mid, 4);
tohex(s+14, time_hi_and_version, 4);
strmov(s+18, clock_seq_and_node_str);
return str;
}
......@@ -153,7 +153,7 @@ class Item_str_conv :public Item_str_func
public:
Item_str_conv(Item *item) :Item_str_func(item) {}
void fix_length_and_dec()
{
{
collation.set(args[0]->collation);
max_length = args[0]->max_length;
}
......@@ -589,10 +589,10 @@ public:
Item_func_quote(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "quote"; }
String *val_str(String *);
void fix_length_and_dec()
{
void fix_length_and_dec()
{
collation.set(args[0]->collation);
max_length= args[0]->max_length * 2 + 2;
max_length= args[0]->max_length * 2 + 2;
}
};
......@@ -600,7 +600,7 @@ class Item_func_conv_charset :public Item_str_func
{
CHARSET_INFO *conv_charset;
public:
Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
{ conv_charset=cs; }
String *val_str(String *);
void fix_length_and_dec();
......@@ -625,7 +625,7 @@ public:
Item_func_charset(Item *a) :Item_str_func(a) {}
String *val_str(String *);
const char *func_name() const { return "charset"; }
void fix_length_and_dec()
void fix_length_and_dec()
{
collation.set(system_charset_info);
max_length= 64 * collation.collation->mbmaxlen; // should be enough
......@@ -691,3 +691,13 @@ public:
String *val_str(String *) ZLIB_DEPENDED_FUNCTION
};
#define UUID_LENGTH (8+1+4+1+4+1+4+1+12)
class Item_func_uuid: public Item_str_func
{
public:
Item_func_uuid(): Item_str_func() {}
void fix_length_and_dec() {max_length= UUID_LENGTH; }
const char *func_name() const{ return "uuid"; }
String *val_str(String *);
};
......@@ -654,7 +654,7 @@ static SYMBOL sql_functions[] = {
{ "STDDEV", SYM(STD_SYM)},
{ "STR_TO_DATE", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)},
{ "STRCMP", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
{ "SUBSTR", SYM(SUBSTRING)},
{ "SUBSTR", SYM(SUBSTRING)},
{ "SUBSTRING", SYM(SUBSTRING)},
{ "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX)},
{ "SUBTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
......@@ -674,6 +674,7 @@ static SYMBOL sql_functions[] = {
{ "UNIQUE_USERS", SYM(UNIQUE_USERS)},
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP)},
{ "UPPER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "UUID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_uuid)},
{ "VARIANCE", SYM(VARIANCE_SYM)},
{ "VERSION", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM)},
......
......@@ -802,7 +802,7 @@ extern char log_error_file[FN_REFLEN];
extern double log_10[32];
extern ulonglong keybuff_size;
extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
extern ulong created_tmp_tables, created_tmp_disk_tables;
extern ulong created_tmp_tables, created_tmp_disk_tables, bytes_sent;
extern ulong aborted_threads,aborted_connects;
extern ulong delayed_insert_timeout;
extern ulong delayed_insert_limit, delayed_queue_size;
......@@ -857,7 +857,7 @@ extern FILE *bootstrap_file;
extern pthread_key(MEM_ROOT*,THR_MALLOC);
extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
LOCK_error_log, LOCK_delayed_insert,
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
LOCK_global_system_variables, LOCK_user_conn;
......@@ -1085,6 +1085,14 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
}
inline ulong sql_rnd_with_mutex()
{
pthread_mutex_lock(&LOCK_thread_count);
ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
pthread_mutex_unlock(&LOCK_thread_count);
return tmp;
}
Comp_creator *comp_eq_creator(bool invert);
Comp_creator *comp_ge_creator(bool invert);
Comp_creator *comp_gt_creator(bool invert);
......
......@@ -369,7 +369,7 @@ pthread_key(MEM_ROOT*,THR_MALLOC);
pthread_key(THD*, THR_THD);
pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_mapped_file, LOCK_status,
LOCK_error_log,
LOCK_error_log, LOCK_uuid_generator,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
LOCK_global_system_variables,
......@@ -2206,6 +2206,7 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
(void) my_rwlock_init(&LOCK_sys_init_connect, NULL);
(void) my_rwlock_init(&LOCK_sys_init_slave, NULL);
(void) my_rwlock_init(&LOCK_grant, NULL);
......
......@@ -179,14 +179,8 @@ THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
transaction.trans_log.end_of_file= max_binlog_cache_size;
}
#endif
/*
We need good random number initialization for new thread
Just coping global one will not work
*/
{
pthread_mutex_lock(&LOCK_thread_count);
ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
pthread_mutex_unlock(&LOCK_thread_count);
ulong tmp=sql_rnd_with_mutex();
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment