tiny_tds 2.1.6-x64-mingw-ucrt

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +407 -0
  3. data/.codeclimate.yml +20 -0
  4. data/.gitattributes +1 -0
  5. data/.gitignore +22 -0
  6. data/.rubocop.yml +31 -0
  7. data/CHANGELOG.md +280 -0
  8. data/CODE_OF_CONDUCT.md +31 -0
  9. data/Gemfile +2 -0
  10. data/ISSUE_TEMPLATE.md +38 -0
  11. data/MIT-LICENSE +23 -0
  12. data/README.md +504 -0
  13. data/Rakefile +62 -0
  14. data/VERSION +1 -0
  15. data/bin/defncopy-ttds +3 -0
  16. data/bin/tsql-ttds +3 -0
  17. data/docker-compose.yml +34 -0
  18. data/exe/.keep +0 -0
  19. data/ext/tiny_tds/client.c +499 -0
  20. data/ext/tiny_tds/client.h +53 -0
  21. data/ext/tiny_tds/extconf.rb +92 -0
  22. data/ext/tiny_tds/extconsts.rb +15 -0
  23. data/ext/tiny_tds/result.c +634 -0
  24. data/ext/tiny_tds/result.h +32 -0
  25. data/ext/tiny_tds/tiny_tds_ext.c +12 -0
  26. data/ext/tiny_tds/tiny_tds_ext.h +17 -0
  27. data/lib/tiny_tds/3.1/tiny_tds.so +0 -0
  28. data/lib/tiny_tds/3.2/tiny_tds.so +0 -0
  29. data/lib/tiny_tds/bin.rb +104 -0
  30. data/lib/tiny_tds/client.rb +136 -0
  31. data/lib/tiny_tds/error.rb +14 -0
  32. data/lib/tiny_tds/gem.rb +27 -0
  33. data/lib/tiny_tds/result.rb +7 -0
  34. data/lib/tiny_tds/version.rb +3 -0
  35. data/lib/tiny_tds.rb +61 -0
  36. data/patches/freetds/1.00.27/0001-mingw_missing_inet_pton.diff +34 -0
  37. data/patches/freetds/1.00.27/0002-Don-t-use-MSYS2-file-libws2_32.diff +28 -0
  38. data/patches/libiconv/1.14/1-avoid-gets-error.patch +17 -0
  39. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/bsqldb.exe +0 -0
  40. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/datacopy.exe +0 -0
  41. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/defncopy.exe +0 -0
  42. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/freebcp.exe +0 -0
  43. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/libct-4.dll +0 -0
  44. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/libsybdb-5.dll +0 -0
  45. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/osql +388 -0
  46. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/tdspool.exe +0 -0
  47. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/tsql.exe +0 -0
  48. data/ports/x64-mingw-ucrt/freetds/1.1.24/lib/libct.dll.a +0 -0
  49. data/ports/x64-mingw-ucrt/freetds/1.1.24/lib/libct.la +41 -0
  50. data/ports/x64-mingw-ucrt/freetds/1.1.24/lib/libsybdb.dll.a +0 -0
  51. data/ports/x64-mingw-ucrt/freetds/1.1.24/lib/libsybdb.la +41 -0
  52. data/ports/x64-mingw-ucrt/libiconv/1.15/bin/iconv.exe +0 -0
  53. data/ports/x64-mingw-ucrt/libiconv/1.15/bin/libcharset-1.dll +0 -0
  54. data/ports/x64-mingw-ucrt/libiconv/1.15/bin/libiconv-2.dll +0 -0
  55. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/charset.alias +4 -0
  56. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/libcharset.dll.a +0 -0
  57. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/libcharset.la +41 -0
  58. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/libiconv.dll.a +0 -0
  59. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/libiconv.la +41 -0
  60. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/c_rehash +251 -0
  61. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/libcrypto-1_1-x64.dll +0 -0
  62. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/libssl-1_1-x64.dll +0 -0
  63. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/openssl.exe +0 -0
  64. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libcrypto.a +0 -0
  65. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libcrypto.dll.a +0 -0
  66. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libssl.a +0 -0
  67. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libssl.dll.a +0 -0
  68. data/setup_cimgruby_dev.sh +25 -0
  69. data/start_dev.sh +21 -0
  70. data/tasks/native_gem.rake +23 -0
  71. data/tasks/package.rake +8 -0
  72. data/tasks/ports/freetds.rb +37 -0
  73. data/tasks/ports/libiconv.rb +26 -0
  74. data/tasks/ports/openssl.rb +62 -0
  75. data/tasks/ports/recipe.rb +64 -0
  76. data/tasks/ports.rake +108 -0
  77. data/tasks/test.rake +9 -0
  78. data/test/benchmark/query.rb +77 -0
  79. data/test/benchmark/query_odbc.rb +106 -0
  80. data/test/benchmark/query_tinytds.rb +126 -0
  81. data/test/bin/install-freetds.sh +20 -0
  82. data/test/bin/install-mssql.ps1 +31 -0
  83. data/test/bin/install-mssqltools.sh +9 -0
  84. data/test/bin/install-openssl.sh +18 -0
  85. data/test/bin/setup_tinytds_db.sh +7 -0
  86. data/test/bin/setup_volume_permissions.sh +10 -0
  87. data/test/client_test.rb +275 -0
  88. data/test/gem_test.rb +177 -0
  89. data/test/result_test.rb +814 -0
  90. data/test/schema/1px.gif +0 -0
  91. data/test/schema/sqlserver_2000.sql +140 -0
  92. data/test/schema/sqlserver_2005.sql +140 -0
  93. data/test/schema/sqlserver_2008.sql +140 -0
  94. data/test/schema/sqlserver_2014.sql +140 -0
  95. data/test/schema/sqlserver_2016.sql +140 -0
  96. data/test/schema/sqlserver_azure.sql +140 -0
  97. data/test/schema/sybase_ase.sql +138 -0
  98. data/test/schema_test.rb +443 -0
  99. data/test/sql/db-create.sql +18 -0
  100. data/test/sql/db-login.sql +38 -0
  101. data/test/test_helper.rb +280 -0
  102. data/test/thread_test.rb +98 -0
  103. data/tiny_tds.gemspec +31 -0
  104. metadata +267 -0
@@ -0,0 +1,104 @@
1
+ require_relative './version'
2
+ require_relative './gem'
3
+ require 'shellwords'
4
+
5
+ module TinyTds
6
+ class Bin
7
+
8
+ attr_reader :name
9
+
10
+ class << self
11
+ def exe(name, *args)
12
+ bin = new(name)
13
+ puts bin.info unless args.any? { |x| x == '-q' }
14
+ bin.run(*args)
15
+ end
16
+ end
17
+
18
+ def initialize(name)
19
+ @root = Gem.root_path
20
+ @exts = (ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']) | ['.exe']
21
+
22
+ @name = name
23
+ @binstub = find_bin
24
+ @exefile = find_exe
25
+ end
26
+
27
+ def run(*args)
28
+ with_ports_paths do
29
+ return nil unless path
30
+ Kernel.system Shellwords.join(args.unshift(path))
31
+ $CHILD_STATUS.to_i
32
+ end
33
+ end
34
+
35
+ def path
36
+ @path ||= @exefile && File.exist?(@exefile) ? @exefile : which
37
+ end
38
+
39
+ def info
40
+ "[TinyTds][v#{TinyTds::VERSION}][#{name}]: #{path}"
41
+ end
42
+
43
+ private
44
+
45
+ def search_paths
46
+ ENV['PATH'].split File::PATH_SEPARATOR
47
+ end
48
+
49
+ def with_ports_paths
50
+ old_path = ENV['PATH']
51
+
52
+ begin
53
+ ENV['PATH'] = [
54
+ Gem.ports_bin_paths,
55
+ old_path
56
+ ].flatten.join File::PATH_SEPARATOR
57
+
58
+ yield if block_given?
59
+ ensure
60
+ ENV['PATH'] = old_path
61
+ end
62
+ end
63
+
64
+ def find_bin
65
+ File.join @root, 'bin', name
66
+ end
67
+
68
+ def find_exe
69
+ Gem.ports_bin_paths.each do |bin|
70
+ @exts.each do |ext|
71
+ f = File.join bin, "#{name}#{ext}"
72
+ return f if File.exist?(f)
73
+ end
74
+ end
75
+ nil
76
+ end
77
+
78
+ def which
79
+ search_paths.each do |path|
80
+ @exts.each do |ext|
81
+ exe = File.expand_path File.join(path, "#{name}#{ext}"), @root
82
+ next if exe == @binstub
83
+ next unless File.executable?(exe)
84
+ next unless binary?(exe)
85
+ return exe
86
+ end
87
+ end
88
+ nil
89
+ end
90
+
91
+ # Implementation directly copied from ptools.
92
+ # https://github.com/djberg96/ptools
93
+ # https://opensource.org/licenses/Artistic-2.0
94
+ #
95
+ def binary?(file)
96
+ bytes = File.stat(file).blksize
97
+ return false unless bytes
98
+ bytes = 4096 if bytes > 4096
99
+ s = (File.read(file, bytes) || '')
100
+ s = s.encode('US-ASCII', undef: :replace).split(//)
101
+ ((s.size - s.grep(' '..'~').size) / s.size.to_f) > 0.30
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,136 @@
1
+ module TinyTds
2
+ class Client
3
+
4
+ @default_query_options = {
5
+ as: :hash,
6
+ symbolize_keys: false,
7
+ cache_rows: true,
8
+ timezone: :local,
9
+ empty_sets: true
10
+ }
11
+
12
+ attr_reader :query_options
13
+ attr_reader :message_handler
14
+
15
+ class << self
16
+
17
+ attr_reader :default_query_options
18
+
19
+ # Most, if not all, iconv encoding names can be found by ruby. Just in case, you can
20
+ # overide this method to return a string name that Encoding.find would work with. Default
21
+ # is to return the passed encoding.
22
+ #
23
+ def transpose_iconv_encoding(encoding)
24
+ encoding
25
+ end
26
+
27
+ def local_offset
28
+ ::Time.local(2010).utc_offset.to_r / 86_400
29
+ end
30
+
31
+ end
32
+
33
+ # rubocop:disable Metrics/AbcSize
34
+ # rubocop:disable Metrics/MethodLength
35
+ # rubocop:disable Metrics/CyclomaticComplexity
36
+ # rubocop:disable Metrics/PerceivedComplexity
37
+ def initialize(opts = {})
38
+ if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
39
+ raise ArgumentError, 'missing :host option if no :dataserver given'
40
+ end
41
+
42
+ @message_handler = opts[:message_handler]
43
+ if @message_handler && !@message_handler.respond_to?(:call)
44
+ raise ArgumentError, ':message_handler must implement `call` (eg, a Proc or a Method)'
45
+ end
46
+
47
+ opts[:username] = parse_username(opts)
48
+ @query_options = self.class.default_query_options.dup
49
+ opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip != ''
50
+ opts[:appname] ||= 'TinyTds'
51
+ opts[:tds_version] = tds_versions_setter(opts)
52
+ opts[:use_utf16] = opts[:use_utf16].nil? || ["true", "1", "yes"].include?(opts[:use_utf16].to_s)
53
+ opts[:login_timeout] ||= 60
54
+ opts[:timeout] ||= 5
55
+ opts[:encoding] = opts[:encoding].nil? || opts[:encoding].casecmp('utf8').zero? ? 'UTF-8' : opts[:encoding].upcase
56
+ opts[:port] ||= 1433
57
+ opts[:dataserver] = "#{opts[:host]}:#{opts[:port]}" if opts[:dataserver].to_s.empty?
58
+ forced_integer_keys = [:login_timeout, :port, :timeout]
59
+ forced_integer_keys.each { |k| opts[k] = opts[k].to_i if opts[k] }
60
+ connect(opts)
61
+ end
62
+
63
+ def tds_73?
64
+ tds_version >= 11
65
+ end
66
+
67
+ def tds_version_info
68
+ info = TDS_VERSIONS_GETTERS[tds_version]
69
+ "#{info[:name]} - #{info[:description]}" if info
70
+ end
71
+
72
+ def active?
73
+ !closed? && !dead?
74
+ end
75
+
76
+ private
77
+
78
+ def parse_username(opts)
79
+ host = opts[:host]
80
+ username = opts[:username]
81
+ return username if username.nil? || !opts[:azure]
82
+ return username if username.include?('@') && !username.include?('database.windows.net')
83
+ user, domain = username.split('@')
84
+ domain ||= host
85
+ "#{user}@#{domain.split('.').first}"
86
+ end
87
+
88
+ def tds_versions_setter(opts = {})
89
+ v = opts[:tds_version] || ENV['TDSVER'] || '7.3'
90
+ TDS_VERSIONS_SETTERS[v.to_s]
91
+ end
92
+
93
+ # From sybdb.h comments:
94
+ # DBVERSION_xxx are used with dbsetversion()
95
+ #
96
+ TDS_VERSIONS_SETTERS = {
97
+ 'unknown' => 0,
98
+ '46' => 1,
99
+ '100' => 2,
100
+ '42' => 3,
101
+ '70' => 4,
102
+ '7.0' => 4,
103
+ '71' => 5,
104
+ '7.1' => 5,
105
+ '80' => 5,
106
+ '8.0' => 5,
107
+ '72' => 6,
108
+ '7.2' => 6,
109
+ '90' => 6,
110
+ '9.0' => 6,
111
+ '73' => 7,
112
+ '7.3' => 7
113
+ }.freeze
114
+
115
+ # From sybdb.h comments:
116
+ # DBTDS_xxx are returned by DBTDS()
117
+ # The integer values of the constants are poorly chosen.
118
+ #
119
+ TDS_VERSIONS_GETTERS = {
120
+ 0 => { name: 'DBTDS_UNKNOWN', description: 'Unknown' },
121
+ 1 => { name: 'DBTDS_2_0', description: 'Pre 4.0 SQL Server' },
122
+ 2 => { name: 'DBTDS_3_4', description: 'Microsoft SQL Server (3.0)' },
123
+ 3 => { name: 'DBTDS_4_0', description: '4.0 SQL Server' },
124
+ 4 => { name: 'DBTDS_4_2', description: '4.2 SQL Server' },
125
+ 5 => { name: 'DBTDS_4_6', description: '2.0 OpenServer and 4.6 SQL Server.' },
126
+ 6 => { name: 'DBTDS_4_9_5', description: '4.9.5 (NCR) SQL Server' },
127
+ 7 => { name: 'DBTDS_5_0', description: '5.0 SQL Server' },
128
+ 8 => { name: 'DBTDS_7_0', description: 'Microsoft SQL Server 7.0' },
129
+ 9 => { name: 'DBTDS_7_1/DBTDS_8_0', description: 'Microsoft SQL Server 2000' },
130
+ 10 => { name: 'DBTDS_7_2/DBTDS_9_0', description: 'Microsoft SQL Server 2005' },
131
+ 11 => { name: 'DBTDS_7_3', description: 'Microsoft SQL Server 2008' },
132
+ 12 => { name: 'DBTDS_7_4', description: 'Microsoft SQL Server 2012/2014' }
133
+ }.freeze
134
+
135
+ end
136
+ end
@@ -0,0 +1,14 @@
1
+ module TinyTds
2
+ class Error < StandardError
3
+
4
+ attr_accessor :source, :severity, :db_error_number, :os_error_number
5
+
6
+ def initialize(message)
7
+ super
8
+ @severity = nil
9
+ @db_error_number = nil
10
+ @os_error_number = nil
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ require 'rbconfig'
2
+
3
+ module TinyTds
4
+ module Gem
5
+ class << self
6
+ def root_path
7
+ File.expand_path '../../..', __FILE__
8
+ end
9
+
10
+ def ports_root_path
11
+ File.join(root_path,'ports')
12
+ end
13
+
14
+ def ports_bin_paths
15
+ Dir.glob(File.join(ports_root_path,ports_host,'**','bin'))
16
+ end
17
+
18
+ def ports_lib_paths
19
+ Dir.glob(File.join(ports_root_path,ports_host,'**','lib'))
20
+ end
21
+
22
+ def ports_host
23
+ RbConfig::CONFIG["arch"]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ module TinyTds
2
+ class Result
3
+
4
+ include Enumerable
5
+
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module TinyTds
2
+ VERSION = File.read(File.expand_path('../../../VERSION', __FILE__)).chomp
3
+ end
data/lib/tiny_tds.rb ADDED
@@ -0,0 +1,61 @@
1
+ # encoding: UTF-8
2
+ require 'date'
3
+ require 'bigdecimal'
4
+ require 'rational'
5
+
6
+ require 'tiny_tds/version'
7
+ require 'tiny_tds/error'
8
+ require 'tiny_tds/client'
9
+ require 'tiny_tds/result'
10
+ require 'tiny_tds/gem'
11
+
12
+ # Support multiple ruby versions, fat binaries under Windows.
13
+ if RUBY_PLATFORM =~ /mingw|mswin/ && RUBY_VERSION =~ /(\d+.\d+)/
14
+ ver = Regexp.last_match(1)
15
+
16
+ add_dll_path = proc do |path, &block|
17
+ begin
18
+ require 'ruby_installer/runtime'
19
+ RubyInstaller::Runtime.add_dll_directory(path, &block)
20
+ rescue LoadError
21
+ old_path = ENV['PATH']
22
+ ENV['PATH'] = "#{path};#{old_path}"
23
+ begin
24
+ block.call
25
+ ensure
26
+ ENV['PATH'] = old_path
27
+ end
28
+ end
29
+ end
30
+
31
+ add_dll_paths = proc do |paths, &block|
32
+ if path=paths.shift
33
+ add_dll_path.call(path) do
34
+ add_dll_paths.call(paths, &block)
35
+ end
36
+ else
37
+ block.call
38
+ end
39
+ end
40
+
41
+ # Temporary add bin directories for DLL search, so that freetds DLLs can be found.
42
+ add_dll_paths.call( TinyTds::Gem.ports_bin_paths ) do
43
+ begin
44
+ require "tiny_tds/#{ver}/tiny_tds"
45
+ rescue LoadError
46
+ require 'tiny_tds/tiny_tds'
47
+ end
48
+ end
49
+ else
50
+ # Load dependent shared libraries into the process, so that they are already present,
51
+ # when tiny_tds.so is loaded. This ensures, that shared libraries are loaded even when
52
+ # the path is different between build and run time (e.g. Heroku).
53
+ ports_libs = File.join(TinyTds::Gem.ports_root_path,
54
+ "#{RbConfig::CONFIG['host']}/lib/*.so")
55
+ Dir[ports_libs].each do |lib|
56
+ require 'fiddle'
57
+ Fiddle.dlopen(lib)
58
+ end
59
+
60
+ require 'tiny_tds/tiny_tds'
61
+ end
@@ -0,0 +1,34 @@
1
+ diff --git a/src/tds/tls.c b/src/tds/tls.c
2
+ index 09e7fa0..1da18f6 100644
3
+ --- a/src/tds/tls.c
4
+ +++ b/src/tds/tls.c
5
+ @@ -101,6 +101,29 @@
6
+ #define SSL_PTR BIO_get_data(bio)
7
+ #endif
8
+
9
+ +/*
10
+ + * Add a workaround for older Mingw versions without inet_pton().
11
+ + * This means RubyInstallers DevKit-4.7.2 in particular.
12
+ + */
13
+ +#if defined(__MINGW32__) && !defined(InetPtonA)
14
+ + #include <windows.h>
15
+ +
16
+ + static HMODULE ws2_32 = NULL;
17
+ + typedef INT (WINAPI * __inet_pton)(INT Family, LPCWSTR pStringBuf, PVOID pAddr);
18
+ + static __inet_pton _inet_pton = NULL;
19
+ +
20
+ + INT WINAPI inet_pton(INT Family, LPCWSTR pStringBuf, PVOID pAddr)
21
+ + {
22
+ + if (_inet_pton == NULL) {
23
+ + ws2_32 = LoadLibraryEx("Ws2_32.dll", NULL, 0);
24
+ +
25
+ + _inet_pton = (__inet_pton)GetProcAddress(ws2_32, "inet_pton");
26
+ + }
27
+ +
28
+ + return (_inet_pton)(Family, pStringBuf, pAddr);
29
+ + }
30
+ +#endif
31
+ +
32
+ static SSL_RET
33
+ tds_pull_func_login(SSL_PULL_ARGS)
34
+ {
@@ -0,0 +1,28 @@
1
+ From 56e8972f66c3e948e2ad6885595c58fd23dcdb37 Mon Sep 17 00:00:00 2001
2
+ From: Lars Kanis <kanis@comcard.de>
3
+ Date: Thu, 6 Jul 2017 17:09:40 +0200
4
+ Subject: [PATCH] Don't use MSYS2 file libws2_32.a for MINGW build
5
+
6
+ This file is intended for MSYS2/cygwin builds and blocks OpenSSL
7
+ detection of freetds on i686.
8
+ ---
9
+ configure | 2 --
10
+ configure.ac | 2 --
11
+ 2 files changed, 4 deletions(-)
12
+
13
+ diff --git a/configure b/configure
14
+ index 9495a49..31eb01d 100644
15
+ --- a/configure
16
+ +++ b/configure
17
+ @@ -15915,8 +15915,6 @@ case $host in
18
+ tds_mingw=yes
19
+ if test "$host_cpu" = "x86_64"; then
20
+ LIBS="-lws2_32"
21
+ - elif test -r /usr/lib/w32api/libws2_32.a; then
22
+ - LIBS="-L/usr/lib/w32api -lws2_32"
23
+ else
24
+ LIBS="-lws2_32"
25
+ fi
26
+ --
27
+ 2.6.2.windows.1
28
+
@@ -0,0 +1,17 @@
1
+ --- a/srclib/stdio.in.h 2017-01-22 01:23:00.000000000 -0400
2
+ +++ b/srclib/stdio.in.h 2017-01-22 01:24:00.000000000 -0400
3
+ @@ -695,8 +695,14 @@
4
+ /* It is very rare that the developer ever has full control of stdin,
5
+ so any use of gets warrants an unconditional warning. Assume it is
6
+ always declared, since it is required by C89. */
7
+ +#if defined(__GLIBC__) && !defined(__UCLIBC__)
8
+ +# ifdef __GLIBC_PREREQ
9
+ +# if !__GLIBC_PREREQ(2, 16)
10
+ _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
11
+ +# endif
12
+ +# endif
13
+ +#endif
14
+ #endif
15
+
16
+
17
+ #if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@