|
|
@@ -1,4 +1,5 @@
|
|
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
|
+ *
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
@@ -64,11 +65,18 @@
|
|
|
#define RDWR_BUF_SIZE 4096
|
|
|
#define EQ(a,b) (strcmp(a,b) == 0)
|
|
|
|
|
|
+static uv_mutex_t process_title_mutex;
|
|
|
+static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
|
|
static void* args_mem = NULL;
|
|
|
static char** process_argv = NULL;
|
|
|
static int process_argc = 0;
|
|
|
static char* process_title_ptr = NULL;
|
|
|
|
|
|
+static void init_process_title_mutex_once(void) {
|
|
|
+ uv_mutex_init(&process_title_mutex);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
int uv__platform_loop_init(uv_loop_t* loop) {
|
|
|
loop->fs_fd = -1;
|
|
|
|
|
|
@@ -316,104 +324,6 @@ update_timeout:
|
|
|
}
|
|
|
|
|
|
|
|
|
-uint64_t uv__hrtime(uv_clocktype_t type) {
|
|
|
- uint64_t G = 1000000000;
|
|
|
- timebasestruct_t t;
|
|
|
- read_wall_time(&t, TIMEBASE_SZ);
|
|
|
- time_base_to_time(&t, TIMEBASE_SZ);
|
|
|
- return (uint64_t) t.tb_high * G + t.tb_low;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*
|
|
|
- * We could use a static buffer for the path manipulations that we need outside
|
|
|
- * of the function, but this function could be called by multiple consumers and
|
|
|
- * we don't want to potentially create a race condition in the use of snprintf.
|
|
|
- * There is no direct way of getting the exe path in AIX - either through /procfs
|
|
|
- * or through some libc APIs. The below approach is to parse the argv[0]'s pattern
|
|
|
- * and use it in conjunction with PATH environment variable to craft one.
|
|
|
- */
|
|
|
-int uv_exepath(char* buffer, size_t* size) {
|
|
|
- int res;
|
|
|
- char args[PATH_MAX];
|
|
|
- char abspath[PATH_MAX];
|
|
|
- size_t abspath_size;
|
|
|
- struct procsinfo pi;
|
|
|
-
|
|
|
- if (buffer == NULL || size == NULL || *size == 0)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- pi.pi_pid = getpid();
|
|
|
- res = getargs(&pi, sizeof(pi), args, sizeof(args));
|
|
|
- if (res < 0)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- /*
|
|
|
- * Possibilities for args:
|
|
|
- * i) an absolute path such as: /home/user/myprojects/nodejs/node
|
|
|
- * ii) a relative path such as: ./node or ../myprojects/nodejs/node
|
|
|
- * iii) a bare filename such as "node", after exporting PATH variable
|
|
|
- * to its location.
|
|
|
- */
|
|
|
-
|
|
|
- /* Case i) and ii) absolute or relative paths */
|
|
|
- if (strchr(args, '/') != NULL) {
|
|
|
- if (realpath(args, abspath) != abspath)
|
|
|
- return -errno;
|
|
|
-
|
|
|
- abspath_size = strlen(abspath);
|
|
|
-
|
|
|
- *size -= 1;
|
|
|
- if (*size > abspath_size)
|
|
|
- *size = abspath_size;
|
|
|
-
|
|
|
- memcpy(buffer, abspath, *size);
|
|
|
- buffer[*size] = '\0';
|
|
|
-
|
|
|
- return 0;
|
|
|
- } else {
|
|
|
- /* Case iii). Search PATH environment variable */
|
|
|
- char trypath[PATH_MAX];
|
|
|
- char *clonedpath = NULL;
|
|
|
- char *token = NULL;
|
|
|
- char *path = getenv("PATH");
|
|
|
-
|
|
|
- if (path == NULL)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- clonedpath = uv__strdup(path);
|
|
|
- if (clonedpath == NULL)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- token = strtok(clonedpath, ":");
|
|
|
- while (token != NULL) {
|
|
|
- snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
|
|
|
- if (realpath(trypath, abspath) == abspath) {
|
|
|
- /* Check the match is executable */
|
|
|
- if (access(abspath, X_OK) == 0) {
|
|
|
- abspath_size = strlen(abspath);
|
|
|
-
|
|
|
- *size -= 1;
|
|
|
- if (*size > abspath_size)
|
|
|
- *size = abspath_size;
|
|
|
-
|
|
|
- memcpy(buffer, abspath, *size);
|
|
|
- buffer[*size] = '\0';
|
|
|
-
|
|
|
- uv__free(clonedpath);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- token = strtok(NULL, ":");
|
|
|
- }
|
|
|
- uv__free(clonedpath);
|
|
|
-
|
|
|
- /* Out of tokens (path entries), and no match found */
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
uint64_t uv_get_free_memory(void) {
|
|
|
perfstat_memory_total_t mem_total;
|
|
|
int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1);
|
|
|
@@ -855,6 +765,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|
|
uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
|
|
|
handle->path = uv__strdup(filename);
|
|
|
handle->cb = cb;
|
|
|
+ handle->dir_filename = NULL;
|
|
|
|
|
|
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
|
|
|
|
|
|
@@ -952,6 +863,9 @@ int uv_set_process_title(const char* title) {
|
|
|
if (new_title == NULL)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
|
|
+ uv_mutex_lock(&process_title_mutex);
|
|
|
+
|
|
|
/* If this is the first time this is set,
|
|
|
* don't free and set argv[1] to NULL.
|
|
|
*/
|
|
|
@@ -964,6 +878,8 @@ int uv_set_process_title(const char* title) {
|
|
|
if (process_argc > 1)
|
|
|
process_argv[1] = NULL;
|
|
|
|
|
|
+ uv_mutex_unlock(&process_title_mutex);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -976,8 +892,13 @@ int uv_get_process_title(char* buffer, size_t size) {
|
|
|
else if (size <= len)
|
|
|
return -ENOBUFS;
|
|
|
|
|
|
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
|
|
+ uv_mutex_lock(&process_title_mutex);
|
|
|
+
|
|
|
memcpy(buffer, process_argv[0], len + 1);
|
|
|
|
|
|
+ uv_mutex_unlock(&process_title_mutex);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -1017,6 +938,7 @@ int uv_uptime(double* uptime) {
|
|
|
size_t entries = 0;
|
|
|
time_t boot_time;
|
|
|
|
|
|
+ boot_time = 0;
|
|
|
utmpname(UTMP_FILE);
|
|
|
|
|
|
setutent();
|
|
|
@@ -1093,130 +1015,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < count; ++i) {
|
|
|
- uv__free(cpu_infos[i].model);
|
|
|
- }
|
|
|
-
|
|
|
- uv__free(cpu_infos);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-int uv_interface_addresses(uv_interface_address_t** addresses,
|
|
|
- int* count) {
|
|
|
- uv_interface_address_t* address;
|
|
|
- int sockfd, size = 1;
|
|
|
- struct ifconf ifc;
|
|
|
- struct ifreq *ifr, *p, flg;
|
|
|
-
|
|
|
- *count = 0;
|
|
|
-
|
|
|
- if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
|
|
|
- return -errno;
|
|
|
- }
|
|
|
-
|
|
|
- if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
|
|
|
- uv__close(sockfd);
|
|
|
- return -errno;
|
|
|
- }
|
|
|
-
|
|
|
- ifc.ifc_req = (struct ifreq*)uv__malloc(size);
|
|
|
- ifc.ifc_len = size;
|
|
|
- if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
|
|
|
- uv__close(sockfd);
|
|
|
- return -errno;
|
|
|
- }
|
|
|
-
|
|
|
-#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
|
|
|
-
|
|
|
- /* Count all up and running ipv4/ipv6 addresses */
|
|
|
- ifr = ifc.ifc_req;
|
|
|
- while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
|
|
- p = ifr;
|
|
|
- ifr = (struct ifreq*)
|
|
|
- ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
|
|
|
-
|
|
|
- if (!(p->ifr_addr.sa_family == AF_INET6 ||
|
|
|
- p->ifr_addr.sa_family == AF_INET))
|
|
|
- continue;
|
|
|
-
|
|
|
- memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
|
|
- if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
|
|
- uv__close(sockfd);
|
|
|
- return -errno;
|
|
|
- }
|
|
|
-
|
|
|
- if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
|
|
- continue;
|
|
|
-
|
|
|
- (*count)++;
|
|
|
- }
|
|
|
-
|
|
|
- /* Alloc the return interface structs */
|
|
|
- *addresses = (uv_interface_address_t*)
|
|
|
- uv__malloc(*count * sizeof(uv_interface_address_t));
|
|
|
- if (!(*addresses)) {
|
|
|
- uv__close(sockfd);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
- address = *addresses;
|
|
|
-
|
|
|
- ifr = ifc.ifc_req;
|
|
|
- while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
|
|
- p = ifr;
|
|
|
- ifr = (struct ifreq*)
|
|
|
- ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
|
|
|
-
|
|
|
- if (!(p->ifr_addr.sa_family == AF_INET6 ||
|
|
|
- p->ifr_addr.sa_family == AF_INET))
|
|
|
- continue;
|
|
|
-
|
|
|
- memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
|
|
- if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
|
|
- uv__close(sockfd);
|
|
|
- return -ENOSYS;
|
|
|
- }
|
|
|
-
|
|
|
- if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
|
|
- continue;
|
|
|
-
|
|
|
- /* All conditions above must match count loop */
|
|
|
-
|
|
|
- address->name = uv__strdup(p->ifr_name);
|
|
|
-
|
|
|
- if (p->ifr_addr.sa_family == AF_INET6) {
|
|
|
- address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
|
|
- } else {
|
|
|
- address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
|
|
|
- }
|
|
|
-
|
|
|
- /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
|
|
|
-
|
|
|
- address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
|
|
|
-
|
|
|
- address++;
|
|
|
- }
|
|
|
-
|
|
|
-#undef ADDR_SIZE
|
|
|
-
|
|
|
- uv__close(sockfd);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
|
|
- int count) {
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < count; ++i) {
|
|
|
- uv__free(addresses[i].name);
|
|
|
- }
|
|
|
-
|
|
|
- uv__free(addresses);
|
|
|
-}
|
|
|
-
|
|
|
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
|
|
struct pollfd* events;
|
|
|
uintptr_t i;
|