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 <netinet/in6_var.h> 38 #include <arpa/inet.h> 39 40 #include <sys/time.h> 41 #include <unistd.h> 42 #include <fcntl.h> 43 #include <utmp.h> 44 #include <libgen.h> 45 46 #include <sys/protosw.h> 47 #include <procinfo.h> 48 #include <sys/proc.h> 49 #include <sys/procfs.h> 50 51 #include <sys/poll.h> 52 53 #include <sys/pollset.h> 54 #include <ctype.h> 55 56 #include <sys/mntctl.h> 57 #include <sys/vmount.h> 58 #include <limits.h> 59 #include <strings.h> 60 #include <sys/vnode.h> 61 62 uint64_t uv__hrtime(uv_clocktype_t type) { 63 uint64_t G = 1000000000; 64 timebasestruct_t t; 65 read_wall_time(&t, TIMEBASE_SZ); 66 time_base_to_time(&t, TIMEBASE_SZ); 67 return (uint64_t) t.tb_high * G + t.tb_low; 68 } 69 70 71 /* 72 * We could use a static buffer for the path manipulations that we need outside 73 * of the function, but this function could be called by multiple consumers and 74 * we don't want to potentially create a race condition in the use of snprintf. 75 * There is no direct way of getting the exe path in AIX - either through /procfs 76 * or through some libc APIs. The below approach is to parse the argv[0]'s pattern 77 * and use it in conjunction with PATH environment variable to craft one. 78 */ 79 int uv_exepath(char* buffer, size_t* size) { 80 int res; 81 char args[PATH_MAX]; 82 char abspath[PATH_MAX]; 83 size_t abspath_size; 84 struct procsinfo pi; 85 86 if (buffer == NULL || size == NULL || *size == 0) 87 return UV_EINVAL; 88 89 pi.pi_pid = getpid(); 90 res = getargs(&pi, sizeof(pi), args, sizeof(args)); 91 if (res < 0) 92 return UV_EINVAL; 93 94 /* 95 * Possibilities for args: 96 * i) an absolute path such as: /home/user/myprojects/nodejs/node 97 * ii) a relative path such as: ./node or ../myprojects/nodejs/node 98 * iii) a bare filename such as "node", after exporting PATH variable 99 * to its location. 100 */ 101 102 /* Case i) and ii) absolute or relative paths */ 103 if (strchr(args, '/') != NULL) { 104 if (realpath(args, abspath) != abspath) 105 return UV__ERR(errno); 106 107 abspath_size = strlen(abspath); 108 109 *size -= 1; 110 if (*size > abspath_size) 111 *size = abspath_size; 112 113 memcpy(buffer, abspath, *size); 114 buffer[*size] = '\0'; 115 116 return 0; 117 } else { 118 /* Case iii). Search PATH environment variable */ 119 char trypath[PATH_MAX]; 120 char *clonedpath = NULL; 121 char *token = NULL; 122 char *path = getenv("PATH"); 123 124 if (path == NULL) 125 return UV_EINVAL; 126 127 clonedpath = uv__strdup(path); 128 if (clonedpath == NULL) 129 return UV_ENOMEM; 130 131 token = strtok(clonedpath, ":"); 132 while (token != NULL) { 133 snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); 134 if (realpath(trypath, abspath) == abspath) { 135 /* Check the match is executable */ 136 if (access(abspath, X_OK) == 0) { 137 abspath_size = strlen(abspath); 138 139 *size -= 1; 140 if (*size > abspath_size) 141 *size = abspath_size; 142 143 memcpy(buffer, abspath, *size); 144 buffer[*size] = '\0'; 145 146 uv__free(clonedpath); 147 return 0; 148 } 149 } 150 token = strtok(NULL, ":"); 151 } 152 uv__free(clonedpath); 153 154 /* Out of tokens (path entries), and no match found */ 155 return UV_EINVAL; 156 } 157 } 158