modules/jdk.packager/src/main/native/library/common/PosixPlatform.cpp

Print this page

        

@@ -42,19 +42,113 @@
 #include <assert.h>
 #include <stdbool.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/sysctl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
 #include <iostream>
 #include <dlfcn.h>
 #include <signal.h>
 
 
 PosixPlatform::PosixPlatform(void) {
 }
 
 PosixPlatform::~PosixPlatform(void) {
+    if (!SingleInstanceFile.empty()) {
+        unlink(SingleInstanceFile.c_str());
+    }
+}
+
+bool PosixPlatform::mkdirs(const char* path) {
+    char* p = NULL;
+    char tmp_path[PATH_MAX] = {0};
+
+    if (strlen(path) > (sizeof(tmp_path) - 1)) {
+        // too long name
+        return false;
+    }
+
+    strcpy(tmp_path, path);
+
+    errno = 0;
+    for (p = tmp_path + 1; *p; ++p) {
+        if (*p == '/') {
+            *p = '\0';
+            if (mkdir(tmp_path, S_IRWXU) != 0) {
+                if (errno != EEXIST) {
+                    return false;
+                }
+            }
+            *p = '/';
+        }
+    }
+
+    if (mkdir(tmp_path, S_IRWXU) != 0) {
+        if (errno != EEXIST) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool PosixPlatform::getTmpDir(char* path, int len) {
+    struct passwd* pw = getpwuid(getuid());
+    const char* homedir = pw->pw_dir;
+    snprintf(path, len-1 , "%s%s", homedir, getTmpDirString());
+    struct stat sb;
+    if (stat(path, &sb) != 0 || !S_ISDIR(sb.st_mode)) {
+        // the dir doesn't exist
+        if (!mkdirs(path)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+// returns true if another instance is already running.
+// if false, we need to continue regular launch.
+bool PosixPlatform::CheckForSingleInstance(TString appName) {
+    char tmpDir[PATH_MAX] = {0};
+    if (!getTmpDir(tmpDir, PATH_MAX)) {
+        printf("Unable to check for single instance.\n");
+        return false;
+    }
+
+    char lock_file[PATH_MAX] = {0};
+    snprintf(lock_file, PATH_MAX-1, "%s/%s", tmpDir, appName.c_str());
+    SingleInstanceFile = lock_file;
+    int pid_file = open(lock_file, O_CREAT | O_RDWR, 0666);
+    int rc = flock(pid_file, LOCK_EX | LOCK_NB);
+
+    if (rc) {
+        if (EWOULDBLOCK == errno) {
+            // another instance is running
+            pid_t pid = 0;
+            read(pid_file, (void*)&pid, sizeof(pid_t));
+            printf("Another instance is running PID: %d\n", pid);
+            if (pid != 0) {
+                singleInstanceProcessId = pid;
+                SingleInstanceFile.clear();
+                return true;
+            }
+        } else {
+            printf("Unable to check for single instance.\n");
+        }
+    } else {
+        // It is the first instance.
+        pid_t pid = getpid();
+        write(pid_file, (void*)&pid, sizeof(pid_t));
+    }
+
+    return false;
 }
 
 MessageResponse PosixPlatform::ShowResponseMessage(TString title, TString description) {
     MessageResponse result = mrCancel;