1
+ /* Copyright libuv project contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include "uv.h"
23
+ #include "internal.h"
24
+
25
+ #include <stdio.h>
26
+ #include <stdint.h>
27
+ #include <stdlib.h>
28
+ #include <string.h>
29
+ #include <assert.h>
30
+ #include <errno.h>
31
+
32
+ #include <sys/types.h>
33
+ #include <sys/socket.h>
34
+ #include <sys/ioctl.h>
35
+ #include <net/if.h>
36
+ #include <netinet/in.h>
37
+ #include <arpa/inet.h>
38
+
39
+ #include <sys/time.h>
40
+ #include <unistd.h>
41
+ #include <fcntl.h>
42
+ #include <utmp.h>
43
+ #include <libgen.h>
44
+
45
+ #include <sys/protosw.h>
46
+ #include <procinfo.h>
47
+ #include <sys/proc.h>
48
+ #include <sys/procfs.h>
49
+
50
+ #include <sys/poll.h>
51
+
52
+ #include <sys/pollset.h>
53
+ #include <ctype.h>
54
+
55
+ #include <sys/mntctl.h>
56
+ #include <sys/vmount.h>
57
+ #include <limits.h>
58
+ #include <strings.h>
59
+ #include <sys/vnode.h>
60
+
61
+ uint64_t uv__hrtime (uv_clocktype_t type ) {
62
+ uint64_t G = 1000000000 ;
63
+ timebasestruct_t t ;
64
+ read_wall_time (& t , TIMEBASE_SZ );
65
+ time_base_to_time (& t , TIMEBASE_SZ );
66
+ return (uint64_t ) t .tb_high * G + t .tb_low ;
67
+ }
68
+
69
+
70
+ /*
71
+ * We could use a static buffer for the path manipulations that we need outside
72
+ * of the function, but this function could be called by multiple consumers and
73
+ * we don't want to potentially create a race condition in the use of snprintf.
74
+ * There is no direct way of getting the exe path in AIX - either through /procfs
75
+ * or through some libc APIs. The below approach is to parse the argv[0]'s pattern
76
+ * and use it in conjunction with PATH environment variable to craft one.
77
+ */
78
+ int uv_exepath (char * buffer , size_t * size ) {
79
+ int res ;
80
+ char args [PATH_MAX ];
81
+ char abspath [PATH_MAX ];
82
+ size_t abspath_size ;
83
+ struct procsinfo pi ;
84
+
85
+ if (buffer == NULL || size == NULL || * size == 0 )
86
+ return - EINVAL ;
87
+
88
+ pi .pi_pid = getpid ();
89
+ res = getargs (& pi , sizeof (pi ), args , sizeof (args ));
90
+ if (res < 0 )
91
+ return - EINVAL ;
92
+
93
+ /*
94
+ * Possibilities for args:
95
+ * i) an absolute path such as: /home/user/myprojects/nodejs/node
96
+ * ii) a relative path such as: ./node or ../myprojects/nodejs/node
97
+ * iii) a bare filename such as "node", after exporting PATH variable
98
+ * to its location.
99
+ */
100
+
101
+ /* Case i) and ii) absolute or relative paths */
102
+ if (strchr (args , '/' ) != NULL ) {
103
+ if (realpath (args , abspath ) != abspath )
104
+ return - errno ;
105
+
106
+ abspath_size = strlen (abspath );
107
+
108
+ * size -= 1 ;
109
+ if (* size > abspath_size )
110
+ * size = abspath_size ;
111
+
112
+ memcpy (buffer , abspath , * size );
113
+ buffer [* size ] = '\0' ;
114
+
115
+ return 0 ;
116
+ } else {
117
+ /* Case iii). Search PATH environment variable */
118
+ char trypath [PATH_MAX ];
119
+ char * clonedpath = NULL ;
120
+ char * token = NULL ;
121
+ char * path = getenv ("PATH" );
122
+
123
+ if (path == NULL )
124
+ return - EINVAL ;
125
+
126
+ clonedpath = uv__strdup (path );
127
+ if (clonedpath == NULL )
128
+ return - ENOMEM ;
129
+
130
+ token = strtok (clonedpath , ":" );
131
+ while (token != NULL ) {
132
+ snprintf (trypath , sizeof (trypath ) - 1 , "%s/%s" , token , args );
133
+ if (realpath (trypath , abspath ) == abspath ) {
134
+ /* Check the match is executable */
135
+ if (access (abspath , X_OK ) == 0 ) {
136
+ abspath_size = strlen (abspath );
137
+
138
+ * size -= 1 ;
139
+ if (* size > abspath_size )
140
+ * size = abspath_size ;
141
+
142
+ memcpy (buffer , abspath , * size );
143
+ buffer [* size ] = '\0' ;
144
+
145
+ uv__free (clonedpath );
146
+ return 0 ;
147
+ }
148
+ }
149
+ token = strtok (NULL , ":" );
150
+ }
151
+ uv__free (clonedpath );
152
+
153
+ /* Out of tokens (path entries), and no match found */
154
+ return - EINVAL ;
155
+ }
156
+ }
157
+
158
+ void uv_free_cpu_info (uv_cpu_info_t * cpu_infos , int count ) {
159
+ int i ;
160
+
161
+ for (i = 0 ; i < count ; ++ i ) {
162
+ uv__free (cpu_infos [i ].model );
163
+ }
164
+
165
+ uv__free (cpu_infos );
166
+ }
167
+
168
+
169
+ int uv_interface_addresses (uv_interface_address_t * * addresses ,
170
+ int * count ) {
171
+ uv_interface_address_t * address ;
172
+ int sockfd , inet6 , size = 1 ;
173
+ struct ifconf ifc ;
174
+ struct ifreq * ifr , * p , flg ;
175
+ struct sockaddr_dl * sa_addr ;
176
+
177
+ * count = 0 ;
178
+
179
+ if (0 > (sockfd = socket (AF_INET , SOCK_DGRAM , IPPROTO_IP ))) {
180
+ return - errno ;
181
+ }
182
+
183
+ if (ioctl (sockfd , SIOCGSIZIFCONF , & size ) == -1 ) {
184
+ uv__close (sockfd );
185
+ return - errno ;
186
+ }
187
+
188
+ ifc .ifc_req = (struct ifreq * )uv__malloc (size );
189
+ ifc .ifc_len = size ;
190
+ if (ioctl (sockfd , SIOCGIFCONF , & ifc ) == -1 ) {
191
+ uv__close (sockfd );
192
+ return - errno ;
193
+ }
194
+
195
+ #define ADDR_SIZE (p ) MAX((p).sa_len, sizeof(p))
196
+
197
+ /* Count all up and running ipv4/ipv6 addresses */
198
+ ifr = ifc .ifc_req ;
199
+ while ((char * )ifr < (char * )ifc .ifc_req + ifc .ifc_len ) {
200
+ p = ifr ;
201
+ ifr = (struct ifreq * )
202
+ ((char * )ifr + sizeof (ifr -> ifr_name ) + ADDR_SIZE (ifr -> ifr_addr ));
203
+
204
+ if (!(p -> ifr_addr .sa_family == AF_INET6 ||
205
+ p -> ifr_addr .sa_family == AF_INET ))
206
+ continue ;
207
+
208
+ memcpy (flg .ifr_name , p -> ifr_name , sizeof (flg .ifr_name ));
209
+ if (ioctl (sockfd , SIOCGIFFLAGS , & flg ) == -1 ) {
210
+ uv__close (sockfd );
211
+ return - errno ;
212
+ }
213
+
214
+ if (!(flg .ifr_flags & IFF_UP && flg .ifr_flags & IFF_RUNNING ))
215
+ continue ;
216
+
217
+ (* count )++ ;
218
+ }
219
+
220
+ /* Alloc the return interface structs */
221
+ * addresses = uv__malloc (* count * sizeof (uv_interface_address_t ));
222
+ if (!(* addresses )) {
223
+ uv__close (sockfd );
224
+ return - ENOMEM ;
225
+ }
226
+ address = * addresses ;
227
+
228
+ ifr = ifc .ifc_req ;
229
+ while ((char * )ifr < (char * )ifc .ifc_req + ifc .ifc_len ) {
230
+ p = ifr ;
231
+ ifr = (struct ifreq * )
232
+ ((char * )ifr + sizeof (ifr -> ifr_name ) + ADDR_SIZE (ifr -> ifr_addr ));
233
+
234
+ if (!(p -> ifr_addr .sa_family == AF_INET6 ||
235
+ p -> ifr_addr .sa_family == AF_INET ))
236
+ continue ;
237
+
238
+ inet6 = (p -> ifr_addr .sa_family == AF_INET6 );
239
+
240
+ memcpy (flg .ifr_name , p -> ifr_name , sizeof (flg .ifr_name ));
241
+ if (ioctl (sockfd , SIOCGIFFLAGS , & flg ) == -1 ) {
242
+ uv__close (sockfd );
243
+ return - ENOSYS ;
244
+ }
245
+
246
+ if (!(flg .ifr_flags & IFF_UP && flg .ifr_flags & IFF_RUNNING ))
247
+ continue ;
248
+
249
+ /* All conditions above must match count loop */
250
+
251
+ address -> name = uv__strdup (p -> ifr_name );
252
+
253
+ if (inet6 )
254
+ address -> address .address6 = * ((struct sockaddr_in6 * ) & p -> ifr_addr );
255
+ else
256
+ address -> address .address4 = * ((struct sockaddr_in * ) & p -> ifr_addr );
257
+
258
+ sa_addr = (struct sockaddr_dl * ) & p -> ifr_addr ;
259
+ memcpy (address -> phys_addr , LLADDR (sa_addr ), sizeof (address -> phys_addr ));
260
+
261
+ if (ioctl (sockfd , SIOCGIFNETMASK , p ) == -1 ) {
262
+ uv__close (sockfd );
263
+ return - ENOSYS ;
264
+ }
265
+
266
+ if (inet6 )
267
+ address -> netmask .netmask6 = * ((struct sockaddr_in6 * ) & p -> ifr_addr );
268
+ else
269
+ address -> netmask .netmask4 = * ((struct sockaddr_in * ) & p -> ifr_addr );
270
+
271
+ address -> is_internal = flg .ifr_flags & IFF_LOOPBACK ? 1 : 0 ;
272
+
273
+ address ++ ;
274
+ }
275
+
276
+ #undef ADDR_SIZE
277
+
278
+ uv__close (sockfd );
279
+ return 0 ;
280
+ }
281
+
282
+
283
+ void uv_free_interface_addresses (uv_interface_address_t * addresses ,
284
+ int count ) {
285
+ int i ;
286
+
287
+ for (i = 0 ; i < count ; ++ i ) {
288
+ uv__free (addresses [i ].name );
289
+ }
290
+
291
+ uv__free (addresses );
292
+ }
0 commit comments