#include "node.h" #include "platform.h" #include // for MAXPATHLEN #include // getpagesize #include namespace node { static char buf[MAXPATHLEN + 1]; static char *process_title = NULL; // Does the about the same as perror(), but for windows api functions static void _winapi_perror(const char* prefix = NULL) { DWORD errno = GetLastError(); char *errmsg; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL); // FormatMessage messages include a newline character if (prefix) { fprintf(stderr, "%s: %s", prefix, errmsg); } else { fputs(errmsg, stderr); } } char** OS::SetupArgs(int argc, char *argv[]) { return argv; } void OS::SetProcessTitle(char *title) { // We need to convert _title_ to UTF-16 first, because that's what windows uses internally. // It would be more efficient to use the UTF-16 value that we can obtain from v8, // but it's not accessible from here. // Max title length; according to the specs it should be 64K but in practice it's a little over 30000, // but who needs titles that long anyway? const int MAX_TITLE_LENGTH = 30001; int length; WCHAR *title_w; // Find out how big the buffer for the wide-char title must be length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); if (!length) { _winapi_perror("MultiByteToWideChar"); return; } // Convert to wide-char string title_w = new WCHAR[length]; length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length); if (!length) { _winapi_perror("MultiByteToWideChar"); delete title_w; return; }; // If the title must be truncated insert a \0 terminator there if (length > MAX_TITLE_LENGTH) { title_w[MAX_TITLE_LENGTH - 1] = *L"\0"; } if (!SetConsoleTitleW(title_w)) { _winapi_perror("SetConsoleTitleW"); } free(process_title); process_title = strdup(title); delete title_w; } static inline char* _getProcessTitle() { WCHAR *title_w; char *title; int length, length_w; length_w = GetConsoleTitleW(L"\0", sizeof(WCHAR)); // If length is zero, there may be an error or the title may be empty if (!length_w) { if (GetLastError()) { _winapi_perror("GetConsoleTitleW"); return NULL; } else { // The title is empty, so return empty string process_title = strdup("\0"); return process_title; } } // Room for \0 terminator length_w++; title_w = new WCHAR[length_w]; if (!GetConsoleTitleW(title_w, length_w * sizeof(WCHAR))) { _winapi_perror("GetConsoleTitleW"); delete title_w; return NULL; } // Find out what the size of the buffer is that we need length = WideCharToMultiByte(CP_UTF8, 0, title_w, length_w, NULL, 0, NULL, NULL); if (!length) { _winapi_perror("WideCharToMultiByte"); delete title_w; return NULL; } title = (char *) malloc(length); if (!title) { perror("malloc"); delete title_w; return NULL; } // Do utf16 -> utf8 conversion here if (!WideCharToMultiByte(CP_UTF8, 0, title_w, -1, title, length, NULL, NULL)) { _winapi_perror("WideCharToMultiByte"); delete title_w; free(title); return NULL; } delete title_w; return title; } const char* OS::GetProcessTitle(int *len) { // If the process_title was never read before nor explicitly set, // we must query it with getConsoleTitleW if (!process_title) { process_title = _getProcessTitle(); } if (process_title) { *len = strlen(process_title); return process_title; } else { *len = 0; return NULL; } } int OS::GetMemory(size_t *rss, size_t *vsize) { FILE *f = fopen("/proc/self/stat", "r"); if (!f) return -1; int itmp; char ctmp; size_t page_size = getpagesize(); /* PID */ if (fscanf(f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Exec file */ if (fscanf (f, "%s ", buf) == 0) goto error; /* coverity[secure_coding] */ /* State */ if (fscanf (f, "%c ", &ctmp) == 0) goto error; /* coverity[secure_coding] */ /* Parent process */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Process group */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Session id */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* TTY */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* TTY owner process group */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Flags */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Minor faults (no memory page) */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Minor faults, children */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Major faults (memory page faults) */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Major faults, children */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* utime */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* stime */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* utime, children */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* stime, children */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* jiffies remaining in current time slice */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* 'nice' value */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* jiffies until next timeout */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* jiffies until next SIGALRM */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* start time (jiffies since system boot) */ if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Virtual memory size */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ *vsize = (size_t) itmp; /* Resident set size */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ *rss = (size_t) itmp * page_size; /* rlim */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Start of text */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* End of text */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ /* Start of stack */ if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ fclose (f); return 0; error: fclose (f); return -1; } int OS::GetExecutablePath(char* buffer, size_t* size) { *size = readlink("/proc/self/exe", buffer, *size - 1); if (*size <= 0) return -1; buffer[*size] = '\0'; return 0; } } // namespace node