Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(514)

Side by Side Diff: src/d8-posix.cc

Issue 1240993003: Revert of Make d8 stop using to-be-deprecated APIs (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/d8-debug.cc ('k') | src/d8-readline.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <errno.h> 5 #include <errno.h>
6 #include <fcntl.h> 6 #include <fcntl.h>
7 #include <signal.h> 7 #include <signal.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/stat.h> 10 #include <sys/stat.h>
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 163
164 164
165 // A utility class that takes the array of command arguments and puts then in an 165 // A utility class that takes the array of command arguments and puts then in an
166 // array of new[]ed UTF-8 C strings. Deallocates them again when it goes out of 166 // array of new[]ed UTF-8 C strings. Deallocates them again when it goes out of
167 // scope. 167 // scope.
168 class ExecArgs { 168 class ExecArgs {
169 public: 169 public:
170 ExecArgs() { 170 ExecArgs() {
171 exec_args_[0] = NULL; 171 exec_args_[0] = NULL;
172 } 172 }
173 bool Init(Isolate* isolate, Local<Value> arg0, Local<Array> command_args) { 173 bool Init(Isolate* isolate, Handle<Value> arg0, Handle<Array> command_args) {
174 String::Utf8Value prog(arg0); 174 String::Utf8Value prog(arg0);
175 if (*prog == NULL) { 175 if (*prog == NULL) {
176 const char* message = 176 const char* message =
177 "os.system(): String conversion of program name failed"; 177 "os.system(): String conversion of program name failed";
178 isolate->ThrowException( 178 isolate->ThrowException(String::NewFromUtf8(isolate, message));
179 String::NewFromUtf8(isolate, message, NewStringType::kNormal)
180 .ToLocalChecked());
181 return false; 179 return false;
182 } 180 }
183 int len = prog.length() + 3; 181 int len = prog.length() + 3;
184 char* c_arg = new char[len]; 182 char* c_arg = new char[len];
185 snprintf(c_arg, len, "%s", *prog); 183 snprintf(c_arg, len, "%s", *prog);
186 exec_args_[0] = c_arg; 184 exec_args_[0] = c_arg;
187 int i = 1; 185 int i = 1;
188 for (unsigned j = 0; j < command_args->Length(); i++, j++) { 186 for (unsigned j = 0; j < command_args->Length(); i++, j++) {
189 Local<Value> arg( 187 Handle<Value> arg(command_args->Get(Integer::New(isolate, j)));
190 command_args->Get(isolate->GetCurrentContext(),
191 Integer::New(isolate, j)).ToLocalChecked());
192 String::Utf8Value utf8_arg(arg); 188 String::Utf8Value utf8_arg(arg);
193 if (*utf8_arg == NULL) { 189 if (*utf8_arg == NULL) {
194 exec_args_[i] = NULL; // Consistent state for destructor. 190 exec_args_[i] = NULL; // Consistent state for destructor.
195 const char* message = 191 const char* message =
196 "os.system(): String conversion of argument failed."; 192 "os.system(): String conversion of argument failed.";
197 isolate->ThrowException( 193 isolate->ThrowException(String::NewFromUtf8(isolate, message));
198 String::NewFromUtf8(isolate, message, NewStringType::kNormal)
199 .ToLocalChecked());
200 return false; 194 return false;
201 } 195 }
202 int len = utf8_arg.length() + 1; 196 int len = utf8_arg.length() + 1;
203 char* c_arg = new char[len]; 197 char* c_arg = new char[len];
204 snprintf(c_arg, len, "%s", *utf8_arg); 198 snprintf(c_arg, len, "%s", *utf8_arg);
205 exec_args_[i] = c_arg; 199 exec_args_[i] = c_arg;
206 } 200 }
207 exec_args_[i] = NULL; 201 exec_args_[i] = NULL;
208 return true; 202 return true;
209 } 203 }
(...skipping 14 matching lines...) Expand all
224 char* exec_args_[kMaxArgs + 1]; 218 char* exec_args_[kMaxArgs + 1];
225 }; 219 };
226 220
227 221
228 // Gets the optional timeouts from the arguments to the system() call. 222 // Gets the optional timeouts from the arguments to the system() call.
229 static bool GetTimeouts(const v8::FunctionCallbackInfo<v8::Value>& args, 223 static bool GetTimeouts(const v8::FunctionCallbackInfo<v8::Value>& args,
230 int* read_timeout, 224 int* read_timeout,
231 int* total_timeout) { 225 int* total_timeout) {
232 if (args.Length() > 3) { 226 if (args.Length() > 3) {
233 if (args[3]->IsNumber()) { 227 if (args[3]->IsNumber()) {
234 *total_timeout = args[3] 228 *total_timeout = args[3]->Int32Value();
235 ->Int32Value(args.GetIsolate()->GetCurrentContext())
236 .FromJust();
237 } else { 229 } else {
238 args.GetIsolate()->ThrowException( 230 args.GetIsolate()->ThrowException(String::NewFromUtf8(
239 String::NewFromUtf8(args.GetIsolate(), 231 args.GetIsolate(), "system: Argument 4 must be a number"));
240 "system: Argument 4 must be a number",
241 NewStringType::kNormal).ToLocalChecked());
242 return false; 232 return false;
243 } 233 }
244 } 234 }
245 if (args.Length() > 2) { 235 if (args.Length() > 2) {
246 if (args[2]->IsNumber()) { 236 if (args[2]->IsNumber()) {
247 *read_timeout = args[2] 237 *read_timeout = args[2]->Int32Value();
248 ->Int32Value(args.GetIsolate()->GetCurrentContext())
249 .FromJust();
250 } else { 238 } else {
251 args.GetIsolate()->ThrowException( 239 args.GetIsolate()->ThrowException(String::NewFromUtf8(
252 String::NewFromUtf8(args.GetIsolate(), 240 args.GetIsolate(), "system: Argument 3 must be a number"));
253 "system: Argument 3 must be a number",
254 NewStringType::kNormal).ToLocalChecked());
255 return false; 241 return false;
256 } 242 }
257 } 243 }
258 return true; 244 return true;
259 } 245 }
260 246
261 247
262 static const int kReadFD = 0; 248 static const int kReadFD = 0;
263 static const int kWriteFD = 1; 249 static const int kWriteFD = 1;
264 250
(...skipping 24 matching lines...) Expand all
289 275
290 // Runs in the parent process. Checks that the child was able to exec (closing 276 // Runs in the parent process. Checks that the child was able to exec (closing
291 // the file desriptor), or reports an error if it failed. 277 // the file desriptor), or reports an error if it failed.
292 static bool ChildLaunchedOK(Isolate* isolate, int* exec_error_fds) { 278 static bool ChildLaunchedOK(Isolate* isolate, int* exec_error_fds) {
293 ssize_t bytes_read; 279 ssize_t bytes_read;
294 int err; 280 int err;
295 do { 281 do {
296 bytes_read = read(exec_error_fds[kReadFD], &err, sizeof(err)); 282 bytes_read = read(exec_error_fds[kReadFD], &err, sizeof(err));
297 } while (bytes_read == -1 && errno == EINTR); 283 } while (bytes_read == -1 && errno == EINTR);
298 if (bytes_read != 0) { 284 if (bytes_read != 0) {
299 isolate->ThrowException( 285 isolate->ThrowException(String::NewFromUtf8(isolate, strerror(err)));
300 String::NewFromUtf8(isolate, strerror(err), NewStringType::kNormal)
301 .ToLocalChecked());
302 return false; 286 return false;
303 } 287 }
304 return true; 288 return true;
305 } 289 }
306 290
307 291
308 // Accumulates the output from the child in a string handle. Returns true if it 292 // Accumulates the output from the child in a string handle. Returns true if it
309 // succeeded or false if an exception was thrown. 293 // succeeded or false if an exception was thrown.
310 static Local<Value> GetStdout(Isolate* isolate, int child_fd, 294 static Handle<Value> GetStdout(Isolate* isolate,
311 const struct timeval& start_time, 295 int child_fd,
312 int read_timeout, int total_timeout) { 296 const struct timeval& start_time,
313 Local<String> accumulator = String::Empty(isolate); 297 int read_timeout,
298 int total_timeout) {
299 Handle<String> accumulator = String::Empty(isolate);
314 300
315 int fullness = 0; 301 int fullness = 0;
316 static const int kStdoutReadBufferSize = 4096; 302 static const int kStdoutReadBufferSize = 4096;
317 char buffer[kStdoutReadBufferSize]; 303 char buffer[kStdoutReadBufferSize];
318 304
319 if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) { 305 if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
320 return isolate->ThrowException( 306 return isolate->ThrowException(
321 String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal) 307 String::NewFromUtf8(isolate, strerror(errno)));
322 .ToLocalChecked());
323 } 308 }
324 309
325 int bytes_read; 310 int bytes_read;
326 do { 311 do {
327 bytes_read = static_cast<int>( 312 bytes_read = static_cast<int>(
328 read(child_fd, buffer + fullness, kStdoutReadBufferSize - fullness)); 313 read(child_fd, buffer + fullness, kStdoutReadBufferSize - fullness));
329 if (bytes_read == -1) { 314 if (bytes_read == -1) {
330 if (errno == EAGAIN) { 315 if (errno == EAGAIN) {
331 if (!WaitOnFD(child_fd, 316 if (!WaitOnFD(child_fd,
332 read_timeout, 317 read_timeout,
333 total_timeout, 318 total_timeout,
334 start_time) || 319 start_time) ||
335 (TimeIsOut(start_time, total_timeout))) { 320 (TimeIsOut(start_time, total_timeout))) {
336 return isolate->ThrowException( 321 return isolate->ThrowException(
337 String::NewFromUtf8(isolate, "Timed out waiting for output", 322 String::NewFromUtf8(isolate, "Timed out waiting for output"));
338 NewStringType::kNormal).ToLocalChecked());
339 } 323 }
340 continue; 324 continue;
341 } else if (errno == EINTR) { 325 } else if (errno == EINTR) {
342 continue; 326 continue;
343 } else { 327 } else {
344 break; 328 break;
345 } 329 }
346 } 330 }
347 if (bytes_read + fullness > 0) { 331 if (bytes_read + fullness > 0) {
348 int length = bytes_read == 0 ? 332 int length = bytes_read == 0 ?
349 bytes_read + fullness : 333 bytes_read + fullness :
350 LengthWithoutIncompleteUtf8(buffer, bytes_read + fullness); 334 LengthWithoutIncompleteUtf8(buffer, bytes_read + fullness);
351 Local<String> addition = 335 Handle<String> addition =
352 String::NewFromUtf8(isolate, buffer, NewStringType::kNormal, length) 336 String::NewFromUtf8(isolate, buffer, String::kNormalString, length);
353 .ToLocalChecked();
354 accumulator = String::Concat(accumulator, addition); 337 accumulator = String::Concat(accumulator, addition);
355 fullness = bytes_read + fullness - length; 338 fullness = bytes_read + fullness - length;
356 memcpy(buffer, buffer + length, fullness); 339 memcpy(buffer, buffer + length, fullness);
357 } 340 }
358 } while (bytes_read != 0); 341 } while (bytes_read != 0);
359 return accumulator; 342 return accumulator;
360 } 343 }
361 344
362 345
363 // Modern Linux has the waitid call, which is like waitpid, but more useful 346 // Modern Linux has the waitid call, which is like waitpid, but more useful
(...skipping 26 matching lines...) Expand all
390 siginfo_t child_info; 373 siginfo_t child_info;
391 child_info.si_pid = 0; 374 child_info.si_pid = 0;
392 int useconds = 1; 375 int useconds = 1;
393 // Wait for child to exit. 376 // Wait for child to exit.
394 while (child_info.si_pid == 0) { 377 while (child_info.si_pid == 0) {
395 waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT); 378 waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
396 usleep(useconds); 379 usleep(useconds);
397 if (useconds < 1000000) useconds <<= 1; 380 if (useconds < 1000000) useconds <<= 1;
398 if ((read_timeout != -1 && useconds / 1000 > read_timeout) || 381 if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
399 (TimeIsOut(start_time, total_timeout))) { 382 (TimeIsOut(start_time, total_timeout))) {
400 isolate->ThrowException( 383 isolate->ThrowException(String::NewFromUtf8(
401 String::NewFromUtf8(isolate, 384 isolate, "Timed out waiting for process to terminate"));
402 "Timed out waiting for process to terminate",
403 NewStringType::kNormal).ToLocalChecked());
404 kill(pid, SIGINT); 385 kill(pid, SIGINT);
405 return false; 386 return false;
406 } 387 }
407 } 388 }
408 if (child_info.si_code == CLD_KILLED) { 389 if (child_info.si_code == CLD_KILLED) {
409 char message[999]; 390 char message[999];
410 snprintf(message, 391 snprintf(message,
411 sizeof(message), 392 sizeof(message),
412 "Child killed by signal %d", 393 "Child killed by signal %d",
413 child_info.si_status); 394 child_info.si_status);
414 isolate->ThrowException( 395 isolate->ThrowException(String::NewFromUtf8(isolate, message));
415 String::NewFromUtf8(isolate, message, NewStringType::kNormal)
416 .ToLocalChecked());
417 return false; 396 return false;
418 } 397 }
419 if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) { 398 if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
420 char message[999]; 399 char message[999];
421 snprintf(message, 400 snprintf(message,
422 sizeof(message), 401 sizeof(message),
423 "Child exited with status %d", 402 "Child exited with status %d",
424 child_info.si_status); 403 child_info.si_status);
425 isolate->ThrowException( 404 isolate->ThrowException(String::NewFromUtf8(isolate, message));
426 String::NewFromUtf8(isolate, message, NewStringType::kNormal)
427 .ToLocalChecked());
428 return false; 405 return false;
429 } 406 }
430 407
431 #else // No waitid call. 408 #else // No waitid call.
432 409
433 int child_status; 410 int child_status;
434 waitpid(pid, &child_status, 0); // We hang here if the child doesn't exit. 411 waitpid(pid, &child_status, 0); // We hang here if the child doesn't exit.
435 child_waiter.ChildIsDeadNow(); 412 child_waiter.ChildIsDeadNow();
436 if (WIFSIGNALED(child_status)) { 413 if (WIFSIGNALED(child_status)) {
437 char message[999]; 414 char message[999];
438 snprintf(message, 415 snprintf(message,
439 sizeof(message), 416 sizeof(message),
440 "Child killed by signal %d", 417 "Child killed by signal %d",
441 WTERMSIG(child_status)); 418 WTERMSIG(child_status));
442 isolate->ThrowException( 419 isolate->ThrowException(String::NewFromUtf8(isolate, message));
443 String::NewFromUtf8(isolate, message, NewStringType::kNormal)
444 .ToLocalChecked());
445 return false; 420 return false;
446 } 421 }
447 if (WEXITSTATUS(child_status) != 0) { 422 if (WEXITSTATUS(child_status) != 0) {
448 char message[999]; 423 char message[999];
449 int exit_status = WEXITSTATUS(child_status); 424 int exit_status = WEXITSTATUS(child_status);
450 snprintf(message, 425 snprintf(message,
451 sizeof(message), 426 sizeof(message),
452 "Child exited with status %d", 427 "Child exited with status %d",
453 exit_status); 428 exit_status);
454 isolate->ThrowException( 429 isolate->ThrowException(String::NewFromUtf8(isolate, message));
455 String::NewFromUtf8(isolate, message, NewStringType::kNormal)
456 .ToLocalChecked());
457 return false; 430 return false;
458 } 431 }
459 432
460 #endif // No waitid call. 433 #endif // No waitid call.
461 434
462 return true; 435 return true;
463 } 436 }
464 437
465 438
466 // Implementation of the system() function (see d8.h for details). 439 // Implementation of the system() function (see d8.h for details).
467 void Shell::System(const v8::FunctionCallbackInfo<v8::Value>& args) { 440 void Shell::System(const v8::FunctionCallbackInfo<v8::Value>& args) {
468 HandleScope scope(args.GetIsolate()); 441 HandleScope scope(args.GetIsolate());
469 int read_timeout = -1; 442 int read_timeout = -1;
470 int total_timeout = -1; 443 int total_timeout = -1;
471 if (!GetTimeouts(args, &read_timeout, &total_timeout)) return; 444 if (!GetTimeouts(args, &read_timeout, &total_timeout)) return;
472 Local<Array> command_args; 445 Handle<Array> command_args;
473 if (args.Length() > 1) { 446 if (args.Length() > 1) {
474 if (!args[1]->IsArray()) { 447 if (!args[1]->IsArray()) {
475 args.GetIsolate()->ThrowException( 448 args.GetIsolate()->ThrowException(String::NewFromUtf8(
476 String::NewFromUtf8(args.GetIsolate(), 449 args.GetIsolate(), "system: Argument 2 must be an array"));
477 "system: Argument 2 must be an array",
478 NewStringType::kNormal).ToLocalChecked());
479 return; 450 return;
480 } 451 }
481 command_args = Local<Array>::Cast(args[1]); 452 command_args = Handle<Array>::Cast(args[1]);
482 } else { 453 } else {
483 command_args = Array::New(args.GetIsolate(), 0); 454 command_args = Array::New(args.GetIsolate(), 0);
484 } 455 }
485 if (command_args->Length() > ExecArgs::kMaxArgs) { 456 if (command_args->Length() > ExecArgs::kMaxArgs) {
486 args.GetIsolate()->ThrowException( 457 args.GetIsolate()->ThrowException(String::NewFromUtf8(
487 String::NewFromUtf8(args.GetIsolate(), "Too many arguments to system()", 458 args.GetIsolate(), "Too many arguments to system()"));
488 NewStringType::kNormal).ToLocalChecked());
489 return; 459 return;
490 } 460 }
491 if (args.Length() < 1) { 461 if (args.Length() < 1) {
492 args.GetIsolate()->ThrowException( 462 args.GetIsolate()->ThrowException(String::NewFromUtf8(
493 String::NewFromUtf8(args.GetIsolate(), "Too few arguments to system()", 463 args.GetIsolate(), "Too few arguments to system()"));
494 NewStringType::kNormal).ToLocalChecked());
495 return; 464 return;
496 } 465 }
497 466
498 struct timeval start_time; 467 struct timeval start_time;
499 gettimeofday(&start_time, NULL); 468 gettimeofday(&start_time, NULL);
500 469
501 ExecArgs exec_args; 470 ExecArgs exec_args;
502 if (!exec_args.Init(args.GetIsolate(), args[0], command_args)) { 471 if (!exec_args.Init(args.GetIsolate(), args[0], command_args)) {
503 return; 472 return;
504 } 473 }
505 int exec_error_fds[2]; 474 int exec_error_fds[2];
506 int stdout_fds[2]; 475 int stdout_fds[2];
507 476
508 if (pipe(exec_error_fds) != 0) { 477 if (pipe(exec_error_fds) != 0) {
509 args.GetIsolate()->ThrowException( 478 args.GetIsolate()->ThrowException(
510 String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed.", 479 String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed."));
511 NewStringType::kNormal).ToLocalChecked());
512 return; 480 return;
513 } 481 }
514 if (pipe(stdout_fds) != 0) { 482 if (pipe(stdout_fds) != 0) {
515 args.GetIsolate()->ThrowException( 483 args.GetIsolate()->ThrowException(
516 String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed.", 484 String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed."));
517 NewStringType::kNormal).ToLocalChecked());
518 return; 485 return;
519 } 486 }
520 487
521 pid_t pid = fork(); 488 pid_t pid = fork();
522 if (pid == 0) { // Child process. 489 if (pid == 0) { // Child process.
523 ExecSubprocess(exec_error_fds, stdout_fds, exec_args); 490 ExecSubprocess(exec_error_fds, stdout_fds, exec_args);
524 exit(1); 491 exit(1);
525 } 492 }
526 493
527 // Parent process. Ensure that we clean up if we exit this function early. 494 // Parent process. Ensure that we clean up if we exit this function early.
528 ZombieProtector child_waiter(pid); 495 ZombieProtector child_waiter(pid);
529 close(exec_error_fds[kWriteFD]); 496 close(exec_error_fds[kWriteFD]);
530 close(stdout_fds[kWriteFD]); 497 close(stdout_fds[kWriteFD]);
531 OpenFDCloser error_read_closer(exec_error_fds[kReadFD]); 498 OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
532 OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]); 499 OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]);
533 500
534 if (!ChildLaunchedOK(args.GetIsolate(), exec_error_fds)) return; 501 if (!ChildLaunchedOK(args.GetIsolate(), exec_error_fds)) return;
535 502
536 Local<Value> accumulator = GetStdout(args.GetIsolate(), stdout_fds[kReadFD], 503 Handle<Value> accumulator = GetStdout(args.GetIsolate(),
537 start_time, read_timeout, total_timeout); 504 stdout_fds[kReadFD],
505 start_time,
506 read_timeout,
507 total_timeout);
538 if (accumulator->IsUndefined()) { 508 if (accumulator->IsUndefined()) {
539 kill(pid, SIGINT); // On timeout, kill the subprocess. 509 kill(pid, SIGINT); // On timeout, kill the subprocess.
540 args.GetReturnValue().Set(accumulator); 510 args.GetReturnValue().Set(accumulator);
541 return; 511 return;
542 } 512 }
543 513
544 if (!WaitForChild(args.GetIsolate(), 514 if (!WaitForChild(args.GetIsolate(),
545 pid, 515 pid,
546 child_waiter, 516 child_waiter,
547 start_time, 517 start_time,
548 read_timeout, 518 read_timeout,
549 total_timeout)) { 519 total_timeout)) {
550 return; 520 return;
551 } 521 }
552 522
553 args.GetReturnValue().Set(accumulator); 523 args.GetReturnValue().Set(accumulator);
554 } 524 }
555 525
556 526
557 void Shell::ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { 527 void Shell::ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
558 if (args.Length() != 1) { 528 if (args.Length() != 1) {
559 const char* message = "chdir() takes one argument"; 529 const char* message = "chdir() takes one argument";
560 args.GetIsolate()->ThrowException( 530 args.GetIsolate()->ThrowException(
561 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 531 String::NewFromUtf8(args.GetIsolate(), message));
562 .ToLocalChecked());
563 return; 532 return;
564 } 533 }
565 String::Utf8Value directory(args[0]); 534 String::Utf8Value directory(args[0]);
566 if (*directory == NULL) { 535 if (*directory == NULL) {
567 const char* message = "os.chdir(): String conversion of argument failed."; 536 const char* message = "os.chdir(): String conversion of argument failed.";
568 args.GetIsolate()->ThrowException( 537 args.GetIsolate()->ThrowException(
569 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 538 String::NewFromUtf8(args.GetIsolate(), message));
570 .ToLocalChecked());
571 return; 539 return;
572 } 540 }
573 if (chdir(*directory) != 0) { 541 if (chdir(*directory) != 0) {
574 args.GetIsolate()->ThrowException( 542 args.GetIsolate()->ThrowException(
575 String::NewFromUtf8(args.GetIsolate(), strerror(errno), 543 String::NewFromUtf8(args.GetIsolate(), strerror(errno)));
576 NewStringType::kNormal).ToLocalChecked());
577 return; 544 return;
578 } 545 }
579 } 546 }
580 547
581 548
582 void Shell::SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args) { 549 void Shell::SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args) {
583 if (args.Length() != 1) { 550 if (args.Length() != 1) {
584 const char* message = "umask() takes one argument"; 551 const char* message = "umask() takes one argument";
585 args.GetIsolate()->ThrowException( 552 args.GetIsolate()->ThrowException(
586 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 553 String::NewFromUtf8(args.GetIsolate(), message));
587 .ToLocalChecked());
588 return; 554 return;
589 } 555 }
590 if (args[0]->IsNumber()) { 556 if (args[0]->IsNumber()) {
591 #if V8_OS_NACL 557 #if V8_OS_NACL
592 // PNaCL has no support for umask. 558 // PNaCL has no support for umask.
593 int previous = 0; 559 int previous = 0;
594 #else 560 #else
595 int previous = umask( 561 int previous = umask(args[0]->Int32Value());
596 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
597 #endif 562 #endif
598 args.GetReturnValue().Set(previous); 563 args.GetReturnValue().Set(previous);
599 return; 564 return;
600 } else { 565 } else {
601 const char* message = "umask() argument must be numeric"; 566 const char* message = "umask() argument must be numeric";
602 args.GetIsolate()->ThrowException( 567 args.GetIsolate()->ThrowException(
603 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 568 String::NewFromUtf8(args.GetIsolate(), message));
604 .ToLocalChecked());
605 return; 569 return;
606 } 570 }
607 } 571 }
608 572
609 573
610 static bool CheckItsADirectory(Isolate* isolate, char* directory) { 574 static bool CheckItsADirectory(Isolate* isolate, char* directory) {
611 struct stat stat_buf; 575 struct stat stat_buf;
612 int stat_result = stat(directory, &stat_buf); 576 int stat_result = stat(directory, &stat_buf);
613 if (stat_result != 0) { 577 if (stat_result != 0) {
614 isolate->ThrowException( 578 isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
615 String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
616 .ToLocalChecked());
617 return false; 579 return false;
618 } 580 }
619 if ((stat_buf.st_mode & S_IFDIR) != 0) return true; 581 if ((stat_buf.st_mode & S_IFDIR) != 0) return true;
620 isolate->ThrowException( 582 isolate->ThrowException(String::NewFromUtf8(isolate, strerror(EEXIST)));
621 String::NewFromUtf8(isolate, strerror(EEXIST), NewStringType::kNormal)
622 .ToLocalChecked());
623 return false; 583 return false;
624 } 584 }
625 585
626 586
627 // Returns true for success. Creates intermediate directories as needed. No 587 // Returns true for success. Creates intermediate directories as needed. No
628 // error if the directory exists already. 588 // error if the directory exists already.
629 static bool mkdirp(Isolate* isolate, char* directory, mode_t mask) { 589 static bool mkdirp(Isolate* isolate, char* directory, mode_t mask) {
630 int result = mkdir(directory, mask); 590 int result = mkdir(directory, mask);
631 if (result == 0) return true; 591 if (result == 0) return true;
632 if (errno == EEXIST) { 592 if (errno == EEXIST) {
633 return CheckItsADirectory(isolate, directory); 593 return CheckItsADirectory(isolate, directory);
634 } else if (errno == ENOENT) { // Intermediate path element is missing. 594 } else if (errno == ENOENT) { // Intermediate path element is missing.
635 char* last_slash = strrchr(directory, '/'); 595 char* last_slash = strrchr(directory, '/');
636 if (last_slash == NULL) { 596 if (last_slash == NULL) {
637 isolate->ThrowException( 597 isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
638 String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
639 .ToLocalChecked());
640 return false; 598 return false;
641 } 599 }
642 *last_slash = 0; 600 *last_slash = 0;
643 if (!mkdirp(isolate, directory, mask)) return false; 601 if (!mkdirp(isolate, directory, mask)) return false;
644 *last_slash = '/'; 602 *last_slash = '/';
645 result = mkdir(directory, mask); 603 result = mkdir(directory, mask);
646 if (result == 0) return true; 604 if (result == 0) return true;
647 if (errno == EEXIST) { 605 if (errno == EEXIST) {
648 return CheckItsADirectory(isolate, directory); 606 return CheckItsADirectory(isolate, directory);
649 } 607 }
650 isolate->ThrowException( 608 isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
651 String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
652 .ToLocalChecked());
653 return false; 609 return false;
654 } else { 610 } else {
655 isolate->ThrowException( 611 isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
656 String::NewFromUtf8(isolate, strerror(errno), NewStringType::kNormal)
657 .ToLocalChecked());
658 return false; 612 return false;
659 } 613 }
660 } 614 }
661 615
662 616
663 void Shell::MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { 617 void Shell::MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
664 mode_t mask = 0777; 618 mode_t mask = 0777;
665 if (args.Length() == 2) { 619 if (args.Length() == 2) {
666 if (args[1]->IsNumber()) { 620 if (args[1]->IsNumber()) {
667 mask = args[1] 621 mask = args[1]->Int32Value();
668 ->Int32Value(args.GetIsolate()->GetCurrentContext())
669 .FromJust();
670 } else { 622 } else {
671 const char* message = "mkdirp() second argument must be numeric"; 623 const char* message = "mkdirp() second argument must be numeric";
672 args.GetIsolate()->ThrowException( 624 args.GetIsolate()->ThrowException(
673 String::NewFromUtf8(args.GetIsolate(), message, 625 String::NewFromUtf8(args.GetIsolate(), message));
674 NewStringType::kNormal).ToLocalChecked());
675 return; 626 return;
676 } 627 }
677 } else if (args.Length() != 1) { 628 } else if (args.Length() != 1) {
678 const char* message = "mkdirp() takes one or two arguments"; 629 const char* message = "mkdirp() takes one or two arguments";
679 args.GetIsolate()->ThrowException( 630 args.GetIsolate()->ThrowException(
680 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 631 String::NewFromUtf8(args.GetIsolate(), message));
681 .ToLocalChecked());
682 return; 632 return;
683 } 633 }
684 String::Utf8Value directory(args[0]); 634 String::Utf8Value directory(args[0]);
685 if (*directory == NULL) { 635 if (*directory == NULL) {
686 const char* message = "os.mkdirp(): String conversion of argument failed."; 636 const char* message = "os.mkdirp(): String conversion of argument failed.";
687 args.GetIsolate()->ThrowException( 637 args.GetIsolate()->ThrowException(
688 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 638 String::NewFromUtf8(args.GetIsolate(), message));
689 .ToLocalChecked());
690 return; 639 return;
691 } 640 }
692 mkdirp(args.GetIsolate(), *directory, mask); 641 mkdirp(args.GetIsolate(), *directory, mask);
693 } 642 }
694 643
695 644
696 void Shell::RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { 645 void Shell::RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
697 if (args.Length() != 1) { 646 if (args.Length() != 1) {
698 const char* message = "rmdir() takes one or two arguments"; 647 const char* message = "rmdir() takes one or two arguments";
699 args.GetIsolate()->ThrowException( 648 args.GetIsolate()->ThrowException(
700 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 649 String::NewFromUtf8(args.GetIsolate(), message));
701 .ToLocalChecked());
702 return; 650 return;
703 } 651 }
704 String::Utf8Value directory(args[0]); 652 String::Utf8Value directory(args[0]);
705 if (*directory == NULL) { 653 if (*directory == NULL) {
706 const char* message = "os.rmdir(): String conversion of argument failed."; 654 const char* message = "os.rmdir(): String conversion of argument failed.";
707 args.GetIsolate()->ThrowException( 655 args.GetIsolate()->ThrowException(
708 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 656 String::NewFromUtf8(args.GetIsolate(), message));
709 .ToLocalChecked());
710 return; 657 return;
711 } 658 }
712 rmdir(*directory); 659 rmdir(*directory);
713 } 660 }
714 661
715 662
716 void Shell::SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) { 663 void Shell::SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) {
717 if (args.Length() != 2) { 664 if (args.Length() != 2) {
718 const char* message = "setenv() takes two arguments"; 665 const char* message = "setenv() takes two arguments";
719 args.GetIsolate()->ThrowException( 666 args.GetIsolate()->ThrowException(
720 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 667 String::NewFromUtf8(args.GetIsolate(), message));
721 .ToLocalChecked());
722 return; 668 return;
723 } 669 }
724 String::Utf8Value var(args[0]); 670 String::Utf8Value var(args[0]);
725 String::Utf8Value value(args[1]); 671 String::Utf8Value value(args[1]);
726 if (*var == NULL) { 672 if (*var == NULL) {
727 const char* message = 673 const char* message =
728 "os.setenv(): String conversion of variable name failed."; 674 "os.setenv(): String conversion of variable name failed.";
729 args.GetIsolate()->ThrowException( 675 args.GetIsolate()->ThrowException(
730 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 676 String::NewFromUtf8(args.GetIsolate(), message));
731 .ToLocalChecked());
732 return; 677 return;
733 } 678 }
734 if (*value == NULL) { 679 if (*value == NULL) {
735 const char* message = 680 const char* message =
736 "os.setenv(): String conversion of variable contents failed."; 681 "os.setenv(): String conversion of variable contents failed.";
737 args.GetIsolate()->ThrowException( 682 args.GetIsolate()->ThrowException(
738 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 683 String::NewFromUtf8(args.GetIsolate(), message));
739 .ToLocalChecked());
740 return; 684 return;
741 } 685 }
742 setenv(*var, *value, 1); 686 setenv(*var, *value, 1);
743 } 687 }
744 688
745 689
746 void Shell::UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) { 690 void Shell::UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) {
747 if (args.Length() != 1) { 691 if (args.Length() != 1) {
748 const char* message = "unsetenv() takes one argument"; 692 const char* message = "unsetenv() takes one argument";
749 args.GetIsolate()->ThrowException( 693 args.GetIsolate()->ThrowException(
750 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 694 String::NewFromUtf8(args.GetIsolate(), message));
751 .ToLocalChecked());
752 return; 695 return;
753 } 696 }
754 String::Utf8Value var(args[0]); 697 String::Utf8Value var(args[0]);
755 if (*var == NULL) { 698 if (*var == NULL) {
756 const char* message = 699 const char* message =
757 "os.setenv(): String conversion of variable name failed."; 700 "os.setenv(): String conversion of variable name failed.";
758 args.GetIsolate()->ThrowException( 701 args.GetIsolate()->ThrowException(
759 String::NewFromUtf8(args.GetIsolate(), message, NewStringType::kNormal) 702 String::NewFromUtf8(args.GetIsolate(), message));
760 .ToLocalChecked());
761 return; 703 return;
762 } 704 }
763 unsetenv(*var); 705 unsetenv(*var);
764 } 706 }
765 707
766 708
767 void Shell::AddOSMethods(Isolate* isolate, Local<ObjectTemplate> os_templ) { 709 void Shell::AddOSMethods(Isolate* isolate, Handle<ObjectTemplate> os_templ) {
768 os_templ->Set(String::NewFromUtf8(isolate, "system", NewStringType::kNormal) 710 os_templ->Set(String::NewFromUtf8(isolate, "system"),
769 .ToLocalChecked(),
770 FunctionTemplate::New(isolate, System)); 711 FunctionTemplate::New(isolate, System));
771 os_templ->Set(String::NewFromUtf8(isolate, "chdir", NewStringType::kNormal) 712 os_templ->Set(String::NewFromUtf8(isolate, "chdir"),
772 .ToLocalChecked(),
773 FunctionTemplate::New(isolate, ChangeDirectory)); 713 FunctionTemplate::New(isolate, ChangeDirectory));
774 os_templ->Set(String::NewFromUtf8(isolate, "setenv", NewStringType::kNormal) 714 os_templ->Set(String::NewFromUtf8(isolate, "setenv"),
775 .ToLocalChecked(),
776 FunctionTemplate::New(isolate, SetEnvironment)); 715 FunctionTemplate::New(isolate, SetEnvironment));
777 os_templ->Set(String::NewFromUtf8(isolate, "unsetenv", NewStringType::kNormal) 716 os_templ->Set(String::NewFromUtf8(isolate, "unsetenv"),
778 .ToLocalChecked(),
779 FunctionTemplate::New(isolate, UnsetEnvironment)); 717 FunctionTemplate::New(isolate, UnsetEnvironment));
780 os_templ->Set(String::NewFromUtf8(isolate, "umask", NewStringType::kNormal) 718 os_templ->Set(String::NewFromUtf8(isolate, "umask"),
781 .ToLocalChecked(),
782 FunctionTemplate::New(isolate, SetUMask)); 719 FunctionTemplate::New(isolate, SetUMask));
783 os_templ->Set(String::NewFromUtf8(isolate, "mkdirp", NewStringType::kNormal) 720 os_templ->Set(String::NewFromUtf8(isolate, "mkdirp"),
784 .ToLocalChecked(),
785 FunctionTemplate::New(isolate, MakeDirectory)); 721 FunctionTemplate::New(isolate, MakeDirectory));
786 os_templ->Set(String::NewFromUtf8(isolate, "rmdir", NewStringType::kNormal) 722 os_templ->Set(String::NewFromUtf8(isolate, "rmdir"),
787 .ToLocalChecked(),
788 FunctionTemplate::New(isolate, RemoveDirectory)); 723 FunctionTemplate::New(isolate, RemoveDirectory));
789 } 724 }
790 725
791 } // namespace v8 726 } // namespace v8
OLDNEW
« no previous file with comments | « src/d8-debug.cc ('k') | src/d8-readline.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698