Imported Upstream version 3.2.0
[debian/amanda] / common-src / util.c
index 1a812013b77dd2f3cb50d359b8369614bc29739b..9ca0b4db604d249ffdbd737e614b49c60cc706df 100644 (file)
@@ -322,6 +322,56 @@ bind_portrange(
     return -1;
 }
 
+int
+interruptible_accept(
+    int sock,
+    struct sockaddr *addr,
+    socklen_t *addrlen,
+    gboolean (*prolong)(gpointer data),
+    gpointer prolong_data)
+{
+    SELECT_ARG_TYPE readset;
+    struct timeval tv;
+    int nfound;
+
+    if (sock < 0 || sock >= FD_SETSIZE) {
+       g_debug("interruptible_accept: bad socket %d", sock);
+       return EBADF;
+    }
+
+    memset(&readset, 0, SIZEOF(readset));
+
+    while (1) {
+       if (!prolong(prolong_data)) {
+           errno = 0;
+           return -1;
+       }
+
+       FD_ZERO(&readset);
+       FD_SET(sock, &readset);
+
+       /* try accepting for 1s */
+       memset(&tv, 0, SIZEOF(tv));
+       tv.tv_sec = 1;
+
+       nfound = select(sock+1, &readset, NULL, NULL, &tv);
+       if (nfound < 0) {
+           return -1;
+       } else if (nfound == 0) {
+           continue;
+       } else if (!FD_ISSET(sock, &readset)) {
+           g_debug("interruptible_accept: select malfunction");
+           errno = EBADF;
+           return -1;
+       } else {
+           int rv = accept(sock, addr, addrlen);
+           if (rv < 0 && errno == EAGAIN)
+               continue;
+           return rv;
+       }
+    }
+}
+
 /*
  * Writes out the entire iovec
  */
@@ -539,7 +589,7 @@ split_quoted_strings(
     result = g_new0(char *, strs->len + 1);
     memmove(result, strs->pdata, sizeof(char *) * strs->len);
 
-    g_ptr_array_free(strs, FALSE); /* FALSE => don't free strings */
+    g_ptr_array_free(strs, TRUE); /* TRUE => free pdata, strings are not freed */
     g_free(local);
 
     return result;
@@ -699,6 +749,66 @@ cleanup:
     return ret;
 }
 
+/* Helper for parse_braced_component; this will turn a single element array
+ * matching /^\d+\.\.\d+$/ into a sequence of numbered array elements. */
+static GPtrArray *
+expand_braced_sequence(GPtrArray *arr)
+{
+    char *elt, *p;
+    char *l, *r;
+    int ldigits, rdigits, ndigits;
+    guint64 start, end;
+    gboolean leading_zero;
+
+    /* check whether the element matches the pattern */
+    /* expand last element of the array only */
+    elt = g_ptr_array_index(arr, arr->len-1);
+    ldigits = 0;
+    for (l = p = elt; *p && g_ascii_isdigit(*p); p++)
+       ldigits++;
+    if (ldigits == 0)
+       return arr;
+    if (*(p++) != '.')
+       return arr;
+    if (*(p++) != '.')
+       return arr;
+    rdigits = 0;
+    for (r = p; *p && g_ascii_isdigit(*p); p++)
+       rdigits++;
+    if (rdigits == 0)
+       return arr;
+    if (*p)
+       return arr;
+
+    /* we have a match, so extract start and end */
+    start = g_ascii_strtoull(l, NULL, 10);
+    end = g_ascii_strtoull(r, NULL, 10);
+    leading_zero = *l == '0';
+    ndigits = MAX(ldigits, rdigits);
+    if (start > end)
+       return arr;
+
+    /* sanity check.. */
+    if (end - start > 100000)
+       return arr;
+
+    /* remove last from the array */
+    g_ptr_array_remove_index(arr, arr->len - 1);
+
+    /* Add new elements */
+    while (start <= end) {
+       if (leading_zero) {
+           g_ptr_array_add(arr, g_strdup_printf("%0*ju",
+                       ndigits, (uintmax_t)start));
+       } else {
+           g_ptr_array_add(arr, g_strdup_printf("%ju", (uintmax_t)start));
+       }
+       start++;
+    }
+
+    return arr;
+}
+
 /* Helper for expand_braced_alternates; returns a list of un-escaped strings
  * for the first "component" of str, where a component is a plain string or a
  * brace-enclosed set of alternatives.  str is pointing to the first character
@@ -725,6 +835,7 @@ parse_braced_component(char **str)
            if (*p == '}' || *p == ',') {
                *c = '\0';
                g_ptr_array_add(result, g_strdup(current));
+               result = expand_braced_sequence(result);
                current = ++c;
 
                if (*p == '}')
@@ -1298,23 +1409,15 @@ base64_decode_alloc_string(
 }
 
 
-/* A GHFunc (callback for g_hash_table_foreach) */
-void count_proplist(
-    gpointer key_p G_GNUC_UNUSED,
-    gpointer value_p,
-    gpointer user_data_p)
-{
-    property_t *value_s = value_p;
-    int    *nb = user_data_p;
-    GSList  *value;
-
-    for(value=value_s->values; value != NULL; value = value->next) {
-       (*nb)++;
-    }
-}
-
-/* A GHFunc (callback for g_hash_table_foreach) */
-void proplist_add_to_argv(
+/* A GHFunc (callback for g_hash_table_foreach),
+ * Store a property and it's value in an ARGV.
+ *
+ * @param key_p: (char *) property name.
+ * @param value_p: (GSList *) property values list.
+ * @param user_data_p: (char ***) pointer to ARGV.
+ */
+static void
+proplist_add_to_argv(
     gpointer key_p,
     gpointer value_p,
     gpointer user_data_p)
@@ -1341,6 +1444,14 @@ void proplist_add_to_argv(
     amfree(qprop);
 }
 
+void
+property_add_to_argv(
+    GPtrArray  *argv_ptr,
+    GHashTable *proplist)
+{
+    g_hash_table_foreach(proplist, &proplist_add_to_argv, argv_ptr);
+}
+
 
 /*
  * Process parameters