• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright Joyent, Inc. and other Node 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 <libperfstat.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 #ifdef HAVE_SYS_AHAFS_EVPRODS_H
56 #include <sys/ahafs_evProds.h>
57 #endif
58 
59 #include <sys/mntctl.h>
60 #include <sys/vmount.h>
61 #include <limits.h>
62 #include <strings.h>
63 #include <sys/vnode.h>
64 
65 #define RDWR_BUF_SIZE   4096
66 #define EQ(a,b)         (strcmp(a,b) == 0)
67 
68 char* original_exepath = NULL;
69 uv_mutex_t process_title_mutex;
70 uv_once_t process_title_mutex_once = UV_ONCE_INIT;
71 static void* args_mem = NULL;
72 static char** process_argv = NULL;
73 static int process_argc = 0;
74 static char* process_title_ptr = NULL;
75 
init_process_title_mutex_once(void)76 void init_process_title_mutex_once(void) {
77   uv_mutex_init(&process_title_mutex);
78 }
79 
80 
uv__platform_loop_init(uv_loop_t * loop)81 int uv__platform_loop_init(uv_loop_t* loop) {
82   loop->fs_fd = -1;
83 
84   /* Passing maxfd of -1 should mean the limit is determined
85    * by the user's ulimit or the global limit as per the doc */
86   loop->backend_fd = pollset_create(-1);
87 
88   if (loop->backend_fd == -1)
89     return -1;
90 
91   return 0;
92 }
93 
94 
uv__platform_loop_delete(uv_loop_t * loop)95 void uv__platform_loop_delete(uv_loop_t* loop) {
96   if (loop->fs_fd != -1) {
97     uv__close(loop->fs_fd);
98     loop->fs_fd = -1;
99   }
100 
101   if (loop->backend_fd != -1) {
102     pollset_destroy(loop->backend_fd);
103     loop->backend_fd = -1;
104   }
105 }
106 
107 
uv__io_fork(uv_loop_t * loop)108 int uv__io_fork(uv_loop_t* loop) {
109   uv__platform_loop_delete(loop);
110 
111   return uv__platform_loop_init(loop);
112 }
113 
114 
uv__io_check_fd(uv_loop_t * loop,int fd)115 int uv__io_check_fd(uv_loop_t* loop, int fd) {
116   struct poll_ctl pc;
117 
118   pc.events = POLLIN;
119   pc.cmd = PS_MOD;  /* Equivalent to PS_ADD if the fd is not in the pollset. */
120   pc.fd = fd;
121 
122   if (pollset_ctl(loop->backend_fd, &pc, 1))
123     return UV__ERR(errno);
124 
125   pc.cmd = PS_DELETE;
126   if (pollset_ctl(loop->backend_fd, &pc, 1))
127     abort();
128 
129   return 0;
130 }
131 
132 
uv__io_poll(uv_loop_t * loop,int timeout)133 void uv__io_poll(uv_loop_t* loop, int timeout) {
134   struct pollfd events[1024];
135   struct pollfd pqry;
136   struct pollfd* pe;
137   struct poll_ctl pc;
138   QUEUE* q;
139   uv__io_t* w;
140   uint64_t base;
141   uint64_t diff;
142   int have_signals;
143   int nevents;
144   int count;
145   int nfds;
146   int i;
147   int rc;
148   int add_failed;
149   int user_timeout;
150   int reset_timeout;
151 
152   if (loop->nfds == 0) {
153     assert(QUEUE_EMPTY(&loop->watcher_queue));
154     return;
155   }
156 
157   while (!QUEUE_EMPTY(&loop->watcher_queue)) {
158     q = QUEUE_HEAD(&loop->watcher_queue);
159     QUEUE_REMOVE(q);
160     QUEUE_INIT(q);
161 
162     w = QUEUE_DATA(q, uv__io_t, watcher_queue);
163     assert(w->pevents != 0);
164     assert(w->fd >= 0);
165     assert(w->fd < (int) loop->nwatchers);
166 
167     pc.events = w->pevents;
168     pc.fd = w->fd;
169 
170     add_failed = 0;
171     if (w->events == 0) {
172       pc.cmd = PS_ADD;
173       if (pollset_ctl(loop->backend_fd, &pc, 1)) {
174         if (errno != EINVAL) {
175           assert(0 && "Failed to add file descriptor (pc.fd) to pollset");
176           abort();
177         }
178         /* Check if the fd is already in the pollset */
179         pqry.fd = pc.fd;
180         rc = pollset_query(loop->backend_fd, &pqry);
181         switch (rc) {
182         case -1:
183           assert(0 && "Failed to query pollset for file descriptor");
184           abort();
185         case 0:
186           assert(0 && "Pollset does not contain file descriptor");
187           abort();
188         }
189         /* If we got here then the pollset already contained the file descriptor even though
190          * we didn't think it should. This probably shouldn't happen, but we can continue. */
191         add_failed = 1;
192       }
193     }
194     if (w->events != 0 || add_failed) {
195       /* Modify, potentially removing events -- need to delete then add.
196        * Could maybe mod if we knew for sure no events are removed, but
197        * content of w->events is handled above as not reliable (falls back)
198        * so may require a pollset_query() which would have to be pretty cheap
199        * compared to a PS_DELETE to be worth optimizing. Alternatively, could
200        * lazily remove events, squelching them in the mean time. */
201       pc.cmd = PS_DELETE;
202       if (pollset_ctl(loop->backend_fd, &pc, 1)) {
203         assert(0 && "Failed to delete file descriptor (pc.fd) from pollset");
204         abort();
205       }
206       pc.cmd = PS_ADD;
207       if (pollset_ctl(loop->backend_fd, &pc, 1)) {
208         assert(0 && "Failed to add file descriptor (pc.fd) to pollset");
209         abort();
210       }
211     }
212 
213     w->events = w->pevents;
214   }
215 
216   assert(timeout >= -1);
217   base = loop->time;
218   count = 48; /* Benchmarks suggest this gives the best throughput. */
219 
220   if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
221     reset_timeout = 1;
222     user_timeout = timeout;
223     timeout = 0;
224   } else {
225     reset_timeout = 0;
226   }
227 
228   for (;;) {
229     /* Only need to set the provider_entry_time if timeout != 0. The function
230      * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
231      */
232     if (timeout != 0)
233       uv__metrics_set_provider_entry_time(loop);
234 
235     nfds = pollset_poll(loop->backend_fd,
236                         events,
237                         ARRAY_SIZE(events),
238                         timeout);
239 
240     /* Update loop->time unconditionally. It's tempting to skip the update when
241      * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
242      * operating system didn't reschedule our process while in the syscall.
243      */
244     SAVE_ERRNO(uv__update_time(loop));
245 
246     if (nfds == 0) {
247       if (reset_timeout != 0) {
248         timeout = user_timeout;
249         reset_timeout = 0;
250         if (timeout == -1)
251           continue;
252         if (timeout > 0)
253           goto update_timeout;
254       }
255 
256       assert(timeout != -1);
257       return;
258     }
259 
260     if (nfds == -1) {
261       if (errno != EINTR) {
262         abort();
263       }
264 
265       if (reset_timeout != 0) {
266         timeout = user_timeout;
267         reset_timeout = 0;
268       }
269 
270       if (timeout == -1)
271         continue;
272 
273       if (timeout == 0)
274         return;
275 
276       /* Interrupted by a signal. Update timeout and poll again. */
277       goto update_timeout;
278     }
279 
280     have_signals = 0;
281     nevents = 0;
282 
283     assert(loop->watchers != NULL);
284     loop->watchers[loop->nwatchers] = (void*) events;
285     loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
286 
287     for (i = 0; i < nfds; i++) {
288       pe = events + i;
289       pc.cmd = PS_DELETE;
290       pc.fd = pe->fd;
291 
292       /* Skip invalidated events, see uv__platform_invalidate_fd */
293       if (pc.fd == -1)
294         continue;
295 
296       assert(pc.fd >= 0);
297       assert((unsigned) pc.fd < loop->nwatchers);
298 
299       w = loop->watchers[pc.fd];
300 
301       if (w == NULL) {
302         /* File descriptor that we've stopped watching, disarm it.
303          *
304          * Ignore all errors because we may be racing with another thread
305          * when the file descriptor is closed.
306          */
307         pollset_ctl(loop->backend_fd, &pc, 1);
308         continue;
309       }
310 
311       /* Run signal watchers last.  This also affects child process watchers
312        * because those are implemented in terms of signal watchers.
313        */
314       if (w == &loop->signal_io_watcher) {
315         have_signals = 1;
316       } else {
317         uv__metrics_update_idle_time(loop);
318         w->cb(loop, w, pe->revents);
319       }
320 
321       nevents++;
322     }
323 
324     if (reset_timeout != 0) {
325       timeout = user_timeout;
326       reset_timeout = 0;
327     }
328 
329     if (have_signals != 0) {
330       uv__metrics_update_idle_time(loop);
331       loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
332     }
333 
334     loop->watchers[loop->nwatchers] = NULL;
335     loop->watchers[loop->nwatchers + 1] = NULL;
336 
337     if (have_signals != 0)
338       return;  /* Event loop should cycle now so don't poll again. */
339 
340     if (nevents != 0) {
341       if (nfds == ARRAY_SIZE(events) && --count != 0) {
342         /* Poll for more events but don't block this time. */
343         timeout = 0;
344         continue;
345       }
346       return;
347     }
348 
349     if (timeout == 0)
350       return;
351 
352     if (timeout == -1)
353       continue;
354 
355 update_timeout:
356     assert(timeout > 0);
357 
358     diff = loop->time - base;
359     if (diff >= (uint64_t) timeout)
360       return;
361 
362     timeout -= diff;
363   }
364 }
365 
366 
uv_get_free_memory(void)367 uint64_t uv_get_free_memory(void) {
368   perfstat_memory_total_t mem_total;
369   int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1);
370   if (result == -1) {
371     return 0;
372   }
373   return mem_total.real_free * 4096;
374 }
375 
376 
uv_get_total_memory(void)377 uint64_t uv_get_total_memory(void) {
378   perfstat_memory_total_t mem_total;
379   int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1);
380   if (result == -1) {
381     return 0;
382   }
383   return mem_total.real_total * 4096;
384 }
385 
386 
uv_get_constrained_memory(void)387 uint64_t uv_get_constrained_memory(void) {
388   return 0;  /* Memory constraints are unknown. */
389 }
390 
391 
uv_loadavg(double avg[3])392 void uv_loadavg(double avg[3]) {
393   perfstat_cpu_total_t ps_total;
394   int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
395   if (result == -1) {
396     avg[0] = 0.; avg[1] = 0.; avg[2] = 0.;
397     return;
398   }
399   avg[0] = ps_total.loadavg[0] / (double)(1 << SBITS);
400   avg[1] = ps_total.loadavg[1] / (double)(1 << SBITS);
401   avg[2] = ps_total.loadavg[2] / (double)(1 << SBITS);
402 }
403 
404 
405 #ifdef HAVE_SYS_AHAFS_EVPRODS_H
uv__rawname(const char * cp,char (* dst)[FILENAME_MAX+1])406 static char* uv__rawname(const char* cp, char (*dst)[FILENAME_MAX+1]) {
407   char* dp;
408 
409   dp = rindex(cp, '/');
410   if (dp == 0)
411     return 0;
412 
413   snprintf(*dst, sizeof(*dst), "%.*s/r%s", (int) (dp - cp), cp, dp + 1);
414   return *dst;
415 }
416 
417 
418 /*
419  * Determine whether given pathname is a directory
420  * Returns 0 if the path is a directory, -1 if not
421  *
422  * Note: Opportunity here for more detailed error information but
423  *       that requires changing callers of this function as well
424  */
uv__path_is_a_directory(char * filename)425 static int uv__path_is_a_directory(char* filename) {
426   struct stat statbuf;
427 
428   if (stat(filename, &statbuf) < 0)
429     return -1;  /* failed: not a directory, assume it is a file */
430 
431   if (statbuf.st_type == VDIR)
432     return 0;
433 
434   return -1;
435 }
436 
437 
438 /*
439  * Check whether AHAFS is mounted.
440  * Returns 0 if AHAFS is mounted, or an error code < 0 on failure
441  */
uv__is_ahafs_mounted(void)442 static int uv__is_ahafs_mounted(void){
443   char rawbuf[FILENAME_MAX+1];
444   int rv, i = 2;
445   struct vmount *p;
446   int size_multiplier = 10;
447   size_t siz = sizeof(struct vmount)*size_multiplier;
448   struct vmount *vmt;
449   const char *dev = "/aha";
450   char *obj, *stub;
451 
452   p = uv__malloc(siz);
453   if (p == NULL)
454     return UV__ERR(errno);
455 
456   /* Retrieve all mounted filesystems */
457   rv = mntctl(MCTL_QUERY, siz, (char*)p);
458   if (rv < 0)
459     return UV__ERR(errno);
460   if (rv == 0) {
461     /* buffer was not large enough, reallocate to correct size */
462     siz = *(int*)p;
463     uv__free(p);
464     p = uv__malloc(siz);
465     if (p == NULL)
466       return UV__ERR(errno);
467     rv = mntctl(MCTL_QUERY, siz, (char*)p);
468     if (rv < 0)
469       return UV__ERR(errno);
470   }
471 
472   /* Look for dev in filesystems mount info */
473   for(vmt = p, i = 0; i < rv; i++) {
474     obj = vmt2dataptr(vmt, VMT_OBJECT);     /* device */
475     stub = vmt2dataptr(vmt, VMT_STUB);      /* mount point */
476 
477     if (EQ(obj, dev) || EQ(uv__rawname(obj, &rawbuf), dev) || EQ(stub, dev)) {
478       uv__free(p);  /* Found a match */
479       return 0;
480     }
481     vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length);
482   }
483 
484   /* /aha is required for monitoring filesystem changes */
485   return -1;
486 }
487 
488 /*
489  * Recursive call to mkdir() to create intermediate folders, if any
490  * Returns code from mkdir call
491  */
uv__makedir_p(const char * dir)492 static int uv__makedir_p(const char *dir) {
493   char tmp[256];
494   char *p = NULL;
495   size_t len;
496   int err;
497 
498   /* TODO(bnoordhuis) Check uv__strscpy() return value. */
499   uv__strscpy(tmp, dir, sizeof(tmp));
500   len = strlen(tmp);
501   if (tmp[len - 1] == '/')
502     tmp[len - 1] = 0;
503   for (p = tmp + 1; *p; p++) {
504     if (*p == '/') {
505       *p = 0;
506       err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
507       if (err != 0 && errno != EEXIST)
508         return err;
509       *p = '/';
510     }
511   }
512   return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
513 }
514 
515 /*
516  * Creates necessary subdirectories in the AIX Event Infrastructure
517  * file system for monitoring the object specified.
518  * Returns code from mkdir call
519  */
uv__make_subdirs_p(const char * filename)520 static int uv__make_subdirs_p(const char *filename) {
521   char cmd[2048];
522   char *p;
523   int rc = 0;
524 
525   /* Strip off the monitor file name */
526   p = strrchr(filename, '/');
527 
528   if (p == NULL)
529     return 0;
530 
531   if (uv__path_is_a_directory((char*)filename) == 0) {
532     sprintf(cmd, "/aha/fs/modDir.monFactory");
533   } else {
534     sprintf(cmd, "/aha/fs/modFile.monFactory");
535   }
536 
537   strncat(cmd, filename, (p - filename));
538   rc = uv__makedir_p(cmd);
539 
540   if (rc == -1 && errno != EEXIST){
541     return UV__ERR(errno);
542   }
543 
544   return rc;
545 }
546 
547 
548 /*
549  * Checks if /aha is mounted, then proceeds to set up the monitoring
550  * objects for the specified file.
551  * Returns 0 on success, or an error code < 0 on failure
552  */
uv__setup_ahafs(const char * filename,int * fd)553 static int uv__setup_ahafs(const char* filename, int *fd) {
554   int rc = 0;
555   char mon_file_write_string[RDWR_BUF_SIZE];
556   char mon_file[PATH_MAX];
557   int file_is_directory = 0; /* -1 == NO, 0 == YES  */
558 
559   /* Create monitor file name for object */
560   file_is_directory = uv__path_is_a_directory((char*)filename);
561 
562   if (file_is_directory == 0)
563     sprintf(mon_file, "/aha/fs/modDir.monFactory");
564   else
565     sprintf(mon_file, "/aha/fs/modFile.monFactory");
566 
567   if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX)
568     return UV_ENAMETOOLONG;
569 
570   /* Make the necessary subdirectories for the monitor file */
571   rc = uv__make_subdirs_p(filename);
572   if (rc == -1 && errno != EEXIST)
573     return rc;
574 
575   strcat(mon_file, filename);
576   strcat(mon_file, ".mon");
577 
578   *fd = 0; errno = 0;
579 
580   /* Open the monitor file, creating it if necessary */
581   *fd = open(mon_file, O_CREAT|O_RDWR);
582   if (*fd < 0)
583     return UV__ERR(errno);
584 
585   /* Write out the monitoring specifications.
586    * In this case, we are monitoring for a state change event type
587    *    CHANGED=YES
588    * We will be waiting in select call, rather than a read:
589    *    WAIT_TYPE=WAIT_IN_SELECT
590    * We only want minimal information for files:
591    *      INFO_LVL=1
592    * For directories, we want more information to track what file
593    * caused the change
594    *      INFO_LVL=2
595    */
596 
597   if (file_is_directory == 0)
598     sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=2");
599   else
600     sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1");
601 
602   rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
603   if (rc < 0 && errno != EBUSY)
604     return UV__ERR(errno);
605 
606   return 0;
607 }
608 
609 /*
610  * Skips a specified number of lines in the buffer passed in.
611  * Walks the buffer pointed to by p and attempts to skip n lines.
612  * Returns the total number of lines skipped
613  */
uv__skip_lines(char ** p,int n)614 static int uv__skip_lines(char **p, int n) {
615   int lines = 0;
616 
617   while(n > 0) {
618     *p = strchr(*p, '\n');
619     if (!p)
620       return lines;
621 
622     (*p)++;
623     n--;
624     lines++;
625   }
626   return lines;
627 }
628 
629 
630 /*
631  * Parse the event occurrence data to figure out what event just occurred
632  * and take proper action.
633  *
634  * The buf is a pointer to the buffer containing the event occurrence data
635  * Returns 0 on success, -1 if unrecoverable error in parsing
636  *
637  */
uv__parse_data(char * buf,int * events,uv_fs_event_t * handle)638 static int uv__parse_data(char *buf, int *events, uv_fs_event_t* handle) {
639   int    evp_rc, i;
640   char   *p;
641   char   filename[PATH_MAX]; /* To be used when handling directories */
642 
643   p = buf;
644   *events = 0;
645 
646   /* Clean the filename buffer*/
647   for(i = 0; i < PATH_MAX; i++) {
648     filename[i] = 0;
649   }
650   i = 0;
651 
652   /* Check for BUF_WRAP */
653   if (strncmp(buf, "BUF_WRAP", strlen("BUF_WRAP")) == 0) {
654     assert(0 && "Buffer wrap detected, Some event occurrences lost!");
655     return 0;
656   }
657 
658   /* Since we are using the default buffer size (4K), and have specified
659    * INFO_LVL=1, we won't see any EVENT_OVERFLOW conditions.  Applications
660    * should check for this keyword if they are using an INFO_LVL of 2 or
661    * higher, and have a buffer size of <= 4K
662    */
663 
664   /* Skip to RC_FROM_EVPROD */
665   if (uv__skip_lines(&p, 9) != 9)
666     return -1;
667 
668   if (sscanf(p, "RC_FROM_EVPROD=%d\nEND_EVENT_DATA", &evp_rc) == 1) {
669     if (uv__path_is_a_directory(handle->path) == 0) { /* Directory */
670       if (evp_rc == AHAFS_MODDIR_UNMOUNT || evp_rc == AHAFS_MODDIR_REMOVE_SELF) {
671         /* The directory is no longer available for monitoring */
672         *events = UV_RENAME;
673         handle->dir_filename = NULL;
674       } else {
675         /* A file was added/removed inside the directory */
676         *events = UV_CHANGE;
677 
678         /* Get the EVPROD_INFO */
679         if (uv__skip_lines(&p, 1) != 1)
680           return -1;
681 
682         /* Scan out the name of the file that triggered the event*/
683         if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) {
684           handle->dir_filename = uv__strdup((const char*)&filename);
685         } else
686           return -1;
687         }
688     } else { /* Regular File */
689       if (evp_rc == AHAFS_MODFILE_RENAME)
690         *events = UV_RENAME;
691       else
692         *events = UV_CHANGE;
693     }
694   }
695   else
696     return -1;
697 
698   return 0;
699 }
700 
701 
702 /* This is the internal callback */
uv__ahafs_event(uv_loop_t * loop,uv__io_t * event_watch,unsigned int fflags)703 static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int fflags) {
704   char   result_data[RDWR_BUF_SIZE];
705   int bytes, rc = 0;
706   uv_fs_event_t* handle;
707   int events = 0;
708   char fname[PATH_MAX];
709   char *p;
710 
711   handle = container_of(event_watch, uv_fs_event_t, event_watcher);
712 
713   /* At this point, we assume that polling has been done on the
714    * file descriptor, so we can just read the AHAFS event occurrence
715    * data and parse its results without having to block anything
716    */
717   bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0);
718 
719   assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file");
720 
721   /* In file / directory move cases, AIX Event infrastructure
722    * produces a second event with no data.
723    * Ignore it and return gracefully.
724    */
725   if(bytes == 0)
726     return;
727 
728   /* Parse the data */
729   if(bytes > 0)
730     rc = uv__parse_data(result_data, &events, handle);
731 
732   /* Unrecoverable error */
733   if (rc == -1)
734     return;
735 
736   /* For directory changes, the name of the files that triggered the change
737    * are never absolute pathnames
738    */
739   if (uv__path_is_a_directory(handle->path) == 0) {
740     p = handle->dir_filename;
741   } else {
742     p = strrchr(handle->path, '/');
743     if (p == NULL)
744       p = handle->path;
745     else
746       p++;
747   }
748 
749   /* TODO(bnoordhuis) Check uv__strscpy() return value. */
750   uv__strscpy(fname, p, sizeof(fname));
751 
752   handle->cb(handle, fname, events, 0);
753 }
754 #endif
755 
756 
uv_fs_event_init(uv_loop_t * loop,uv_fs_event_t * handle)757 int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
758 #ifdef HAVE_SYS_AHAFS_EVPRODS_H
759   uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
760   return 0;
761 #else
762   return UV_ENOSYS;
763 #endif
764 }
765 
766 
uv_fs_event_start(uv_fs_event_t * handle,uv_fs_event_cb cb,const char * filename,unsigned int flags)767 int uv_fs_event_start(uv_fs_event_t* handle,
768                       uv_fs_event_cb cb,
769                       const char* filename,
770                       unsigned int flags) {
771 #ifdef HAVE_SYS_AHAFS_EVPRODS_H
772   int  fd, rc, str_offset = 0;
773   char cwd[PATH_MAX];
774   char absolute_path[PATH_MAX];
775   char readlink_cwd[PATH_MAX];
776   struct timeval zt;
777   fd_set pollfd;
778 
779 
780   /* Figure out whether filename is absolute or not */
781   if (filename[0] == '\0') {
782     /* Missing a pathname */
783     return UV_ENOENT;
784   }
785   else if (filename[0] == '/') {
786     /* We have absolute pathname */
787     /* TODO(bnoordhuis) Check uv__strscpy() return value. */
788     uv__strscpy(absolute_path, filename, sizeof(absolute_path));
789   } else {
790     /* We have a relative pathname, compose the absolute pathname */
791     snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid());
792     rc = readlink(cwd, readlink_cwd, sizeof(readlink_cwd) - 1);
793     if (rc < 0)
794       return rc;
795     /* readlink does not null terminate our string */
796     readlink_cwd[rc] = '\0';
797 
798     if (filename[0] == '.' && filename[1] == '/')
799       str_offset = 2;
800 
801     snprintf(absolute_path, sizeof(absolute_path), "%s%s", readlink_cwd,
802              filename + str_offset);
803   }
804 
805   if (uv__is_ahafs_mounted() < 0)  /* /aha checks failed */
806     return UV_ENOSYS;
807 
808   /* Setup ahafs */
809   rc = uv__setup_ahafs((const char *)absolute_path, &fd);
810   if (rc != 0)
811     return rc;
812 
813   /* Setup/Initialize all the libuv routines */
814   uv__handle_start(handle);
815   uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
816   handle->path = uv__strdup(filename);
817   handle->cb = cb;
818   handle->dir_filename = NULL;
819 
820   uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
821 
822   /* AHAFS wants someone to poll for it to start mointoring.
823    *  so kick-start it so that we don't miss an event in the
824    *  eventuality of an event that occurs in the current loop. */
825   do {
826     memset(&zt, 0, sizeof(zt));
827     FD_ZERO(&pollfd);
828     FD_SET(fd, &pollfd);
829     rc = select(fd + 1, &pollfd, NULL, NULL, &zt);
830   } while (rc == -1 && errno == EINTR);
831   return 0;
832 #else
833   return UV_ENOSYS;
834 #endif
835 }
836 
837 
uv_fs_event_stop(uv_fs_event_t * handle)838 int uv_fs_event_stop(uv_fs_event_t* handle) {
839 #ifdef HAVE_SYS_AHAFS_EVPRODS_H
840   if (!uv__is_active(handle))
841     return 0;
842 
843   uv__io_close(handle->loop, &handle->event_watcher);
844   uv__handle_stop(handle);
845 
846   if (uv__path_is_a_directory(handle->path) == 0) {
847     uv__free(handle->dir_filename);
848     handle->dir_filename = NULL;
849   }
850 
851   uv__free(handle->path);
852   handle->path = NULL;
853   uv__close(handle->event_watcher.fd);
854   handle->event_watcher.fd = -1;
855 
856   return 0;
857 #else
858   return UV_ENOSYS;
859 #endif
860 }
861 
862 
uv__fs_event_close(uv_fs_event_t * handle)863 void uv__fs_event_close(uv_fs_event_t* handle) {
864 #ifdef HAVE_SYS_AHAFS_EVPRODS_H
865   uv_fs_event_stop(handle);
866 #else
867   UNREACHABLE();
868 #endif
869 }
870 
871 
uv_setup_args(int argc,char ** argv)872 char** uv_setup_args(int argc, char** argv) {
873   char exepath[UV__PATH_MAX];
874   char** new_argv;
875   size_t size;
876   char* s;
877   int i;
878 
879   if (argc <= 0)
880     return argv;
881 
882   /* Save the original pointer to argv.
883    * AIX uses argv to read the process name.
884    * (Not the memory pointed to by argv[0..n] as on Linux.)
885    */
886   process_argv = argv;
887   process_argc = argc;
888 
889   /* Use argv[0] to determine value for uv_exepath(). */
890   size = sizeof(exepath);
891   if (uv__search_path(argv[0], exepath, &size) == 0) {
892     uv_once(&process_title_mutex_once, init_process_title_mutex_once);
893     uv_mutex_lock(&process_title_mutex);
894     original_exepath = uv__strdup(exepath);
895     uv_mutex_unlock(&process_title_mutex);
896   }
897 
898   /* Calculate how much memory we need for the argv strings. */
899   size = 0;
900   for (i = 0; i < argc; i++)
901     size += strlen(argv[i]) + 1;
902 
903   /* Add space for the argv pointers. */
904   size += (argc + 1) * sizeof(char*);
905 
906   new_argv = uv__malloc(size);
907   if (new_argv == NULL)
908     return argv;
909   args_mem = new_argv;
910 
911   /* Copy over the strings and set up the pointer table. */
912   s = (char*) &new_argv[argc + 1];
913   for (i = 0; i < argc; i++) {
914     size = strlen(argv[i]) + 1;
915     memcpy(s, argv[i], size);
916     new_argv[i] = s;
917     s += size;
918   }
919   new_argv[i] = NULL;
920 
921   return new_argv;
922 }
923 
924 
uv_set_process_title(const char * title)925 int uv_set_process_title(const char* title) {
926   char* new_title;
927 
928   /* If uv_setup_args wasn't called or failed, we can't continue. */
929   if (process_argv == NULL || args_mem == NULL)
930     return UV_ENOBUFS;
931 
932   /* We cannot free this pointer when libuv shuts down,
933    * the process may still be using it.
934    */
935   new_title = uv__strdup(title);
936   if (new_title == NULL)
937     return UV_ENOMEM;
938 
939   uv_once(&process_title_mutex_once, init_process_title_mutex_once);
940   uv_mutex_lock(&process_title_mutex);
941 
942   /* If this is the first time this is set,
943    * don't free and set argv[1] to NULL.
944    */
945   if (process_title_ptr != NULL)
946     uv__free(process_title_ptr);
947 
948   process_title_ptr = new_title;
949 
950   process_argv[0] = process_title_ptr;
951   if (process_argc > 1)
952      process_argv[1] = NULL;
953 
954   uv_mutex_unlock(&process_title_mutex);
955 
956   return 0;
957 }
958 
959 
uv_get_process_title(char * buffer,size_t size)960 int uv_get_process_title(char* buffer, size_t size) {
961   size_t len;
962   if (buffer == NULL || size == 0)
963     return UV_EINVAL;
964 
965   /* If uv_setup_args wasn't called, we can't continue. */
966   if (process_argv == NULL)
967     return UV_ENOBUFS;
968 
969   uv_once(&process_title_mutex_once, init_process_title_mutex_once);
970   uv_mutex_lock(&process_title_mutex);
971 
972   len = strlen(process_argv[0]);
973   if (size <= len) {
974     uv_mutex_unlock(&process_title_mutex);
975     return UV_ENOBUFS;
976   }
977 
978   memcpy(buffer, process_argv[0], len);
979   buffer[len] = '\0';
980 
981   uv_mutex_unlock(&process_title_mutex);
982 
983   return 0;
984 }
985 
986 
uv__process_title_cleanup(void)987 void uv__process_title_cleanup(void) {
988   uv__free(args_mem);  /* Keep valgrind happy. */
989   args_mem = NULL;
990 }
991 
992 
uv_resident_set_memory(size_t * rss)993 int uv_resident_set_memory(size_t* rss) {
994   char pp[64];
995   psinfo_t psinfo;
996   int err;
997   int fd;
998 
999   snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
1000 
1001   fd = open(pp, O_RDONLY);
1002   if (fd == -1)
1003     return UV__ERR(errno);
1004 
1005   /* FIXME(bnoordhuis) Handle EINTR. */
1006   err = UV_EINVAL;
1007   if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
1008     *rss = (size_t)psinfo.pr_rssize * 1024;
1009     err = 0;
1010   }
1011   uv__close(fd);
1012 
1013   return err;
1014 }
1015 
1016 
uv_uptime(double * uptime)1017 int uv_uptime(double* uptime) {
1018   struct utmp *utmp_buf;
1019   size_t entries = 0;
1020   time_t boot_time;
1021 
1022   boot_time = 0;
1023   utmpname(UTMP_FILE);
1024 
1025   setutent();
1026 
1027   while ((utmp_buf = getutent()) != NULL) {
1028     if (utmp_buf->ut_user[0] && utmp_buf->ut_type == USER_PROCESS)
1029       ++entries;
1030     if (utmp_buf->ut_type == BOOT_TIME)
1031       boot_time = utmp_buf->ut_time;
1032   }
1033 
1034   endutent();
1035 
1036   if (boot_time == 0)
1037     return UV_ENOSYS;
1038 
1039   *uptime = time(NULL) - boot_time;
1040   return 0;
1041 }
1042 
1043 
uv_cpu_info(uv_cpu_info_t ** cpu_infos,int * count)1044 int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
1045   uv_cpu_info_t* cpu_info;
1046   perfstat_cpu_total_t ps_total;
1047   perfstat_cpu_t* ps_cpus;
1048   perfstat_id_t cpu_id;
1049   int result, ncpus, idx = 0;
1050 
1051   result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
1052   if (result == -1) {
1053     return UV_ENOSYS;
1054   }
1055 
1056   ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
1057   if (result == -1) {
1058     return UV_ENOSYS;
1059   }
1060 
1061   ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t));
1062   if (!ps_cpus) {
1063     return UV_ENOMEM;
1064   }
1065 
1066   /* TODO(bnoordhuis) Check uv__strscpy() return value. */
1067   uv__strscpy(cpu_id.name, FIRST_CPU, sizeof(cpu_id.name));
1068   result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus);
1069   if (result == -1) {
1070     uv__free(ps_cpus);
1071     return UV_ENOSYS;
1072   }
1073 
1074   *cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t));
1075   if (!*cpu_infos) {
1076     uv__free(ps_cpus);
1077     return UV_ENOMEM;
1078   }
1079 
1080   *count = ncpus;
1081 
1082   cpu_info = *cpu_infos;
1083   while (idx < ncpus) {
1084     cpu_info->speed = (int)(ps_total.processorHZ / 1000000);
1085     cpu_info->model = uv__strdup(ps_total.description);
1086     cpu_info->cpu_times.user = ps_cpus[idx].user;
1087     cpu_info->cpu_times.sys = ps_cpus[idx].sys;
1088     cpu_info->cpu_times.idle = ps_cpus[idx].idle;
1089     cpu_info->cpu_times.irq = ps_cpus[idx].wait;
1090     cpu_info->cpu_times.nice = 0;
1091     cpu_info++;
1092     idx++;
1093   }
1094 
1095   uv__free(ps_cpus);
1096   return 0;
1097 }
1098 
1099 
uv_interface_addresses(uv_interface_address_t ** addresses,int * count)1100 int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
1101   uv_interface_address_t* address;
1102   int sockfd, sock6fd, inet6, i, r, size = 1;
1103   struct ifconf ifc;
1104   struct ifreq *ifr, *p, flg;
1105   struct in6_ifreq if6;
1106   struct sockaddr_dl* sa_addr;
1107 
1108   ifc.ifc_req = NULL;
1109   sock6fd = -1;
1110   r = 0;
1111   *count = 0;
1112   *addresses = NULL;
1113 
1114   if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
1115     r = UV__ERR(errno);
1116     goto cleanup;
1117   }
1118 
1119   if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) {
1120     r = UV__ERR(errno);
1121     goto cleanup;
1122   }
1123 
1124   if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
1125     r = UV__ERR(errno);
1126     goto cleanup;
1127   }
1128 
1129   ifc.ifc_req = (struct ifreq*)uv__malloc(size);
1130   if (ifc.ifc_req == NULL) {
1131     r = UV_ENOMEM;
1132     goto cleanup;
1133   }
1134   ifc.ifc_len = size;
1135   if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
1136     r = UV__ERR(errno);
1137     goto cleanup;
1138   }
1139 
1140 #define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
1141 
1142   /* Count all up and running ipv4/ipv6 addresses */
1143   ifr = ifc.ifc_req;
1144   while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
1145     p = ifr;
1146     ifr = (struct ifreq*)
1147       ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
1148 
1149     if (!(p->ifr_addr.sa_family == AF_INET6 ||
1150           p->ifr_addr.sa_family == AF_INET))
1151       continue;
1152 
1153     memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
1154     if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
1155       r = UV__ERR(errno);
1156       goto cleanup;
1157     }
1158 
1159     if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
1160       continue;
1161 
1162     (*count)++;
1163   }
1164 
1165   if (*count == 0)
1166     goto cleanup;
1167 
1168   /* Alloc the return interface structs */
1169   *addresses = uv__calloc(*count, sizeof(**addresses));
1170   if (!(*addresses)) {
1171     r = UV_ENOMEM;
1172     goto cleanup;
1173   }
1174   address = *addresses;
1175 
1176   ifr = ifc.ifc_req;
1177   while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
1178     p = ifr;
1179     ifr = (struct ifreq*)
1180       ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
1181 
1182     if (!(p->ifr_addr.sa_family == AF_INET6 ||
1183           p->ifr_addr.sa_family == AF_INET))
1184       continue;
1185 
1186     inet6 = (p->ifr_addr.sa_family == AF_INET6);
1187 
1188     memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
1189     if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1)
1190       goto syserror;
1191 
1192     if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
1193       continue;
1194 
1195     /* All conditions above must match count loop */
1196 
1197     address->name = uv__strdup(p->ifr_name);
1198 
1199     if (inet6)
1200       address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
1201     else
1202       address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
1203 
1204     if (inet6) {
1205       memset(&if6, 0, sizeof(if6));
1206       r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name));
1207       if (r == UV_E2BIG)
1208         goto cleanup;
1209       r = 0;
1210       memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr));
1211       if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1)
1212         goto syserror;
1213       address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr);
1214       /* Explicitly set family as the ioctl call appears to return it as 0. */
1215       address->netmask.netmask6.sin6_family = AF_INET6;
1216     } else {
1217       if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1)
1218         goto syserror;
1219       address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
1220       /* Explicitly set family as the ioctl call appears to return it as 0. */
1221       address->netmask.netmask4.sin_family = AF_INET;
1222     }
1223 
1224     address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
1225 
1226     address++;
1227   }
1228 
1229   /* Fill in physical addresses. */
1230   ifr = ifc.ifc_req;
1231   while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
1232     p = ifr;
1233     ifr = (struct ifreq*)
1234       ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
1235 
1236     if (p->ifr_addr.sa_family != AF_LINK)
1237       continue;
1238 
1239     address = *addresses;
1240     for (i = 0; i < *count; i++) {
1241       if (strcmp(address->name, p->ifr_name) == 0) {
1242         sa_addr = (struct sockaddr_dl*) &p->ifr_addr;
1243         memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
1244       }
1245       address++;
1246     }
1247   }
1248 
1249 #undef ADDR_SIZE
1250   goto cleanup;
1251 
1252 syserror:
1253   uv_free_interface_addresses(*addresses, *count);
1254   *addresses = NULL;
1255   *count = 0;
1256   r = UV_ENOSYS;
1257 
1258 cleanup:
1259   if (sockfd != -1)
1260     uv__close(sockfd);
1261   if (sock6fd != -1)
1262     uv__close(sock6fd);
1263   uv__free(ifc.ifc_req);
1264   return r;
1265 }
1266 
1267 
uv_free_interface_addresses(uv_interface_address_t * addresses,int count)1268 void uv_free_interface_addresses(uv_interface_address_t* addresses,
1269   int count) {
1270   int i;
1271 
1272   for (i = 0; i < count; ++i) {
1273     uv__free(addresses[i].name);
1274   }
1275 
1276   uv__free(addresses);
1277 }
1278 
1279 
uv__platform_invalidate_fd(uv_loop_t * loop,int fd)1280 void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
1281   struct pollfd* events;
1282   uintptr_t i;
1283   uintptr_t nfds;
1284   struct poll_ctl pc;
1285 
1286   assert(loop->watchers != NULL);
1287   assert(fd >= 0);
1288 
1289   events = (struct pollfd*) loop->watchers[loop->nwatchers];
1290   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
1291 
1292   if (events != NULL)
1293     /* Invalidate events with same file descriptor */
1294     for (i = 0; i < nfds; i++)
1295       if ((int) events[i].fd == fd)
1296         events[i].fd = -1;
1297 
1298   /* Remove the file descriptor from the poll set */
1299   pc.events = 0;
1300   pc.cmd = PS_DELETE;
1301   pc.fd = fd;
1302   if(loop->backend_fd >= 0)
1303     pollset_ctl(loop->backend_fd, &pc, 1);
1304 }
1305