Chromium Code Reviews| Index: src/d8-posix.cc |
| =================================================================== |
| --- src/d8-posix.cc (revision 1649) |
| +++ src/d8-posix.cc (working copy) |
| @@ -29,6 +29,7 @@ |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <sys/types.h> |
| +#include <sys/stat.h> |
| #include <sys/time.h> |
| #include <time.h> |
| #include <unistd.h> |
| @@ -162,7 +163,7 @@ |
| class ZombieProtector { |
| public: |
| explicit ZombieProtector(int pid): pid_(pid) { } |
| - ~ZombieProtector() { if (pid_ != 0) waitpid(pid_, NULL, WNOHANG); } |
| + ~ZombieProtector() { if (pid_ != 0) waitpid(pid_, NULL, 0); } |
| void ChildIsDeadNow() { pid_ = 0; } |
| private: |
| int pid_; |
| @@ -394,7 +395,6 @@ |
| return false; |
| } |
| } |
| - child_waiter.ChildIsDeadNow(); |
| if (child_info.si_code == CLD_KILLED) { |
| char message[999]; |
| snprintf(message, |
| @@ -417,7 +417,6 @@ |
| #else // No waitid call. |
| int child_status; |
| - printf("waitpid"); |
| waitpid(pid, &child_status, 0); // We hang here if the child doesn't exit. |
| child_waiter.ChildIsDeadNow(); |
| if (WIFSIGNALED(child_status)) { |
| @@ -538,6 +537,103 @@ |
| } |
| +Handle<Value> Shell::SetUMask(const Arguments& args) { |
| + if (args.Length() != 1) { |
| + const char* message = "umask() takes one argument"; |
| + return ThrowException(String::New(message)); |
| + } |
| + if (args[0]->IsNumber()) { |
| + mode_t mask = args[0]->Int32Value(); |
| + int previous = umask(mask); |
| + return Number::New(previous); |
| + } else { |
| + const char* message = "umask() argument must be numeric"; |
| + return ThrowException(String::New(message)); |
| + } |
| +} |
| + |
| + |
| +static bool CheckItsADirectory(char* directory) { |
| + struct stat stat_buf; |
| + int stat_result = stat(directory, &stat_buf); |
| + if (stat_result != 0) { |
| + ThrowException(String::New(strerror(errno))); |
| + return false; |
| + } |
| + if ((stat_buf.st_mode & S_IFDIR) != 0) return true; |
| + ThrowException(String::New(strerror(EEXIST))); |
| + return false; |
| +} |
| + |
| + |
| +// Returns true for success. Creates intermediate directories as needed. No |
| +// error if the directory exists already. |
| +static bool mkdirp(char* directory, mode_t mask) { |
| + int result = mkdir(directory, mask); |
| + if (result == 0) return true; |
| + if (errno == EEXIST) { |
| + return CheckItsADirectory(directory); |
| + } else if (errno == ENOENT) { // Intermediate path element is missing. |
| + char* last_slash = strrchr(directory, '/'); |
| + if (last_slash == NULL) { |
| + ThrowException(String::New(strerror(errno))); |
| + return false; |
| + } |
| + *last_slash = 0; |
| + if (!mkdirp(directory, mask)) return false; |
| + *last_slash = '/'; |
| + result = mkdir(directory, mask); |
| + if (result == 0) return true; |
| + 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
|
| + return CheckItsADirectory(directory); |
| + } |
| + ThrowException(String::New(strerror(errno))); |
| + return false; |
| + } else { |
| + ThrowException(String::New(strerror(errno))); |
| + return false; |
| + } |
| +} |
| + |
| + |
| +Handle<Value> Shell::MakeDirectory(const Arguments& args) { |
| + mode_t mask = 0777; |
| + if (args.Length() == 2) { |
| + if (args[1]->IsNumber()) { |
| + mask = args[1]->Int32Value(); |
| + } else { |
| + const char* message = "mkdirp() second argument must be numeric"; |
| + return ThrowException(String::New(message)); |
| + } |
| + } else if (args.Length() != 1) { |
| + const char* message = "mkdirp() takes one or two arguments"; |
| + return ThrowException(String::New(message)); |
| + } |
| + String::Utf8Value directory(args[0]); |
| + if (*directory == NULL) { |
| + const char* message = "os.mkdirp(): String conversion of argument failed."; |
| + return ThrowException(String::New(message)); |
| + } |
| + mkdirp(*directory, mask); |
| + return v8::Undefined(); |
| +} |
| + |
| + |
| +Handle<Value> Shell::RemoveDirectory(const Arguments& args) { |
| + if (args.Length() != 1) { |
| + const char* message = "rmdir() takes one or two arguments"; |
| + return ThrowException(String::New(message)); |
| + } |
| + String::Utf8Value directory(args[0]); |
| + if (*directory == NULL) { |
| + const char* message = "os.rmdir(): String conversion of argument failed."; |
| + return ThrowException(String::New(message)); |
| + } |
| + rmdir(*directory); |
| + return v8::Undefined(); |
| +} |
| + |
| + |
| Handle<Value> Shell::SetEnvironment(const Arguments& args) { |
| if (args.Length() != 2) { |
| const char* message = "setenv() takes two arguments"; |
| @@ -560,4 +656,13 @@ |
| } |
| +void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) { |
| + os_templ->Set(String::New("system"), FunctionTemplate::New(System)); |
| + os_templ->Set(String::New("chdir"), FunctionTemplate::New(ChangeDirectory)); |
| + os_templ->Set(String::New("setenv"), FunctionTemplate::New(SetEnvironment)); |
| + os_templ->Set(String::New("umask"), FunctionTemplate::New(SetUMask)); |
| + os_templ->Set(String::New("mkdirp"), FunctionTemplate::New(MakeDirectory)); |
| + os_templ->Set(String::New("rmdir"), FunctionTemplate::New(RemoveDirectory)); |
| +} |
| + |
| } // namespace v8 |