diff --git a/library/GNUmakefile.68k b/library/GNUmakefile.68k index d436492..90518a3 100644 --- a/library/GNUmakefile.68k +++ b/library/GNUmakefile.68k @@ -1,5 +1,5 @@ # -# $Id: GNUmakefile.68k,v 1.97 2006-09-27 09:40:05 obarthel Exp $ +# $Id: GNUmakefile.68k,v 1.98 2006-11-13 09:25:28 obarthel Exp $ # # :ts=8 # @@ -183,6 +183,7 @@ C_LIB = \ stat_fchmod.o \ stat_fstat.o \ stat_lstat.o \ + stat_lock.o \ stat_mkdir.o \ stat_rmdir.o \ stat_stat.o \ @@ -478,6 +479,7 @@ UNIX_LIB = \ stat_chmod.o \ stat_fstat.o \ stat_lstat.o \ + stat_lock.o \ stat_mkdir.o \ stat_rmdir.o \ stat_stat.o \ diff --git a/library/GNUmakefile.os4 b/library/GNUmakefile.os4 index 9c255e5..4b1a71d 100644 --- a/library/GNUmakefile.os4 +++ b/library/GNUmakefile.os4 @@ -1,5 +1,5 @@ # -# $Id: GNUmakefile.os4,v 1.109 2006-09-17 17:37:27 obarthel Exp $ +# $Id: GNUmakefile.os4,v 1.110 2006-11-13 09:25:28 obarthel Exp $ # # :ts=8 # @@ -21,28 +21,28 @@ # These are for the cross compiler, with the operating system header files # stored in "/V/include" and the network header files in a local directory # called "netinclude". -SDK_INCLUDE := /V/include -NET_INCLUDE := netinclude -CC := ppc-amigaos-gcc -AR := ppc-amigaos-ar -q -RANLIB := ppc-amigaos-ranlib -COPY := cp -a -DELETE := rm -rf -MAKEDIR := mkdir -p -LOG_COMMAND := 2>&1 | tee -a compiler.log +#SDK_INCLUDE := /V/include +#NET_INCLUDE := netinclude +#CC := ppc-amigaos-gcc +#AR := ppc-amigaos-ar -q +#RANLIB := ppc-amigaos-ranlib +#COPY := cp -a +#DELETE := rm -rf +#MAKEDIR := mkdir -p +#LOG_COMMAND := 2>&1 | tee -a compiler.log # The following are for the native OS4 compiler; note that the # LOG_COMMAND should not be enabled unless you have a shell # installed which supports it. -#SDK_INCLUDE := /SDK/Include/include_h -#NET_INCLUDE := /SDK/Include/netinclude -#CC := distcc gcc -#AR := ar -q -#RANLIB := ranlib -#COPY := copy -#DELETE := delete all quiet force -#MAKEDIR := makedir all force -#LOG_COMMAND := *>< | tee >>compiler.log +SDK_INCLUDE := /SDK/Include/include_h +NET_INCLUDE := /SDK/Include/netinclude +CC := distcc gcc +AR := ar -q +RANLIB := ranlib +COPY := copy +DELETE := delete all quiet force +MAKEDIR := makedir all force +LOG_COMMAND := *>< | tee >>compiler.log ############################################################################## @@ -91,7 +91,28 @@ include libprofile.gmk all-targets: \ lib/crt0.o \ lib/small-data/crt0.o \ + lib/soft-float/crt0.o \ lib/baserel/crt0.o \ + lib/crtbegin.o \ + lib/soft-float/crtbegin.o \ + lib/small-data/crtbegin.o \ + lib/baserel/crtbegin.o \ + lib/crtend.o \ + lib/soft-float/crtend.o \ + lib/small-data/crtend.o \ + lib/baserel/crtend.o \ + lib.threadsafe/crt0.o \ + lib.threadsafe/small-data/crt0.o \ + lib.threadsafe/soft-float/crt0.o \ + lib.threadsafe/baserel/crt0.o \ + lib.threadsafe/crtbegin.o \ + lib.threadsafe/soft-float/crtbegin.o \ + lib.threadsafe/small-data/crtbegin.o \ + lib.threadsafe/baserel/crtbegin.o \ + lib.threadsafe/crtend.o \ + lib.threadsafe/soft-float/crtend.o \ + lib.threadsafe/small-data/crtend.o \ + lib.threadsafe/baserel/crtend.o \ $(LIBS) ############################################################################## @@ -136,14 +157,58 @@ lib/%.o : AFLAGS += $(LARGEDATA) lib/%.o : %.S @$(ASSEMBLE) +lib/%.o : %.c + @$(COMPILE) + lib/small-data/%.o : AFLAGS += $(SMALLDATA) lib/small-data/%.o : %.S @$(ASSEMBLE) +lib/small-data/%.o : %.c + @$(COMPILE) + +lib/soft-float/%.o : AFLAGS += $(SOFTFLOAT) +lib/soft-float/%.o : %.S + @$(ASSEMBLE) + +lib/soft-float/%.o : %.c + @$(COMPILE) + lib/baserel/%.o : AFLAGS += $(BASEREL) lib/baserel/%.o : %.S @$(ASSEMBLE) +lib/baserel/%.o : %.c + @$(COMPILE) + +lib.threadsafe/%.o : AFLAGS += $(LARGEDATA) $(THREADSAFE) +lib.threadsafe/%.o : %.S + @$(ASSEMBLE) + +lib.threadsafe/%.o : %.c + @$(COMPILE) + +lib.threadsafe/small-data/%.o : AFLAGS += $(SMALLDATA) $(THREADSAFE) +lib.threadsafe/small-data/%.o : %.S + @$(ASSEMBLE) + +lib.threadsafe/small-data/%.o : %.c + @$(COMPILE) + +lib.threadsafe/soft-float/%.o : AFLAGS += $(SOFTFLOAT) $(THREADSAFE) +lib.threadsafe/soft-float/%.o : %.S + @$(ASSEMBLE) + +lib.threadsafe/soft-float/%.o : %.c + @$(COMPILE) + +lib.threadsafe/baserel/%.o : AFLAGS += $(BASEREL) $(THREADSAFE) +lib.threadsafe/baserel/%.o : %.S + @$(ASSEMBLE) + +lib.threadsafe/baserel/%.o : %.c + @$(COMPILE) + ############################################################################## define COMPILE diff --git a/library/changes b/library/changes index 33f18b1..00a3474 100644 --- a/library/changes +++ b/library/changes @@ -1,3 +1,21 @@ +- readlink() no longer sort-of-works for files and directories. It now only + works for soft linked objects and returns an error for everything else. + This is based upon a fix by Peter Bengtsson. Thank you very much! + +- Moved the lstat() local Lock() function into its own separate file. + +- uname() now returns correct and robust information for OS version + numbers > 36. This integrates a fix by Peter Bengtsson. Thank you + very much! + +- Moved the crtbegin.o/crtend.o files out of the link libraries. Moving + them in was intended to work as a fix for the shared library build, but + now it seems that this has to be done at the link stage through the + GCC specs file... + +- Integrated a fix for __rem_pio2() which affects sin(), tan() and cos(), + contributed by Steven Solie. Thank you very much! + - The internal 'struct fd' file descriptor table entry data structure now has a user data field entry. diff --git a/library/libc.gmk b/library/libc.gmk index e151c60..527314e 100755 --- a/library/libc.gmk +++ b/library/libc.gmk @@ -1,5 +1,5 @@ # -# $Id: libc.gmk,v 1.1 2006-09-17 17:37:27 obarthel Exp $ +# $Id: libc.gmk,v 1.2 2006-11-13 09:25:28 obarthel Exp $ # # :ts=8 # @@ -21,7 +21,6 @@ LIBS += \ C_LIB := \ c.lib_rev.o \ - crtbegin.o \ ctype_isalnum.o \ ctype_isalpha.o \ ctype_isascii.o \ @@ -85,6 +84,7 @@ C_LIB := \ stat_fchmod.o \ stat_fstat.o \ stat_lstat.o \ + stat_lock.o \ stat_mkdir.o \ stat_rmdir.o \ stat_stat.o \ @@ -359,8 +359,7 @@ C_LIB := \ unistd_unlink.o \ unistd_usleep.o \ utime_utime.o \ - utsname_uname.o \ - crtend.o + utsname_uname.o ############################################################################## diff --git a/library/libunix.gmk b/library/libunix.gmk index d6c3377..41e1d1b 100755 --- a/library/libunix.gmk +++ b/library/libunix.gmk @@ -1,5 +1,5 @@ # -# $Id: libunix.gmk,v 1.2 2006-09-27 09:40:06 obarthel Exp $ +# $Id: libunix.gmk,v 1.3 2006-11-13 09:25:28 obarthel Exp $ # # :ts=8 # @@ -37,6 +37,7 @@ UNIX_LIB := \ stat_chmod.o \ stat_fstat.o \ stat_lstat.o \ + stat_lock.o \ stat_mkdir.o \ stat_rmdir.o \ stat_stat.o \ diff --git a/library/math_kernel_rem_pio2.c b/library/math_kernel_rem_pio2.c index c43e34f..5df175e 100644 --- a/library/math_kernel_rem_pio2.c +++ b/library/math_kernel_rem_pio2.c @@ -1,5 +1,5 @@ /* - * $Id: math_kernel_rem_pio2.c,v 1.5 2006-01-08 12:04:23 obarthel Exp $ + * $Id: math_kernel_rem_pio2.c,v 1.6 2006-11-13 09:25:28 obarthel Exp $ * * :ts=4 * @@ -55,7 +55,7 @@ static const double PIo2[] = { 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ - 3.28200341580791294123e422, /* 0x3B78CC51, 0x60000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ diff --git a/library/stat_headers.h b/library/stat_headers.h index 5593ea8..7064ba6 100644 --- a/library/stat_headers.h +++ b/library/stat_headers.h @@ -1,5 +1,5 @@ /* - * $Id: stat_headers.h,v 1.6 2006-01-08 12:04:24 obarthel Exp $ + * $Id: stat_headers.h,v 1.7 2006-11-13 09:25:28 obarthel Exp $ * * :ts=4 * @@ -59,6 +59,7 @@ extern mode_t NOCOMMON __current_umask; /****************************************************************************/ extern void __convert_file_info_to_stat(const struct MsgPort * file_system,const struct FileInfoBlock * fib,struct stat * st); +extern BPTR __lock(const char *name,const int mode,int * link_length,char * real_name,size_t real_name_size); /****************************************************************************/ diff --git a/library/stat_lock.c b/library/stat_lock.c new file mode 100644 index 0000000..2b62eb7 --- /dev/null +++ b/library/stat_lock.c @@ -0,0 +1,186 @@ +/* + * $Id: stat_lock.c,v 1.1 2006-11-13 09:25:28 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2006 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _STDLIB_NULL_POINTER_CHECK_H +#include "stdlib_null_pointer_check.h" +#endif /* _STDLIB_NULL_POINTER_CHECK_H */ + +/****************************************************************************/ + +#ifndef _STAT_HEADERS_H +#include "stat_headers.h" +#endif /* _STAT_HEADERS_H */ + +#ifndef _LOCALE_HEADERS_H +#include "locale_headers.h" +#endif /* _LOCALE_HEADERS_H */ + +#ifndef _TIME_HEADERS_H +#include "time_headers.h" +#endif /* _TIME_HEADERS_H */ + +/****************************************************************************/ + +/* The following is not part of the ISO 'C' (1994) standard. */ + +/****************************************************************************/ + +/* + * __lock(): An implementation of Lock() which remembers whether or + * not it resolved soft links. + * + * Unfortunately is is limited to 255 character names. + */ + +BPTR +__lock( + const char * name, + const int mode, + int * link_length, + char * real_name, + size_t real_name_size) +{ + D_S(struct bcpl_name,bname); + const size_t name_size = sizeof(bname->name); + char * new_name = NULL; + struct DevProc * dvp = NULL; + BPTR lock = ZERO; + size_t name_len; + LONG error; + + assert( name != NULL && link_length != NULL ); + + if(real_name != NULL && real_name_size > 0) + strcpy(real_name,""); + + name_len = strlen(name); + if(name_len >= name_size) + { + SetIoErr(ERROR_LINE_TOO_LONG); + goto out; + } + + /* Convert the name into a BCPL string. */ + bname->name[0] = name_len; + memmove(&bname->name[1],name,name_len); + + while(TRUE) + { + /* Get a handle on the device, volume or assignment name in the path. */ + dvp = GetDeviceProc((STRPTR)name,dvp); + if(dvp == NULL) + goto out; + + /* Try to obtain a lock on the object. */ + lock = DoPkt(dvp->dvp_Port,ACTION_LOCATE_OBJECT,dvp->dvp_Lock,MKBADDR(bname),mode,0,0); + if(lock != ZERO) + break; + + error = IoErr(); + + if(error == ERROR_OBJECT_NOT_FOUND) + { + /* If this is part of a multi-volume assignment, try the next part. */ + if(FLAG_IS_SET(dvp->dvp_Flags,DVPF_ASSIGN)) + continue; + + /* Not much we can do here... */ + break; + } + else if (error == ERROR_IS_SOFT_LINK) + { + size_t new_name_size = name_size+1; + LONG result; + + /* Provide as much buffer space as possible. */ + if(real_name_size > new_name_size) + new_name_size = real_name_size; + + /* For soft link resolution we need a temporary buffer to + let the file system store the resolved path name in. */ + new_name = malloc(new_name_size); + if(new_name == NULL) + { + SetIoErr(ERROR_NO_FREE_STORE); + goto out; + } + + /* Now ask the file system to resolve the entire path. */ + result = ReadLink(dvp->dvp_Port,dvp->dvp_Lock,(STRPTR)name,(STRPTR)new_name,(LONG)new_name_size); + if(result < 0) + { + /* This will return either -1 (resolution error) or -2 + (buffer too small). We regard both as trouble. */ + SetIoErr(ERROR_INVALID_COMPONENT_NAME); + goto out; + } + + assert( result > 0 ); + + /* Remember the length of the link name. */ + (*link_length) = result; + + /* If the caller supplied a buffer, copy as much of the name + as possible into it. */ + if(real_name != NULL && real_name_size > 0) + strlcpy(real_name,new_name,real_name_size); + + /* Finished for now. */ + break; + } + else + { + /* Some other error; ask if the user wants to have another go at it. */ + if(ErrorReport(error,REPORT_LOCK,dvp->dvp_Lock,dvp->dvp_Port) != 0) + break; + } + + /* Retry the lookup. */ + FreeDeviceProc(dvp); + dvp = NULL; + } + + out: + + error = IoErr(); + + if(new_name != NULL) + free(new_name); + + if(dvp != NULL) + FreeDeviceProc(dvp); + + SetIoErr(error); + + return(lock); +} diff --git a/library/stat_lstat.c b/library/stat_lstat.c index 081c706..7054b25 100644 --- a/library/stat_lstat.c +++ b/library/stat_lstat.c @@ -1,5 +1,5 @@ /* - * $Id: stat_lstat.c,v 1.14 2006-09-21 09:24:20 obarthel Exp $ + * $Id: stat_lstat.c,v 1.15 2006-11-13 09:25:28 obarthel Exp $ * * :ts=4 * @@ -55,118 +55,6 @@ /****************************************************************************/ -/* - * lstat_lock(): An implementation of Lock() which remembers whether or - * not it resolved soft links. - * - * Unfortunately is is limited to 255 character names. - */ - -static BPTR -lstat_lock(const char *name,const int mode,int * link_length) -{ - D_S(struct bcpl_name,bname); - const size_t name_size = sizeof(bname->name); - char * new_name = NULL; - struct DevProc * dvp = NULL; - BPTR lock = ZERO; - size_t name_len; - LONG error; - - assert( name != NULL && link_length != NULL ); - - name_len = strlen(name); - if(name_len >= name_size) - { - SetIoErr(ERROR_LINE_TOO_LONG); - goto out; - } - - /* Convert the name into a BCPL string. */ - bname->name[0] = name_len; - memmove(&bname->name[1],name,name_len); - - while(TRUE) - { - /* Get a handle on the device, volume or assignment name in the path. */ - dvp = GetDeviceProc((STRPTR)name,dvp); - if(dvp == NULL) - goto out; - - /* Try to obtain a lock on the object. */ - lock = DoPkt(dvp->dvp_Port,ACTION_LOCATE_OBJECT,dvp->dvp_Lock,MKBADDR(bname),mode,0,0); - if(lock != ZERO) - break; - - error = IoErr(); - - if(error == ERROR_OBJECT_NOT_FOUND) - { - /* If this is part of a multi-volume assignment, try the next part. */ - if(FLAG_IS_SET(dvp->dvp_Flags,DVPF_ASSIGN)) - continue; - - /* Not much we can do here... */ - break; - } - else if (error == ERROR_IS_SOFT_LINK) - { - LONG result; - - /* For soft link resolution we need a temporary buffer to - let the file system store the resolved path name in. */ - new_name = malloc(name_size); - if(new_name == NULL) - { - SetIoErr(ERROR_NO_FREE_STORE); - goto out; - } - - /* Now ask the file system to resolve the entire path. */ - result = ReadLink(dvp->dvp_Port,dvp->dvp_Lock,(STRPTR)name,(STRPTR)new_name,name_size); - - if(result < 0) - { - /* This will return either -1 (resolution error) or -2 - (buffer too small). We regard both as trouble. */ - SetIoErr(ERROR_INVALID_COMPONENT_NAME); - goto out; - } - - assert( result > 0 ); - - /* Remember the length of the link name. */ - (*link_length) = result; - - /* Finished for now. */ - break; - } - else - { - /* Some other error; ask if the user wants to have another go at it. */ - if(ErrorReport(error,REPORT_LOCK,dvp->dvp_Lock,dvp->dvp_Port) != 0) - break; - } - - /* Retry the lookup. */ - FreeDeviceProc(dvp); - dvp = NULL; - } - - out: - - error = IoErr(); - - if(new_name != NULL) - free(new_name); - - FreeDeviceProc(dvp); - - SetIoErr(error); - - return(lock); -} - int lstat(const char * path_name, struct stat * st) { @@ -247,7 +135,7 @@ lstat(const char * path_name, struct stat * st) D(("trying to get a lock on '%s'",path_name)); PROFILE_OFF(); - file_lock = lstat_lock(path_name,SHARED_LOCK,&link_length); + file_lock = __lock(path_name,SHARED_LOCK,&link_length,NULL,0); PROFILE_ON(); if(file_lock == ZERO && link_length < 0) diff --git a/library/unistd_readlink.c b/library/unistd_readlink.c index f2170c5..0d82313 100644 --- a/library/unistd_readlink.c +++ b/library/unistd_readlink.c @@ -1,5 +1,5 @@ /* - * $Id: unistd_readlink.c,v 1.8 2006-01-08 12:04:27 obarthel Exp $ + * $Id: unistd_readlink.c,v 1.9 2006-11-13 09:25:28 obarthel Exp $ * * :ts=4 * @@ -41,6 +41,10 @@ #include "unistd_headers.h" #endif /* _UNISTD_HEADERS_H */ +#ifndef _STAT_HEADERS_H +#include "stat_headers.h" +#endif /* _STAT_HEADERS_H */ + /****************************************************************************/ /* The following is not part of the ISO 'C' (1994) standard. */ @@ -54,9 +58,9 @@ readlink(const char * path_name, char * buffer, int buffer_size) struct name_translation_info path_name_nti; struct name_translation_info buffer_nti; #endif /* UNIX_PATH_SEMANTICS */ - struct DevProc * dvp = NULL; BPTR lock = ZERO; int result = ERROR; + int target_length = -1; ENTER(); @@ -102,61 +106,18 @@ readlink(const char * path_name, char * buffer, int buffer_size) D(("trying to get a lock on '%s'",path_name)); PROFILE_OFF(); - lock = Lock((STRPTR)path_name,SHARED_LOCK); + lock = __lock((STRPTR)path_name,SHARED_LOCK,&target_length,buffer,(size_t)buffer_size); PROFILE_ON(); if(lock != ZERO) { - LONG status; - - SHOWMSG("trying to obtain the absolute path"); - - PROFILE_OFF(); - status = NameFromLock(lock,buffer,buffer_size); - PROFILE_ON(); - - if(status == DOSFALSE) - { - SHOWMSG("that didn't work"); - - __set_errno(__translate_io_error_to_errno(IoErr())); - goto out; - } + __set_errno(EINVAL); + goto out; } - else + else if (target_length <= 0) /* No a soft-link. */ { - LONG read_link_result; - - PROFILE_OFF(); - dvp = GetDeviceProc((STRPTR)path_name,NULL); - PROFILE_ON(); - - if(dvp == NULL) - { - SHOWMSG("didn't get deviceproc"); - - __set_errno(__translate_io_error_to_errno(IoErr())); - goto out; - } - - PROFILE_OFF(); - read_link_result = ReadLink(dvp->dvp_Port,dvp->dvp_Lock,(STRPTR)path_name,buffer,(ULONG)buffer_size); - PROFILE_ON(); - - if(read_link_result == -1) - { - SHOWMSG("couldn't read the link"); - - __set_errno(__translate_io_error_to_errno(IoErr())); - goto out; - } - else if (read_link_result == -2) - { - SHOWMSG("buffer was too short"); - - __set_errno(ENOBUFS); - goto out; - } + __set_errno(__translate_io_error_to_errno(IoErr())); + goto out; } #if defined(UNIX_PATH_SEMANTICS) @@ -180,10 +141,7 @@ readlink(const char * path_name, char * buffer, int buffer_size) out: PROFILE_OFF(); - - FreeDeviceProc(dvp); UnLock(lock); - PROFILE_ON(); RETURN(result); diff --git a/library/utsname_uname.c b/library/utsname_uname.c index 2b6919f..958fa87 100644 --- a/library/utsname_uname.c +++ b/library/utsname_uname.c @@ -1,5 +1,5 @@ /* - * $Id: utsname_uname.c,v 1.6 2006-09-22 07:54:25 obarthel Exp $ + * $Id: utsname_uname.c,v 1.7 2006-11-13 09:25:28 obarthel Exp $ * * :ts=4 * @@ -139,12 +139,16 @@ uname(struct utsname *info) version_string = "4.0"; else if (Version == 45) version_string = "3.9"; - else if (Version >= 44) + else if (Version == 44) version_string = "3.5"; - else if (Version >= 40) + else if (40 <= Version && Version <= 43) version_string = "3.1"; - else if (Version >= 39) + else if (Version == 39) version_string = "3.0"; + else if (Version == 38) + version_string = "2.1"; + else if (Version == 37) + version_string = "2.0"; else version_string = "unknown";