Author: sandervanderburg
Date: Sun Oct 17 13:20:48 2010
New Revision: 24325
URL: https://svn.nixos.org/websvn/nix/?rev=24325&sc=1
Log:
- Completed separating disnix-activate in modules
- Fixed memory leaks in activate_system() function
Added:
disnix/disnix/trunk/src/activate/activate.c
disnix/disnix/trunk/src/activate/activate.h
disnix/disnix/trunk/src/activate/profiles.c
disnix/disnix/trunk/src/activate/profiles.h
Modified:
disnix/disnix/trunk/src/activate/Makefile.am
disnix/disnix/trunk/src/activate/main.c
disnix/disnix/trunk/src/activate/transition.c
Modified: disnix/disnix/trunk/src/activate/Makefile.am
==============================================================================
--- disnix/disnix/trunk/src/activate/Makefile.am Sat Oct 16 23:25:10
2010 (r24324)
+++ disnix/disnix/trunk/src/activate/Makefile.am Sun Oct 17 13:20:48
2010 (r24325)
@@ -1,8 +1,8 @@
AM_CPPFLAGS = -ggdb -DLOCALSTATEDIR=\"$(localstatedir)\"
bin_PROGRAMS = disnix-activate
-noinst_HEADERS = transition.h locking.h
+noinst_HEADERS = transition.h locking.h profiles.h activate.h
-disnix_activate_SOURCES = transition.c locking.c main.c
+disnix_activate_SOURCES = transition.c locking.c profiles.c activate.c main.c
disnix_activate_LDADD = ../libmanifest/libmanifest.la ../libmain/libmain.la
../libinterface/libinterface.la
disnix_activate_CFLAGS = -I../libmanifest -I../libmain -I../libinterface
Added: disnix/disnix/trunk/src/activate/activate.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ disnix/disnix/trunk/src/activate/activate.c Sun Oct 17 13:20:48 2010
(r24325)
@@ -0,0 +1,128 @@
+/*
+ * Disnix - A distributed application layer for Nix
+ * Copyright (C) 2008-2010 Sander van der Burg
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
+ */
+
+#include "activate.h"
+#include "locking.h"
+#include "transition.h"
+#include "profiles.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+
+#include <distributionmapping.h>
+#include <activationmapping.h>
+
+int activate_system(gchar *interface, gchar *new_manifest, gchar
*old_manifest, gchar *coordinator_profile_path, gchar *profile)
+{
+ gchar *old_manifest_file;
+ GArray *old_activation_mappings;
+ int exit_status = 0;
+
+ /* Get all the distribution items of the new configuration */
+ GArray *distribution_array = generate_distribution_array(new_manifest);
+
+ /* Get all the activation items of the new configuration */
+ GArray *new_activation_mappings = create_activation_array(new_manifest);
+
+ /* Get current username */
+ char *username = (getpwuid(geteuid()))->pw_name;
+
+ /* If no previous configuration is given, check whether we have one in the
coordinator profile */
+ if(old_manifest == NULL)
+ {
+ FILE *file;
+
+ if(coordinator_profile_path == NULL)
+ old_manifest_file = g_strconcat(LOCALSTATEDIR
"/nix/profiles/per-user/", username, "/disnix-coordinator/", profile, NULL);
+ else
+ old_manifest_file = g_strconcat(coordinator_profile_path, "/",
profile, NULL);
+
+ /* Try to open file => if it succeeds we have a previous configuration
*/
+ file = fopen(old_manifest_file, "r");
+
+ if(file == NULL)
+ {
+ g_free(old_manifest_file);
+ old_manifest_file = NULL;
+ }
+ else
+ fclose(file);
+ }
+ else
+ old_manifest_file = g_strdup(old_manifest);
+
+ /* If we have an old configuration -> open it */
+ if(old_manifest_file != NULL)
+ {
+ printf("Using previous manifest: %s\n", old_manifest_file);
+ old_activation_mappings = create_activation_array(old_manifest_file);
+
+ /* Free the variable because it's not needed anymore */
+ g_free(old_manifest_file);
+ }
+ else
+ old_activation_mappings = NULL;
+
+
+ /* Try to acquire a lock */
+ if(lock(interface, distribution_array, profile))
+ {
+ /* Execute transition */
+ if(transition(interface, new_activation_mappings,
old_activation_mappings))
+ {
+ int status;
+
+ /* Set the new profiles on the target machines */
+ printf("Setting the new profiles on the target machines:\n");
+ status = set_target_profiles(distribution_array, interface,
profile);
+
+ /* Try to release the lock */
+ unlock(interface, distribution_array, profile);
+
+ /* If setting the profiles succeeds -> set the coordinator profile
*/
+ if(status)
+ {
+ if(!set_coordinator_profile(coordinator_profile_path,
new_manifest, profile, username))
+ exit_status = 1; /* if settings the coordinator profile
fails -> change exit status */
+ }
+ else
+ exit_status = 1; /* else change exit status */
+ }
+ else
+ {
+ /* Try to release the lock */
+ unlock(interface, distribution_array, profile);
+ exit_status = 1;
+ }
+ }
+ else
+ exit_status = 1;
+
+ /* Cleanup */
+ delete_distribution_array(distribution_array);
+ delete_activation_array(new_activation_mappings);
+
+ if(old_activation_mappings != NULL)
+ delete_activation_array(old_activation_mappings);
+
+ /* Return the exit status, which is 0 if everything succeeded */
+ return exit_status;
+}
Added: disnix/disnix/trunk/src/activate/activate.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ disnix/disnix/trunk/src/activate/activate.h Sun Oct 17 13:20:48 2010
(r24325)
@@ -0,0 +1,42 @@
+/*
+ * Disnix - A distributed application layer for Nix
+ * Copyright (C) 2008-2010 Sander van der Burg
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
+ */
+
+#ifndef __ACTIVATE_H
+#define __ACTIVATE_H
+#include <glib.h>
+
+/**
+ * Activates a distributed system deployment state defined in a manifest file.
+ * In this process all the obsolete services from the previous deployment
+ * configuration are deactivated and new services from the desired
configuration
+ * are activated, without breaking inter-dependencies and taking the right
+ * order of activation into account. Moreover, before the activation
+ * all services receive a lock request which they can use for e.g. blocking,
+ * which is released after the process is completed.
+ *
+ * @param interface Path to the client interface executable
+ * @param new_manifest Manifest file representing the new deployment
configuration
+ * @param new_manifest Manifest file representing the old deployment
configuration
+ * @param coordinator_profile_path Path where the current deployment state is
stored for future reference
+ * @param profile Name of the distributed profile
+ * @return 0 if the process suceeds, else a non-zero exit value
+ */
+int activate_system(gchar *interface, gchar *new_manifest, gchar
*old_manifest, gchar *coordinator_profile_path, gchar *profile);
+
+#endif
Modified: disnix/disnix/trunk/src/activate/main.c
==============================================================================
--- disnix/disnix/trunk/src/activate/main.c Sat Oct 16 23:25:10 2010
(r24324)
+++ disnix/disnix/trunk/src/activate/main.c Sun Oct 17 13:20:48 2010
(r24325)
@@ -17,22 +17,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
*/
-#include <stdlib.h>
#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#define _GNU_SOURCE
#include <getopt.h>
-#include <glib.h>
-#include <activationmapping.h>
-#include <distributionmapping.h>
+#define _GNU_SOURCE
#include <defaultoptions.h>
-#include <client-interface.h>
-#include "transition.h"
-#include "locking.h"
+#include "activate.h"
static void print_usage()
{
@@ -41,82 +30,6 @@
fprintf(stderr, "disnix-activate {-h | --help}\n");
}
-static int set_target_profiles(GArray *distribution_array, char *interface,
char *profile)
-{
- unsigned int i;
-
- for(i = 0; i < distribution_array->len; i++)
- {
- int status;
- DistributionItem *item = g_array_index(distribution_array,
DistributionItem*, i);
-
- printf("Setting profile: %s on target: %s\n", item->profile,
item->target);
-
- status = wait_to_finish(exec_set(interface, item->target, profile,
item->profile));
-
- if(status != 0)
- {
- fprintf(stderr, "Cannot set profile!\n");
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static int set_coordinator_profile(char *coordinator_profile_path, char
*distribution_manifest, char *profile, char *username)
-{
- gchar *profile_path, *distribution_manifest_path;
- int status;
-
- printf("Setting the coordinator profile:\n");
-
- if(coordinator_profile_path == NULL)
- profile_path = g_strconcat(LOCALSTATEDIR, "/nix/profiles/per-user/",
username, "/disnix-coordinator", NULL);
- else
- profile_path = g_strdup(coordinator_profile_path);
-
- if(mkdir(profile_path, 0755) == -1)
- fprintf(stderr, "Cannot create profile directory: %s\n", profile_path);
-
- g_free(profile_path);
-
- if((strlen(distribution_manifest) >= 1 && distribution_manifest[0] == '/')
||
- (strlen(distribution_manifest) >= 2 && distribution_manifest[0] == '.'
|| distribution_manifest[1] == '/'))
- distribution_manifest_path = g_strdup(distribution_manifest);
- else
- distribution_manifest_path = g_strconcat("./", NULL);
-
- if(coordinator_profile_path == NULL)
- profile_path = g_strconcat(LOCALSTATEDIR "/nix/profiles/per-user/",
username, "/disnix-coordinator/", profile, NULL);
- else
- profile_path = g_strconcat(coordinator_profile_path, "/", profile,
NULL);
-
- status = fork();
-
- if(status == 0)
- {
- char *args[] = {"nix-env", "-p", profile_path, "--set",
distribution_manifest_path, NULL};
- execvp("nix-env", args);
- _exit(1);
- }
-
- g_free(profile_path);
- g_free(distribution_manifest_path);
-
- if(status == -1)
- return FALSE;
- else
- {
- wait(&status);
-
- if(WEXITSTATUS(status) == 0)
- return TRUE;
- else
- return FALSE;
- }
-}
-
int main(int argc, char *argv[])
{
/* Declarations */
@@ -169,92 +82,5 @@
return 1;
}
else
- {
- /* Get current username */
- char *username = (getpwuid(geteuid()))->pw_name;
- gchar *old_manifest_file;
- GArray *list_new = create_activation_array(argv[optind]);
- GArray *list_old;
- GArray *distribution_array = generate_distribution_array(argv[optind]);
- int status;
-
- if(old_manifest == NULL)
- {
- FILE *file;
-
- /* If no old manifest file is given, try to to open the manifest
file in the Nix profile */
-
- if(coordinator_profile_path == NULL)
- old_manifest_file = g_strconcat(LOCALSTATEDIR
"/nix/profiles/per-user/", username, "/disnix-coordinator/", profile, NULL);
- else
- old_manifest_file = g_strconcat(coordinator_profile_path, "/",
profile, NULL);
-
- file = fopen(old_manifest_file, "r");
-
- if(file == NULL)
- {
- g_free(old_manifest_file);
- old_manifest_file = NULL;
- }
- else
- fclose(file);
- }
- else
- old_manifest_file = g_strdup(old_manifest);
-
- if(old_manifest_file != NULL)
- {
- printf("Using previous manifest: %s\n", old_manifest_file);
- list_old = create_activation_array(old_manifest_file);
- g_free(old_manifest_file);
- }
- else
- list_old = NULL;
-
- /* Try to acquire a lock */
- if(!lock(interface, distribution_array, profile))
- {
- delete_distribution_array(distribution_array);
- return 1;
- }
-
- /* Execute transition */
- status = transition(interface, list_new, list_old);
-
- /* If the transition failed, abort */
- if(!status)
- {
- /* Try to release the lock */
- unlock(interface, distribution_array, profile);
-
- delete_distribution_array(distribution_array);
- return 1;
- }
-
- /* Set the new profiles on the target machines */
- printf("Setting the new profiles on the target machines:\n");
- status = set_target_profiles(distribution_array, interface, profile);
-
- /* Try to release the lock */
- unlock(interface, distribution_array, profile);
-
- /* If setting the profiles failed, abort */
- if(!status)
- {
- delete_distribution_array(distribution_array);
- return 1;
- }
-
- /* Store the activated manifest in the profile of the current user */
- if(!set_coordinator_profile(coordinator_profile_path, argv[optind],
profile, username))
- {
- delete_distribution_array(distribution_array);
- return 1;
- }
-
- /* Cleanup */
- delete_distribution_array(distribution_array);
-
- return 0;
- }
+ return activate_system(interface, argv[optind], old_manifest,
coordinator_profile_path, profile); /* Execute activation operation */
}
Added: disnix/disnix/trunk/src/activate/profiles.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ disnix/disnix/trunk/src/activate/profiles.c Sun Oct 17 13:20:48 2010
(r24325)
@@ -0,0 +1,117 @@
+/*
+ * Disnix - A distributed application layer for Nix
+ * Copyright (C) 2008-2010 Sander van der Burg
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
+ */
+
+#include "profiles.h"
+#include <distributionmapping.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <string.h>
+
+gboolean set_target_profiles(GArray *distribution_array, gchar *interface,
gchar *profile)
+{
+ unsigned int i;
+
+ for(i = 0; i < distribution_array->len; i++)
+ {
+ int status;
+ DistributionItem *item = g_array_index(distribution_array,
DistributionItem*, i);
+
+ g_print("Setting profile: %s on target: %s\n", item->profile,
item->target);
+
+ status = wait_to_finish(exec_set(interface, item->target, profile,
item->profile));
+
+ if(status != 0)
+ {
+ g_printerr("Cannot set profile!\n");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean set_coordinator_profile(gchar *coordinator_profile_path, gchar
*manifest_file, gchar *profile, gchar *username)
+{
+ gchar *profile_path, *manifest_file_path;
+ int status;
+
+ g_print("Setting the coordinator profile:\n");
+
+ /* Determine which profile path to use, if a coordinator profile path is
given use this value otherwise the default */
+ if(coordinator_profile_path == NULL)
+ profile_path = g_strconcat(LOCALSTATEDIR, "/nix/profiles/per-user/",
username, "/disnix-coordinator", NULL);
+ else
+ profile_path = g_strdup(coordinator_profile_path);
+
+ /* Create the profile directory */
+ if(mkdir(profile_path, 0755) == -1)
+ g_printerr("Cannot create profile directory: %s\n", profile_path);
+
+ /* Profile path is not needed anymore */
+ g_free(profile_path);
+
+ /* If the manifest file is an absolute path or a relative path starting
+ * with ./ then the path is OK
+ */
+
+ if((strlen(manifest_file) >= 1 && manifest_file[0] == '/') ||
+ (strlen(manifest_file) >= 2 && manifest_file[0] == '.' ||
manifest_file[1] == '/'))
+ manifest_file_path = g_strdup(manifest_file);
+ else
+ manifest_file_path = g_strconcat("./", manifest_file, NULL); /*
Otherwise add ./ in front of the path */
+
+ /* Determine the path to the profile */
+ if(coordinator_profile_path == NULL)
+ profile_path = g_strconcat(LOCALSTATEDIR "/nix/profiles/per-user/",
username, "/disnix-coordinator/", profile, NULL);
+ else
+ profile_path = g_strconcat(coordinator_profile_path, "/", profile,
NULL);
+
+ /* Execute nix-env --set operation to change the coordinator profile so
+ * that the new configuration is known
+ */
+
+ status = fork();
+
+ if(status == 0)
+ {
+ char *args[] = {"nix-env", "-p", profile_path, "--set",
manifest_file_path, NULL};
+ execvp("nix-env", args);
+ _exit(1);
+ }
+
+ /* Cleanup */
+ g_free(profile_path);
+ g_free(manifest_file_path);
+
+ /* If the process suceeds the the operation succeeded */
+ if(status == -1)
+ return FALSE;
+ else
+ {
+ wait(&status);
+
+ if(WEXITSTATUS(status) == 0)
+ return TRUE;
+ else
+ return FALSE;
+ }
+}
Added: disnix/disnix/trunk/src/activate/profiles.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ disnix/disnix/trunk/src/activate/profiles.h Sun Oct 17 13:20:48 2010
(r24325)
@@ -0,0 +1,47 @@
+/*
+ * Disnix - A distributed application layer for Nix
+ * Copyright (C) 2008-2010 Sander van der Burg
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
+ */
+
+#ifndef __PROFILES_H
+#define __PROFILES_H
+#include <glib.h>
+
+/**
+ * Sets the Disnix profiles on the target machine, so that the services are
+ * no longer garbage to the Nix package manager.
+ *
+ * @param distribution_array Array with Nix profiles containing installed
services for each machine
+ * @param interface Path to the client interface executable
+ * @param profile Name of the distributed profile
+ * @return TRUE if everything succeeds, else FALSE
+ */
+gboolean set_target_profiles(GArray *distribution_array, gchar *interface,
gchar *profile);
+
+/**
+ * Sets the Disnix coordinator profile, so that the current configuration is
+ * known, which we can use for efficient future upgrades.
+ *
+ * @param coordinator_profile Path where the current deployment configuration
must be stored
+ * @param manifest_file Path to the manifest file representing the deployment
state
+ * @param profile Name of the distributed profile
+ * @param username Username of the current user invoking the activation
+ * @return TRUE if everything succeeds, else FALSE
+ */
+gboolean set_coordinator_profile(gchar *coordinator_profile_path, gchar
*manifest_file, gchar *profile, gchar *username);
+
+#endif
Modified: disnix/disnix/trunk/src/activate/transition.c
==============================================================================
--- disnix/disnix/trunk/src/activate/transition.c Sat Oct 16 23:25:10
2010 (r24324)
+++ disnix/disnix/trunk/src/activate/transition.c Sun Oct 17 13:20:48
2010 (r24325)
@@ -156,6 +156,7 @@
GArray *union_array;
GArray *deactivation_array;
GArray *activation_array;
+ gboolean exit_status = TRUE;
unsigned int i;
/* Print configurations */
@@ -186,6 +187,7 @@
union_array = union_activation_array(old_activation_mappings,
new_activation_mappings, intersection_array);
print_activation_array(union_array);
+ /* Remove obsolete intersection array */
g_array_free(intersection_array, TRUE);
}
else
@@ -209,7 +211,7 @@
/* Deactivate each mapping closure that is not in the new configuration */
if(deactivation_array != NULL)
- {
+ {
for(i = 0; i < deactivation_array->len; i++)
{
ActivationMapping *mapping = g_array_index(deactivation_array,
ActivationMapping*, i);
@@ -229,53 +231,67 @@
g_print("Rollback failed!\n");
}
- return FALSE;
+ exit_status = FALSE;
+ break;
}
}
}
- /* Execute activation process */
+ /* Execute activation process (if deactivation process did not fail) */
- g_print("Executing activation:\n");
+ if(exit_status)
+ {
+ g_print("Executing activation:\n");
- /* Activate each mapping closure that is new in the new configuration */
+ /* Activate each mapping closure that is new in the new configuration */
- for(i = 0; i < activation_array->len; i++)
- {
- ActivationMapping *mapping = g_array_index(activation_array,
ActivationMapping*, i);
-
- if(!activate(interface, union_array, mapping))
+ for(i = 0; i < activation_array->len; i++)
{
- /* If the activation fails, perform a rollback */
-
- unsigned int j;
- g_print("Activation failed! Doing a rollback...\n");
+ ActivationMapping *mapping = g_array_index(activation_array,
ActivationMapping*, i);
- /* Deactivate the newly activated services */
- for(j = 0; j < activation_array->len; j++)
+ if(!activate(interface, union_array, mapping))
{
- ActivationMapping *mapping = g_array_index(activation_array,
ActivationMapping*, j);
+ /* If the activation fails, perform a rollback */
- if(!deactivate(interface, union_array, mapping))
- g_print("Rollback failed!\n");
- }
+ unsigned int j;
+ g_print("Activation failed! Doing a rollback...\n");
- if(old_activation_mappings != NULL)
- {
- /* Activate all services in the old configuration */
- for(j = 0; j < old_activation_mappings->len; j++)
+ /* Deactivate the newly activated services */
+ for(j = 0; j < activation_array->len; j++)
{
- ActivationMapping *mapping =
g_array_index(old_activation_mappings, ActivationMapping*, j);
-
- if(!activate(interface, union_array, mapping))
+ ActivationMapping *mapping =
g_array_index(activation_array, ActivationMapping*, j);
+
+ if(!deactivate(interface, union_array, mapping))
g_print("Rollback failed!\n");
}
- }
- return FALSE;
+ if(old_activation_mappings != NULL)
+ {
+ /* Activate all services in the old configuration */
+ for(j = 0; j < old_activation_mappings->len; j++)
+ {
+ ActivationMapping *mapping =
g_array_index(old_activation_mappings, ActivationMapping*, j);
+
+ if(!activate(interface, union_array, mapping))
+ g_print("Rollback failed!\n");
+ }
+ }
+
+ exit_status = FALSE;
+ break;
+ }
}
}
- /* Transition process succeeded */
- return TRUE;
+ /* Cleanup */
+
+ if(old_activation_mappings != NULL)
+ {
+ g_array_free(deactivation_array, TRUE);
+ g_array_free(activation_array, TRUE);
+ g_array_free(union_array, TRUE);
+ }
+
+ /* Transition process succeeded */
+ return exit_status;
}
_______________________________________________
nix-commits mailing list
[email protected]
http://mail.cs.uu.nl/mailman/listinfo/nix-commits