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

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

Issue 56107: * Add rmdir, mkdir -p and umask to d8 on Unix.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « src/d8.cc ('k') | src/d8-windows.cc » ('j') | src/d8-windows.cc » ('J')
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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 28
29 #include <stdlib.h> 29 #include <stdlib.h>
30 #include <errno.h> 30 #include <errno.h>
31 #include <sys/types.h> 31 #include <sys/types.h>
32 #include <sys/stat.h>
32 #include <sys/time.h> 33 #include <sys/time.h>
33 #include <time.h> 34 #include <time.h>
34 #include <unistd.h> 35 #include <unistd.h>
35 #include <fcntl.h> 36 #include <fcntl.h>
36 #include <sys/wait.h> 37 #include <sys/wait.h>
37 #include <signal.h> 38 #include <signal.h>
38 39
39 40
40 #include "d8.h" 41 #include "d8.h"
41 #include "d8-debug.h" 42 #include "d8-debug.h"
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 return false; 156 return false;
156 } 157 }
157 158
158 159
159 // A utility class that does a non-hanging waitpid on the child process if we 160 // A utility class that does a non-hanging waitpid on the child process if we
160 // bail out of the System() function early. If you don't ever do a waitpid on 161 // bail out of the System() function early. If you don't ever do a waitpid on
161 // a subprocess then it turns into one of those annoying 'zombie processes'. 162 // a subprocess then it turns into one of those annoying 'zombie processes'.
162 class ZombieProtector { 163 class ZombieProtector {
163 public: 164 public:
164 explicit ZombieProtector(int pid): pid_(pid) { } 165 explicit ZombieProtector(int pid): pid_(pid) { }
165 ~ZombieProtector() { if (pid_ != 0) waitpid(pid_, NULL, WNOHANG); } 166 ~ZombieProtector() { if (pid_ != 0) waitpid(pid_, NULL, 0); }
166 void ChildIsDeadNow() { pid_ = 0; } 167 void ChildIsDeadNow() { pid_ = 0; }
167 private: 168 private:
168 int pid_; 169 int pid_;
169 }; 170 };
170 171
171 172
172 // A utility class that closes a file descriptor when it goes out of scope. 173 // A utility class that closes a file descriptor when it goes out of scope.
173 class OpenFDCloser { 174 class OpenFDCloser {
174 public: 175 public:
175 explicit OpenFDCloser(int fd): fd_(fd) { } 176 explicit OpenFDCloser(int fd): fd_(fd) { }
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT); 388 waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
388 usleep(useconds); 389 usleep(useconds);
389 if (useconds < 1000000) useconds <<= 1; 390 if (useconds < 1000000) useconds <<= 1;
390 if ((read_timeout != -1 && useconds / 1000 > read_timeout) || 391 if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
391 (TimeIsOut(start_time, total_timeout))) { 392 (TimeIsOut(start_time, total_timeout))) {
392 ThrowException(String::New("Timed out waiting for process to terminate")); 393 ThrowException(String::New("Timed out waiting for process to terminate"));
393 kill(pid, SIGINT); 394 kill(pid, SIGINT);
394 return false; 395 return false;
395 } 396 }
396 } 397 }
397 child_waiter.ChildIsDeadNow();
398 if (child_info.si_code == CLD_KILLED) { 398 if (child_info.si_code == CLD_KILLED) {
399 char message[999]; 399 char message[999];
400 snprintf(message, 400 snprintf(message,
401 sizeof(message), 401 sizeof(message),
402 "Child killed by signal %d", 402 "Child killed by signal %d",
403 child_info.si_status); 403 child_info.si_status);
404 ThrowException(String::New(message)); 404 ThrowException(String::New(message));
405 return false; 405 return false;
406 } 406 }
407 if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) { 407 if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
408 char message[999]; 408 char message[999];
409 snprintf(message, 409 snprintf(message,
410 sizeof(message), 410 sizeof(message),
411 "Child exited with status %d", 411 "Child exited with status %d",
412 child_info.si_status); 412 child_info.si_status);
413 ThrowException(String::New(message)); 413 ThrowException(String::New(message));
414 return false; 414 return false;
415 } 415 }
416 416
417 #else // No waitid call. 417 #else // No waitid call.
418 418
419 int child_status; 419 int child_status;
420 printf("waitpid");
421 waitpid(pid, &child_status, 0); // We hang here if the child doesn't exit. 420 waitpid(pid, &child_status, 0); // We hang here if the child doesn't exit.
422 child_waiter.ChildIsDeadNow(); 421 child_waiter.ChildIsDeadNow();
423 if (WIFSIGNALED(child_status)) { 422 if (WIFSIGNALED(child_status)) {
424 char message[999]; 423 char message[999];
425 snprintf(message, 424 snprintf(message,
426 sizeof(message), 425 sizeof(message),
427 "Child killed by signal %d", 426 "Child killed by signal %d",
428 WTERMSIG(child_status)); 427 WTERMSIG(child_status));
429 ThrowException(String::New(message)); 428 ThrowException(String::New(message));
430 return false; 429 return false;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 const char* message = "os.chdir(): String conversion of argument failed."; 530 const char* message = "os.chdir(): String conversion of argument failed.";
532 return ThrowException(String::New(message)); 531 return ThrowException(String::New(message));
533 } 532 }
534 if (chdir(*directory) != 0) { 533 if (chdir(*directory) != 0) {
535 return ThrowException(String::New(strerror(errno))); 534 return ThrowException(String::New(strerror(errno)));
536 } 535 }
537 return v8::Undefined(); 536 return v8::Undefined();
538 } 537 }
539 538
540 539
540 Handle<Value> Shell::SetUMask(const Arguments& args) {
541 if (args.Length() != 1) {
542 const char* message = "umask() takes one argument";
543 return ThrowException(String::New(message));
544 }
545 if (args[0]->IsNumber()) {
546 mode_t mask = args[0]->Int32Value();
547 int previous = umask(mask);
548 return Number::New(previous);
549 } else {
550 const char* message = "umask() argument must be numeric";
551 return ThrowException(String::New(message));
552 }
553 }
554
555
556 static bool CheckItsADirectory(char* directory) {
557 struct stat stat_buf;
558 int stat_result = stat(directory, &stat_buf);
559 if (stat_result != 0) {
560 ThrowException(String::New(strerror(errno)));
561 return false;
562 }
563 if ((stat_buf.st_mode & S_IFDIR) != 0) return true;
564 ThrowException(String::New(strerror(EEXIST)));
565 return false;
566 }
567
568
569 // Returns true for success. Creates intermediate directories as needed. No
570 // error if the directory exists already.
571 static bool mkdirp(char* directory, mode_t mask) {
572 int result = mkdir(directory, mask);
573 if (result == 0) return true;
574 if (errno == EEXIST) {
575 return CheckItsADirectory(directory);
576 } else if (errno == ENOENT) { // Intermediate path element is missing.
577 char* last_slash = strrchr(directory, '/');
578 if (last_slash == NULL) {
579 ThrowException(String::New(strerror(errno)));
580 return false;
581 }
582 *last_slash = 0;
583 if (!mkdirp(directory, mask)) return false;
584 *last_slash = '/';
585 result = mkdir(directory, mask);
586 if (result == 0) return true;
587 if (errno == EEXIST) {
Søren Thygesen Gjesse 2009/03/31 12:28:02 Is this is to handle from paths with '..' e.g. xxx
Erik Corry 2009/03/31 12:36:31 Can I just pretend that's what I was thinking abou
588 return CheckItsADirectory(directory);
589 }
590 ThrowException(String::New(strerror(errno)));
591 return false;
592 } else {
593 ThrowException(String::New(strerror(errno)));
594 return false;
595 }
596 }
597
598
599 Handle<Value> Shell::MakeDirectory(const Arguments& args) {
600 mode_t mask = 0777;
601 if (args.Length() == 2) {
602 if (args[1]->IsNumber()) {
603 mask = args[1]->Int32Value();
604 } else {
605 const char* message = "mkdirp() second argument must be numeric";
606 return ThrowException(String::New(message));
607 }
608 } else if (args.Length() != 1) {
609 const char* message = "mkdirp() takes one or two arguments";
610 return ThrowException(String::New(message));
611 }
612 String::Utf8Value directory(args[0]);
613 if (*directory == NULL) {
614 const char* message = "os.mkdirp(): String conversion of argument failed.";
615 return ThrowException(String::New(message));
616 }
617 mkdirp(*directory, mask);
618 return v8::Undefined();
619 }
620
621
622 Handle<Value> Shell::RemoveDirectory(const Arguments& args) {
623 if (args.Length() != 1) {
624 const char* message = "rmdir() takes one or two arguments";
625 return ThrowException(String::New(message));
626 }
627 String::Utf8Value directory(args[0]);
628 if (*directory == NULL) {
629 const char* message = "os.rmdir(): String conversion of argument failed.";
630 return ThrowException(String::New(message));
631 }
632 rmdir(*directory);
633 return v8::Undefined();
634 }
635
636
541 Handle<Value> Shell::SetEnvironment(const Arguments& args) { 637 Handle<Value> Shell::SetEnvironment(const Arguments& args) {
542 if (args.Length() != 2) { 638 if (args.Length() != 2) {
543 const char* message = "setenv() takes two arguments"; 639 const char* message = "setenv() takes two arguments";
544 return ThrowException(String::New(message)); 640 return ThrowException(String::New(message));
545 } 641 }
546 String::Utf8Value var(args[0]); 642 String::Utf8Value var(args[0]);
547 String::Utf8Value value(args[1]); 643 String::Utf8Value value(args[1]);
548 if (*var == NULL) { 644 if (*var == NULL) {
549 const char* message = 645 const char* message =
550 "os.setenv(): String conversion of variable name failed."; 646 "os.setenv(): String conversion of variable name failed.";
551 return ThrowException(String::New(message)); 647 return ThrowException(String::New(message));
552 } 648 }
553 if (*value == NULL) { 649 if (*value == NULL) {
554 const char* message = 650 const char* message =
555 "os.setenv(): String conversion of variable contents failed."; 651 "os.setenv(): String conversion of variable contents failed.";
556 return ThrowException(String::New(message)); 652 return ThrowException(String::New(message));
557 } 653 }
558 setenv(*var, *value, 1); 654 setenv(*var, *value, 1);
559 return v8::Undefined(); 655 return v8::Undefined();
560 } 656 }
561 657
562 658
659 void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) {
660 os_templ->Set(String::New("system"), FunctionTemplate::New(System));
661 os_templ->Set(String::New("chdir"), FunctionTemplate::New(ChangeDirectory));
662 os_templ->Set(String::New("setenv"), FunctionTemplate::New(SetEnvironment));
663 os_templ->Set(String::New("umask"), FunctionTemplate::New(SetUMask));
664 os_templ->Set(String::New("mkdirp"), FunctionTemplate::New(MakeDirectory));
665 os_templ->Set(String::New("rmdir"), FunctionTemplate::New(RemoveDirectory));
666 }
667
563 } // namespace v8 668 } // namespace v8
OLDNEW
« no previous file with comments | « src/d8.cc ('k') | src/d8-windows.cc » ('j') | src/d8-windows.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698