lib/util: Make sys_rw available to CTDB
[sfrench/samba-autobuild/.git] / lib / util / server_id.c
index 4a844330ef394675073cb7296263f85e0c825ec5..77c5ee1c09781f86a7b26e3b1aa88bd88d2e7a1a 100644 (file)
 #include "includes.h"
 #include "librpc/gen_ndr/server_id.h"
 
+bool server_id_same_process(const struct server_id *p1,
+                           const struct server_id *p2)
+{
+       return ((p1->pid == p2->pid) && (p1->vnn == p2->vnn));
+}
+
 bool server_id_equal(const struct server_id *p1, const struct server_id *p2)
 {
-       if (p1->pid != p2->pid) {
+       if (!server_id_same_process(p1, p2)) {
                return false;
        }
 
@@ -30,10 +36,6 @@ bool server_id_equal(const struct server_id *p1, const struct server_id *p2)
                return false;
        }
 
-       if (p1->vnn != p2->vnn) {
-               return false;
-       }
-
        if (p1->unique_id != p2->unique_id) {
                return false;
        }
@@ -63,69 +65,110 @@ char *server_id_str_buf(struct server_id id, struct server_id_buf *dst)
        return dst->buf;
 }
 
-char *server_id_str(TALLOC_CTX *mem_ctx, const struct server_id *id)
+size_t server_id_str_buf_unique(struct server_id id, char *buf, size_t buflen)
 {
-       if (server_id_is_disconnected(id)) {
-               return talloc_strdup(mem_ctx, "disconnected");
-       } else if (id->vnn == NONCLUSTER_VNN && id->task_id == 0) {
-               return talloc_asprintf(mem_ctx,
-                                      "%llu",
-                                      (unsigned long long)id->pid);
-       } else if (id->vnn == NONCLUSTER_VNN) {
-               return talloc_asprintf(mem_ctx,
-                                      "%llu.%u",
-                                      (unsigned long long)id->pid,
-                                      (unsigned)id->task_id);
-       } else if (id->task_id == 0) {
-               return talloc_asprintf(mem_ctx,
-                                      "%u:%llu",
-                                      (unsigned)id->vnn,
-                                      (unsigned long long)id->pid);
-       } else {
-               return talloc_asprintf(mem_ctx,
-                                      "%u:%llu.%u",
-                                      (unsigned)id->vnn,
-                                      (unsigned long long)id->pid,
-                                      (unsigned)id->task_id);
+       struct server_id_buf idbuf;
+       char unique_buf[21];    /* 2^64 is 18446744073709551616, 20 chars */
+       size_t idlen, unique_len, needed;
+
+       server_id_str_buf(id, &idbuf);
+
+       idlen = strlen(idbuf.buf);
+       unique_len = snprintf(unique_buf, sizeof(unique_buf), "%"PRIu64,
+                             id.unique_id);
+       needed = idlen + unique_len + 2;
+
+       if (buflen >= needed) {
+               memcpy(buf, idbuf.buf, idlen);
+               buf[idlen] = '/';
+               memcpy(buf + idlen + 1, unique_buf, unique_len+1);
        }
+
+       return needed;
 }
 
 struct server_id server_id_from_string(uint32_t local_vnn,
                                       const char *pid_string)
 {
+       struct server_id templ = {
+               .vnn = NONCLUSTER_VNN, .pid = UINT64_MAX
+       };
        struct server_id result;
-       unsigned long long pid;
-       unsigned int vnn, task_id = 0;
-
-       ZERO_STRUCT(result);
+       int ret;
 
        /*
         * We accept various forms with 1, 2 or 3 component forms
-        * because the server_id_str() can print different forms, and
+        * because the server_id_str_buf() can print different forms, and
         * we want backwards compatibility for scripts that may call
         * smbclient.
         */
-       if (sscanf(pid_string, "%u:%llu.%u", &vnn, &pid, &task_id) == 3) {
-               result.vnn = vnn;
-               result.pid = pid;
-               result.task_id = task_id;
-       } else if (sscanf(pid_string, "%u:%llu", &vnn, &pid) == 2) {
-               result.vnn = vnn;
-               result.pid = pid;
-       } else if (sscanf(pid_string, "%llu.%u", &pid, &task_id) == 2) {
+
+       result = templ;
+       ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32"/%"SCNu64,
+                    &result.vnn, &result.pid, &result.task_id,
+                    &result.unique_id);
+       if (ret == 4) {
+               return result;
+       }
+
+       result = templ;
+       ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32,
+                    &result.vnn, &result.pid, &result.task_id);
+       if (ret == 3) {
+               return result;
+       }
+
+       result = templ;
+       ret = sscanf(pid_string, "%"SCNu32":%"SCNu64"/%"SCNu64,
+                    &result.vnn, &result.pid, &result.unique_id);
+       if (ret == 3) {
+               return result;
+       }
+
+       result = templ;
+       ret = sscanf(pid_string, "%"SCNu32":%"SCNu64,
+                    &result.vnn, &result.pid);
+       if (ret == 2) {
+               return result;
+       }
+
+       result = templ;
+       ret = sscanf(pid_string, "%"SCNu64".%"SCNu32"/%"SCNu64,
+                    &result.pid, &result.task_id, &result.unique_id);
+       if (ret == 3) {
+               result.vnn = local_vnn;
+               return result;
+       }
+
+       result = templ;
+       ret = sscanf(pid_string, "%"SCNu64".%"SCNu32,
+                    &result.pid, &result.task_id);
+       if (ret == 2) {
+               result.vnn = local_vnn;
+               return result;
+       }
+
+       result = templ;
+       ret = sscanf(pid_string, "%"SCNu64"/%"SCNu64,
+                    &result.pid, &result.unique_id);
+       if (ret == 2) {
                result.vnn = local_vnn;
-               result.pid = pid;
-               result.task_id = task_id;
-       } else if (sscanf(pid_string, "%llu", &pid) == 1) {
+               return result;
+       }
+
+       result = templ;
+       ret = sscanf(pid_string, "%"SCNu64, &result.pid);
+       if (ret == 1) {
                result.vnn = local_vnn;
-               result.pid = pid;
-       } else if (strcmp(pid_string, "disconnected") ==0) {
+               return result;
+       }
+
+       if (strcmp(pid_string, "disconnected") == 0) {
                server_id_set_disconnected(&result);
-       } else {
-               result.vnn = NONCLUSTER_VNN;
-               result.pid = UINT64_MAX;
+               return result;
        }
-       return result;
+
+       return templ;
 }
 
 /**
@@ -158,3 +201,21 @@ bool server_id_is_disconnected(const struct server_id *id)
 
        return server_id_equal(id, &dis);
 }
+
+void server_id_put(uint8_t buf[SERVER_ID_BUF_LENGTH],
+                  const struct server_id id)
+{
+       SBVAL(buf, 0,  id.pid);
+       SIVAL(buf, 8,  id.task_id);
+       SIVAL(buf, 12, id.vnn);
+       SBVAL(buf, 16, id.unique_id);
+}
+
+void server_id_get(struct server_id *id,
+                  const uint8_t buf[SERVER_ID_BUF_LENGTH])
+{
+       id->pid       = BVAL(buf, 0);
+       id->task_id   = IVAL(buf, 8);
+       id->vnn       = IVAL(buf, 12);
+       id->unique_id = BVAL(buf, 16);
+}