libmongo-client 0.1.4
src/mongo-utils.c
Go to the documentation of this file.
00001 /* mongo-utils.c - libmongo-client utility functions
00002  * Copyright 2011 Gergely Nagy <algernon@balabit.hu>
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00021 #include <glib.h>
00022 #include <glib/gprintf.h>
00023 
00024 #include <sys/types.h>
00025 #include <string.h>
00026 #include <stdlib.h>
00027 #include <time.h>
00028 #include <unistd.h>
00029 #include <errno.h>
00030 
00031 static guint32 machine_id = 0;
00032 static gint16 pid = 0;
00033 
00034 void
00035 mongo_util_oid_init (gint32 mid)
00036 {
00037   pid_t p = getpid ();
00038 
00039   if (mid == 0)
00040     {
00041       srand (time (NULL));
00042       machine_id = rand ();
00043     }
00044   else
00045     machine_id = mid;
00046 
00047   /*
00048    * If our pid has more than 16 bits, let half the bits modulate the
00049    * machine_id.
00050    */
00051   if (sizeof (pid_t) > 2)
00052     {
00053       machine_id ^= pid >> 16;
00054     }
00055   pid = (gint16)p;
00056 }
00057 
00058 guint8 *
00059 mongo_util_oid_new_with_time (gint32 ts, gint32 seq)
00060 {
00061   guint8 *oid;
00062   time_t t = GINT32_TO_BE (ts);
00063   gint32 tmp = GINT32_TO_BE (seq);
00064 
00065   if (machine_id == 0 || pid == 0)
00066     return NULL;
00067 
00068   oid = (guint8 *)g_new0 (guint8, 12);
00069 
00070   /* Sequence number, last 3 bytes
00071    * For simplicity's sake, we put this in first, and overwrite the
00072    * first byte later.
00073    */
00074   memcpy (oid + 4 + 2 + 2, &tmp, 4);
00075   /* First four bytes: the time, BE byte order */
00076   memcpy (oid, &t, 4);
00077   /* Machine ID, byte order doesn't matter, 3 bytes */
00078   memcpy (oid + 4, &machine_id, 3);
00079   /* PID, byte order doesn't matter, 2 bytes */
00080   memcpy (oid + 4 + 3, &pid, 2);
00081 
00082   return oid;
00083 }
00084 
00085 guint8 *
00086 mongo_util_oid_new (gint32 seq)
00087 {
00088   return mongo_util_oid_new_with_time (time (NULL), seq);
00089 }
00090 
00091 gchar *
00092 mongo_util_oid_as_string (const guint8 *oid)
00093 {
00094   gchar *str;
00095   gint j;
00096 
00097   if (!oid)
00098     return NULL;
00099 
00100   str = g_new (gchar, 26);
00101   for (j = 0; j < 12; j++)
00102     g_sprintf (&str[j * 2], "%02x", oid[j]);
00103   str[25] = 0;
00104   return str;
00105 }
00106 
00107 gboolean
00108 mongo_util_parse_addr (const gchar *addr, gchar **host, gint *port)
00109 {
00110   gchar *port_s, *ep;
00111   glong p;
00112 
00113   if (!addr || !host || !port)
00114     {
00115       if (host)
00116         *host = NULL;
00117       if (port)
00118         *port = -1;
00119       errno = EINVAL;
00120       return FALSE;
00121     }
00122 
00123   /* Check for IPv6 literal */
00124   if (addr[0] == '[')
00125     {
00126       /* Host is everything between [] */
00127       port_s = strchr (addr + 1, ']');
00128       if (!port_s || port_s - addr == 1)
00129         {
00130           *host = NULL;
00131           *port = -1;
00132           errno = EINVAL;
00133           return FALSE;
00134         }
00135       *host = g_strndup (addr + 1, port_s - addr - 1);
00136 
00137       port_s += 2;
00138       if (port_s - addr >= (glong)strlen (addr))
00139         return TRUE;
00140     }
00141   else
00142     {
00143       /* Dealing with something that's not an IPv6 literal */
00144 
00145       /* Split up to host:port */
00146       port_s = g_strrstr (addr, ":");
00147       if (!port_s)
00148         {
00149           *host = g_strdup (addr);
00150           return TRUE;
00151         }
00152       if (port_s == addr)
00153         {
00154           *host = NULL;
00155           *port = -1;
00156           errno = EINVAL;
00157           return FALSE;
00158         }
00159       port_s++;
00160       *host = g_strndup (addr, port_s - addr - 1);
00161     }
00162 
00163   p = strtol (port_s, &ep, 10);
00164   if (p == LONG_MIN || p == LONG_MAX)
00165     {
00166       g_free (*host);
00167       *host = NULL;
00168       *port = -1;
00169       errno = ERANGE;
00170       return FALSE;
00171     }
00172   if (p < 0 || p > INT_MAX)
00173     {
00174       g_free (*host);
00175       *host = NULL;
00176       *port = -1;
00177       errno = ERANGE;
00178       return FALSE;
00179     }
00180   *port = (gint)p;
00181 
00182   if (ep && *ep)
00183     {
00184       g_free (*host);
00185       *host = NULL;
00186       *port = -1;
00187       errno = EINVAL;
00188       return FALSE;
00189     }
00190   return TRUE;
00191 }
 All Data Structures Files Functions Variables Enumerations Enumerator Defines