V8 Project
d8-posix.cc
Go to the documentation of this file.
1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/stat.h>
11 #include <sys/time.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 #include <unistd.h>
15 
16 #include "src/d8.h"
17 
18 #if !V8_OS_NACL
19 #include <sys/select.h>
20 #endif
21 
22 namespace v8 {
23 
24 
25 // If the buffer ends in the middle of a UTF-8 sequence then we return
26 // the length of the string up to but not including the incomplete UTF-8
27 // sequence. If the buffer ends with a valid UTF-8 sequence then we
28 // return the whole buffer.
29 static int LengthWithoutIncompleteUtf8(char* buffer, int len) {
30  int answer = len;
31  // 1-byte encoding.
32  static const int kUtf8SingleByteMask = 0x80;
33  static const int kUtf8SingleByteValue = 0x00;
34  // 2-byte encoding.
35  static const int kUtf8TwoByteMask = 0xe0;
36  static const int kUtf8TwoByteValue = 0xc0;
37  // 3-byte encoding.
38  static const int kUtf8ThreeByteMask = 0xf0;
39  static const int kUtf8ThreeByteValue = 0xe0;
40  // 4-byte encoding.
41  static const int kUtf8FourByteMask = 0xf8;
42  static const int kUtf8FourByteValue = 0xf0;
43  // Subsequent bytes of a multi-byte encoding.
44  static const int kMultiByteMask = 0xc0;
45  static const int kMultiByteValue = 0x80;
46  int multi_byte_bytes_seen = 0;
47  while (answer > 0) {
48  int c = buffer[answer - 1];
49  // Ends in valid single-byte sequence?
50  if ((c & kUtf8SingleByteMask) == kUtf8SingleByteValue) return answer;
51  // Ends in one or more subsequent bytes of a multi-byte value?
52  if ((c & kMultiByteMask) == kMultiByteValue) {
53  multi_byte_bytes_seen++;
54  answer--;
55  } else {
56  if ((c & kUtf8TwoByteMask) == kUtf8TwoByteValue) {
57  if (multi_byte_bytes_seen >= 1) {
58  return answer + 2;
59  }
60  return answer - 1;
61  } else if ((c & kUtf8ThreeByteMask) == kUtf8ThreeByteValue) {
62  if (multi_byte_bytes_seen >= 2) {
63  return answer + 3;
64  }
65  return answer - 1;
66  } else if ((c & kUtf8FourByteMask) == kUtf8FourByteValue) {
67  if (multi_byte_bytes_seen >= 3) {
68  return answer + 4;
69  }
70  return answer - 1;
71  } else {
72  return answer; // Malformed UTF-8.
73  }
74  }
75  }
76  return 0;
77 }
78 
79 
80 // Suspends the thread until there is data available from the child process.
81 // Returns false on timeout, true on data ready.
82 static bool WaitOnFD(int fd,
83  int read_timeout,
84  int total_timeout,
85  const struct timeval& start_time) {
86  fd_set readfds, writefds, exceptfds;
87  struct timeval timeout;
88  int gone = 0;
89  if (total_timeout != -1) {
90  struct timeval time_now;
91  gettimeofday(&time_now, NULL);
92  int seconds = time_now.tv_sec - start_time.tv_sec;
93  gone = seconds * 1000 + (time_now.tv_usec - start_time.tv_usec) / 1000;
94  if (gone >= total_timeout) return false;
95  }
96  FD_ZERO(&readfds);
97  FD_ZERO(&writefds);
98  FD_ZERO(&exceptfds);
99  FD_SET(fd, &readfds);
100  FD_SET(fd, &exceptfds);
101  if (read_timeout == -1 ||
102  (total_timeout != -1 && total_timeout - gone < read_timeout)) {
103  read_timeout = total_timeout - gone;
104  }
105  timeout.tv_usec = (read_timeout % 1000) * 1000;
106  timeout.tv_sec = read_timeout / 1000;
107 #if V8_OS_NACL
108  // PNaCL has no support for select.
109  int number_of_fds_ready = -1;
110 #else
111  int number_of_fds_ready = select(fd + 1,
112  &readfds,
113  &writefds,
114  &exceptfds,
115  read_timeout != -1 ? &timeout : NULL);
116 #endif
117  return number_of_fds_ready == 1;
118 }
119 
120 
121 // Checks whether we ran out of time on the timeout. Returns true if we ran out
122 // of time, false if we still have time.
123 static bool TimeIsOut(const struct timeval& start_time, const int& total_time) {
124  if (total_time == -1) return false;
125  struct timeval time_now;
126  gettimeofday(&time_now, NULL);
127  // Careful about overflow.
128  int seconds = time_now.tv_sec - start_time.tv_sec;
129  if (seconds > 100) {
130  if (seconds * 1000 > total_time) return true;
131  return false;
132  }
133  int useconds = time_now.tv_usec - start_time.tv_usec;
134  if (seconds * 1000000 + useconds > total_time * 1000) {
135  return true;
136  }
137  return false;
138 }
139 
140 
141 // A utility class that does a non-hanging waitpid on the child process if we
142 // bail out of the System() function early. If you don't ever do a waitpid on
143 // a subprocess then it turns into one of those annoying 'zombie processes'.
145  public:
146  explicit ZombieProtector(int pid): pid_(pid) { }
147  ~ZombieProtector() { if (pid_ != 0) waitpid(pid_, NULL, 0); }
148  void ChildIsDeadNow() { pid_ = 0; }
149  private:
150  int pid_;
151 };
152 
153 
154 // A utility class that closes a file descriptor when it goes out of scope.
156  public:
157  explicit OpenFDCloser(int fd): fd_(fd) { }
158  ~OpenFDCloser() { close(fd_); }
159  private:
160  int fd_;
161 };
162 
163 
164 // A utility class that takes the array of command arguments and puts then in an
165 // array of new[]ed UTF-8 C strings. Deallocates them again when it goes out of
166 // scope.
167 class ExecArgs {
168  public:
170  exec_args_[0] = NULL;
171  }
172  bool Init(Isolate* isolate, Handle<Value> arg0, Handle<Array> command_args) {
173  String::Utf8Value prog(arg0);
174  if (*prog == NULL) {
175  const char* message =
176  "os.system(): String conversion of program name failed";
177  isolate->ThrowException(String::NewFromUtf8(isolate, message));
178  return false;
179  }
180  int len = prog.length() + 3;
181  char* c_arg = new char[len];
182  snprintf(c_arg, len, "%s", *prog);
183  exec_args_[0] = c_arg;
184  int i = 1;
185  for (unsigned j = 0; j < command_args->Length(); i++, j++) {
186  Handle<Value> arg(command_args->Get(Integer::New(isolate, j)));
187  String::Utf8Value utf8_arg(arg);
188  if (*utf8_arg == NULL) {
189  exec_args_[i] = NULL; // Consistent state for destructor.
190  const char* message =
191  "os.system(): String conversion of argument failed.";
192  isolate->ThrowException(String::NewFromUtf8(isolate, message));
193  return false;
194  }
195  int len = utf8_arg.length() + 1;
196  char* c_arg = new char[len];
197  snprintf(c_arg, len, "%s", *utf8_arg);
198  exec_args_[i] = c_arg;
199  }
200  exec_args_[i] = NULL;
201  return true;
202  }
204  for (unsigned i = 0; i < kMaxArgs; i++) {
205  if (exec_args_[i] == NULL) {
206  return;
207  }
208  delete [] exec_args_[i];
209  exec_args_[i] = 0;
210  }
211  }
212  static const unsigned kMaxArgs = 1000;
213  char* const* arg_array() const { return exec_args_; }
214  const char* arg0() const { return exec_args_[0]; }
215 
216  private:
217  char* exec_args_[kMaxArgs + 1];
218 };
219 
220 
221 // Gets the optional timeouts from the arguments to the system() call.
223  int* read_timeout,
224  int* total_timeout) {
225  if (args.Length() > 3) {
226  if (args[3]->IsNumber()) {
227  *total_timeout = args[3]->Int32Value();
228  } else {
230  args.GetIsolate(), "system: Argument 4 must be a number"));
231  return false;
232  }
233  }
234  if (args.Length() > 2) {
235  if (args[2]->IsNumber()) {
236  *read_timeout = args[2]->Int32Value();
237  } else {
239  args.GetIsolate(), "system: Argument 3 must be a number"));
240  return false;
241  }
242  }
243  return true;
244 }
245 
246 
247 static const int kReadFD = 0;
248 static const int kWriteFD = 1;
249 
250 
251 // This is run in the child process after fork() but before exec(). It normally
252 // ends with the child process being replaced with the desired child program.
253 // It only returns if an error occurred.
254 static void ExecSubprocess(int* exec_error_fds,
255  int* stdout_fds,
256  const ExecArgs& exec_args) {
257  close(exec_error_fds[kReadFD]); // Don't need this in the child.
258  close(stdout_fds[kReadFD]); // Don't need this in the child.
259  close(1); // Close stdout.
260  dup2(stdout_fds[kWriteFD], 1); // Dup pipe fd to stdout.
261  close(stdout_fds[kWriteFD]); // Don't need the original fd now.
262  fcntl(exec_error_fds[kWriteFD], F_SETFD, FD_CLOEXEC);
263  execvp(exec_args.arg0(), exec_args.arg_array());
264  // Only get here if the exec failed. Write errno to the parent to tell
265  // them it went wrong. If it went well the pipe is closed.
266  int err = errno;
267  int bytes_written;
268  do {
269  bytes_written = write(exec_error_fds[kWriteFD], &err, sizeof(err));
270  } while (bytes_written == -1 && errno == EINTR);
271  // Return (and exit child process).
272 }
273 
274 
275 // Runs in the parent process. Checks that the child was able to exec (closing
276 // the file desriptor), or reports an error if it failed.
277 static bool ChildLaunchedOK(Isolate* isolate, int* exec_error_fds) {
278  int bytes_read;
279  int err;
280  do {
281  bytes_read = read(exec_error_fds[kReadFD], &err, sizeof(err));
282  } while (bytes_read == -1 && errno == EINTR);
283  if (bytes_read != 0) {
284  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(err)));
285  return false;
286  }
287  return true;
288 }
289 
290 
291 // Accumulates the output from the child in a string handle. Returns true if it
292 // succeeded or false if an exception was thrown.
294  int child_fd,
295  const struct timeval& start_time,
296  int read_timeout,
297  int total_timeout) {
298  Handle<String> accumulator = String::Empty(isolate);
299 
300  int fullness = 0;
301  static const int kStdoutReadBufferSize = 4096;
302  char buffer[kStdoutReadBufferSize];
303 
304  if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
305  return isolate->ThrowException(
306  String::NewFromUtf8(isolate, strerror(errno)));
307  }
308 
309  int bytes_read;
310  do {
311  bytes_read = read(child_fd,
312  buffer + fullness,
313  kStdoutReadBufferSize - fullness);
314  if (bytes_read == -1) {
315  if (errno == EAGAIN) {
316  if (!WaitOnFD(child_fd,
317  read_timeout,
318  total_timeout,
319  start_time) ||
320  (TimeIsOut(start_time, total_timeout))) {
321  return isolate->ThrowException(
322  String::NewFromUtf8(isolate, "Timed out waiting for output"));
323  }
324  continue;
325  } else if (errno == EINTR) {
326  continue;
327  } else {
328  break;
329  }
330  }
331  if (bytes_read + fullness > 0) {
332  int length = bytes_read == 0 ?
333  bytes_read + fullness :
334  LengthWithoutIncompleteUtf8(buffer, bytes_read + fullness);
335  Handle<String> addition =
336  String::NewFromUtf8(isolate, buffer, String::kNormalString, length);
337  accumulator = String::Concat(accumulator, addition);
338  fullness = bytes_read + fullness - length;
339  memcpy(buffer, buffer + length, fullness);
340  }
341  } while (bytes_read != 0);
342  return accumulator;
343 }
344 
345 
346 // Modern Linux has the waitid call, which is like waitpid, but more useful
347 // if you want a timeout. If we don't have waitid we can't limit the time
348 // waiting for the process to exit without losing the information about
349 // whether it exited normally. In the common case this doesn't matter because
350 // we don't get here before the child has closed stdout and most programs don't
351 // do that before they exit.
352 //
353 // We're disabling usage of waitid in Mac OS X because it doens't work for us:
354 // a parent process hangs on waiting while a child process is already a zombie.
355 // See http://code.google.com/p/v8/issues/detail?id=401.
356 #if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__) \
357  && !defined(__NetBSD__)
358 #if !defined(__FreeBSD__)
359 #define HAS_WAITID 1
360 #endif
361 #endif
362 
363 
364 // Get exit status of child.
365 static bool WaitForChild(Isolate* isolate,
366  int pid,
367  ZombieProtector& child_waiter, // NOLINT
368  const struct timeval& start_time,
369  int read_timeout,
370  int total_timeout) {
371 #ifdef HAS_WAITID
372 
373  siginfo_t child_info;
374  child_info.si_pid = 0;
375  int useconds = 1;
376  // Wait for child to exit.
377  while (child_info.si_pid == 0) {
378  waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
379  usleep(useconds);
380  if (useconds < 1000000) useconds <<= 1;
381  if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
382  (TimeIsOut(start_time, total_timeout))) {
384  isolate, "Timed out waiting for process to terminate"));
385  kill(pid, SIGINT);
386  return false;
387  }
388  }
389  if (child_info.si_code == CLD_KILLED) {
390  char message[999];
391  snprintf(message,
392  sizeof(message),
393  "Child killed by signal %d",
394  child_info.si_status);
395  isolate->ThrowException(String::NewFromUtf8(isolate, message));
396  return false;
397  }
398  if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
399  char message[999];
400  snprintf(message,
401  sizeof(message),
402  "Child exited with status %d",
403  child_info.si_status);
404  isolate->ThrowException(String::NewFromUtf8(isolate, message));
405  return false;
406  }
407 
408 #else // No waitid call.
409 
410  int child_status;
411  waitpid(pid, &child_status, 0); // We hang here if the child doesn't exit.
412  child_waiter.ChildIsDeadNow();
413  if (WIFSIGNALED(child_status)) {
414  char message[999];
415  snprintf(message,
416  sizeof(message),
417  "Child killed by signal %d",
418  WTERMSIG(child_status));
419  isolate->ThrowException(String::NewFromUtf8(isolate, message));
420  return false;
421  }
422  if (WEXITSTATUS(child_status) != 0) {
423  char message[999];
424  int exit_status = WEXITSTATUS(child_status);
425  snprintf(message,
426  sizeof(message),
427  "Child exited with status %d",
428  exit_status);
429  isolate->ThrowException(String::NewFromUtf8(isolate, message));
430  return false;
431  }
432 
433 #endif // No waitid call.
434 
435  return true;
436 }
437 
438 
439 // Implementation of the system() function (see d8.h for details).
441  HandleScope scope(args.GetIsolate());
442  int read_timeout = -1;
443  int total_timeout = -1;
444  if (!GetTimeouts(args, &read_timeout, &total_timeout)) return;
445  Handle<Array> command_args;
446  if (args.Length() > 1) {
447  if (!args[1]->IsArray()) {
449  args.GetIsolate(), "system: Argument 2 must be an array"));
450  return;
451  }
452  command_args = Handle<Array>::Cast(args[1]);
453  } else {
454  command_args = Array::New(args.GetIsolate(), 0);
455  }
456  if (command_args->Length() > ExecArgs::kMaxArgs) {
458  args.GetIsolate(), "Too many arguments to system()"));
459  return;
460  }
461  if (args.Length() < 1) {
463  args.GetIsolate(), "Too few arguments to system()"));
464  return;
465  }
466 
467  struct timeval start_time;
468  gettimeofday(&start_time, NULL);
469 
470  ExecArgs exec_args;
471  if (!exec_args.Init(args.GetIsolate(), args[0], command_args)) {
472  return;
473  }
474  int exec_error_fds[2];
475  int stdout_fds[2];
476 
477  if (pipe(exec_error_fds) != 0) {
478  args.GetIsolate()->ThrowException(
479  String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed."));
480  return;
481  }
482  if (pipe(stdout_fds) != 0) {
483  args.GetIsolate()->ThrowException(
484  String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed."));
485  return;
486  }
487 
488  pid_t pid = fork();
489  if (pid == 0) { // Child process.
490  ExecSubprocess(exec_error_fds, stdout_fds, exec_args);
491  exit(1);
492  }
493 
494  // Parent process. Ensure that we clean up if we exit this function early.
495  ZombieProtector child_waiter(pid);
496  close(exec_error_fds[kWriteFD]);
497  close(stdout_fds[kWriteFD]);
498  OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
499  OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]);
500 
501  if (!ChildLaunchedOK(args.GetIsolate(), exec_error_fds)) return;
502 
503  Handle<Value> accumulator = GetStdout(args.GetIsolate(),
504  stdout_fds[kReadFD],
505  start_time,
506  read_timeout,
507  total_timeout);
508  if (accumulator->IsUndefined()) {
509  kill(pid, SIGINT); // On timeout, kill the subprocess.
510  args.GetReturnValue().Set(accumulator);
511  return;
512  }
513 
514  if (!WaitForChild(args.GetIsolate(),
515  pid,
516  child_waiter,
517  start_time,
518  read_timeout,
519  total_timeout)) {
520  return;
521  }
522 
523  args.GetReturnValue().Set(accumulator);
524 }
525 
526 
528  if (args.Length() != 1) {
529  const char* message = "chdir() takes one argument";
530  args.GetIsolate()->ThrowException(
531  String::NewFromUtf8(args.GetIsolate(), message));
532  return;
533  }
534  String::Utf8Value directory(args[0]);
535  if (*directory == NULL) {
536  const char* message = "os.chdir(): String conversion of argument failed.";
537  args.GetIsolate()->ThrowException(
538  String::NewFromUtf8(args.GetIsolate(), message));
539  return;
540  }
541  if (chdir(*directory) != 0) {
542  args.GetIsolate()->ThrowException(
543  String::NewFromUtf8(args.GetIsolate(), strerror(errno)));
544  return;
545  }
546 }
547 
548 
550  if (args.Length() != 1) {
551  const char* message = "umask() takes one argument";
552  args.GetIsolate()->ThrowException(
553  String::NewFromUtf8(args.GetIsolate(), message));
554  return;
555  }
556  if (args[0]->IsNumber()) {
557 #if V8_OS_NACL
558  // PNaCL has no support for umask.
559  int previous = 0;
560 #else
561  int previous = umask(args[0]->Int32Value());
562 #endif
563  args.GetReturnValue().Set(previous);
564  return;
565  } else {
566  const char* message = "umask() argument must be numeric";
567  args.GetIsolate()->ThrowException(
568  String::NewFromUtf8(args.GetIsolate(), message));
569  return;
570  }
571 }
572 
573 
574 static bool CheckItsADirectory(Isolate* isolate, char* directory) {
575  struct stat stat_buf;
576  int stat_result = stat(directory, &stat_buf);
577  if (stat_result != 0) {
578  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
579  return false;
580  }
581  if ((stat_buf.st_mode & S_IFDIR) != 0) return true;
582  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(EEXIST)));
583  return false;
584 }
585 
586 
587 // Returns true for success. Creates intermediate directories as needed. No
588 // error if the directory exists already.
589 static bool mkdirp(Isolate* isolate, char* directory, mode_t mask) {
590  int result = mkdir(directory, mask);
591  if (result == 0) return true;
592  if (errno == EEXIST) {
593  return CheckItsADirectory(isolate, directory);
594  } else if (errno == ENOENT) { // Intermediate path element is missing.
595  char* last_slash = strrchr(directory, '/');
596  if (last_slash == NULL) {
597  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
598  return false;
599  }
600  *last_slash = 0;
601  if (!mkdirp(isolate, directory, mask)) return false;
602  *last_slash = '/';
603  result = mkdir(directory, mask);
604  if (result == 0) return true;
605  if (errno == EEXIST) {
606  return CheckItsADirectory(isolate, directory);
607  }
608  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
609  return false;
610  } else {
611  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
612  return false;
613  }
614 }
615 
616 
618  mode_t mask = 0777;
619  if (args.Length() == 2) {
620  if (args[1]->IsNumber()) {
621  mask = args[1]->Int32Value();
622  } else {
623  const char* message = "mkdirp() second argument must be numeric";
624  args.GetIsolate()->ThrowException(
625  String::NewFromUtf8(args.GetIsolate(), message));
626  return;
627  }
628  } else if (args.Length() != 1) {
629  const char* message = "mkdirp() takes one or two arguments";
630  args.GetIsolate()->ThrowException(
631  String::NewFromUtf8(args.GetIsolate(), message));
632  return;
633  }
634  String::Utf8Value directory(args[0]);
635  if (*directory == NULL) {
636  const char* message = "os.mkdirp(): String conversion of argument failed.";
637  args.GetIsolate()->ThrowException(
638  String::NewFromUtf8(args.GetIsolate(), message));
639  return;
640  }
641  mkdirp(args.GetIsolate(), *directory, mask);
642 }
643 
644 
646  if (args.Length() != 1) {
647  const char* message = "rmdir() takes one or two arguments";
648  args.GetIsolate()->ThrowException(
649  String::NewFromUtf8(args.GetIsolate(), message));
650  return;
651  }
652  String::Utf8Value directory(args[0]);
653  if (*directory == NULL) {
654  const char* message = "os.rmdir(): String conversion of argument failed.";
655  args.GetIsolate()->ThrowException(
656  String::NewFromUtf8(args.GetIsolate(), message));
657  return;
658  }
659  rmdir(*directory);
660 }
661 
662 
664  if (args.Length() != 2) {
665  const char* message = "setenv() takes two arguments";
666  args.GetIsolate()->ThrowException(
667  String::NewFromUtf8(args.GetIsolate(), message));
668  return;
669  }
670  String::Utf8Value var(args[0]);
671  String::Utf8Value value(args[1]);
672  if (*var == NULL) {
673  const char* message =
674  "os.setenv(): String conversion of variable name failed.";
675  args.GetIsolate()->ThrowException(
676  String::NewFromUtf8(args.GetIsolate(), message));
677  return;
678  }
679  if (*value == NULL) {
680  const char* message =
681  "os.setenv(): String conversion of variable contents failed.";
682  args.GetIsolate()->ThrowException(
683  String::NewFromUtf8(args.GetIsolate(), message));
684  return;
685  }
686  setenv(*var, *value, 1);
687 }
688 
689 
691  if (args.Length() != 1) {
692  const char* message = "unsetenv() takes one argument";
693  args.GetIsolate()->ThrowException(
694  String::NewFromUtf8(args.GetIsolate(), message));
695  return;
696  }
697  String::Utf8Value var(args[0]);
698  if (*var == NULL) {
699  const char* message =
700  "os.setenv(): String conversion of variable name failed.";
701  args.GetIsolate()->ThrowException(
702  String::NewFromUtf8(args.GetIsolate(), message));
703  return;
704  }
705  unsetenv(*var);
706 }
707 
708 
710  os_templ->Set(String::NewFromUtf8(isolate, "system"),
711  FunctionTemplate::New(isolate, System));
712  os_templ->Set(String::NewFromUtf8(isolate, "chdir"),
714  os_templ->Set(String::NewFromUtf8(isolate, "setenv"),
716  os_templ->Set(String::NewFromUtf8(isolate, "unsetenv"),
718  os_templ->Set(String::NewFromUtf8(isolate, "umask"),
719  FunctionTemplate::New(isolate, SetUMask));
720  os_templ->Set(String::NewFromUtf8(isolate, "mkdirp"),
722  os_templ->Set(String::NewFromUtf8(isolate, "rmdir"),
724 }
725 
726 } // namespace v8
static Local< Array > New(Isolate *isolate, int length=0)
Creates a JavaScript array with the given length.
Definition: api.cc:5805
char * exec_args_[kMaxArgs+1]
Definition: d8-posix.cc:217
static const unsigned kMaxArgs
Definition: d8-posix.cc:212
char *const * arg_array() const
Definition: d8-posix.cc:213
bool Init(Isolate *isolate, Handle< Value > arg0, Handle< Array > command_args)
Definition: d8-posix.cc:172
const char * arg0() const
Definition: d8-posix.cc:214
The argument information given to function call callbacks.
Definition: v8.h:2650
ReturnValue< T > GetReturnValue() const
Definition: v8.h:6348
Isolate * GetIsolate() const
Definition: v8.h:6342
int Length() const
Definition: v8.h:6360
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >(), int length=0)
Creates a function template.
Definition: api.cc:904
A stack-allocated class that governs a number of local handles.
Definition: v8.h:802
An object reference managed by the v8 garbage collector.
Definition: v8.h:198
static Handle< T > Cast(Handle< S > that)
Definition: v8.h:277
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition: api.cc:6281
Isolate represents an isolated instance of the V8 engine.
Definition: v8.h:4356
Local< Value > ThrowException(Local< Value > exception)
Schedules an exception to be thrown when returning to JavaScript.
Definition: api.cc:6411
OpenFDCloser(int fd)
Definition: d8-posix.cc:157
static void SetEnvironment(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:663
static void MakeDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:617
static void AddOSMethods(v8::Isolate *isolate, Handle< ObjectTemplate > os_template)
Definition: d8-posix.cc:709
static void ChangeDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:527
static void System(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:440
static void UnsetEnvironment(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:690
static void RemoveDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:645
static void SetUMask(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:549
Converts an object to a UTF-8-encoded character array.
Definition: v8.h:2048
int length() const
Definition: v8.h:2054
@ kNormalString
Definition: v8.h:1963
static Local< String > Concat(Handle< String > left, Handle< String > right)
Creates a new string by concatenating the left and the right strings passed in as parameters.
Definition: api.cc:5486
static v8::Local< v8::String > Empty(Isolate *isolate)
A zero length string.
Definition: v8.h:6469
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Allocates a new string from UTF-8 data.
Definition: api.cc:5447
ZombieProtector(int pid)
Definition: d8-posix.cc:146
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static bool CheckItsADirectory(Isolate *isolate, char *directory)
Definition: d8-posix.cc:574
static bool WaitForChild(Isolate *isolate, int pid, ZombieProtector &child_waiter, const struct timeval &start_time, int read_timeout, int total_timeout)
Definition: d8-posix.cc:365
static bool mkdirp(Isolate *isolate, char *directory, mode_t mask)
Definition: d8-posix.cc:589
static bool GetTimeouts(const v8::FunctionCallbackInfo< v8::Value > &args, int *read_timeout, int *total_timeout)
Definition: d8-posix.cc:222
static bool TimeIsOut(const struct timeval &start_time, const int &total_time)
Definition: d8-posix.cc:123
static void ExecSubprocess(int *exec_error_fds, int *stdout_fds, const ExecArgs &exec_args)
Definition: d8-posix.cc:254
static int LengthWithoutIncompleteUtf8(char *buffer, int len)
Definition: d8-posix.cc:29
static Handle< Value > GetStdout(Isolate *isolate, int child_fd, const struct timeval &start_time, int read_timeout, int total_timeout)
Definition: d8-posix.cc:293
static bool WaitOnFD(int fd, int read_timeout, int total_timeout, const struct timeval &start_time)
Definition: d8-posix.cc:82
static const int kWriteFD
Definition: d8-posix.cc:248
static bool ChildLaunchedOK(Isolate *isolate, int *exec_error_fds)
Definition: d8-posix.cc:277
static const int kReadFD
Definition: d8-posix.cc:247