aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenstore/xenstored_transaction.c
diff options
context:
space:
mode:
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2005-06-24 08:16:13 +0000
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2005-06-24 08:16:13 +0000
commitc8cf49e882fd2e0aa7450e25c7b5b785dc97c725 (patch)
treef07f344f0d31d1177f356479c0316794edd57ad9 /tools/xenstore/xenstored_transaction.c
parent8e6ffdae8e693b28fbe6d753257e3aefd07c9c31 (diff)
downloadxen-c8cf49e882fd2e0aa7450e25c7b5b785dc97c725.tar.gz
xen-c8cf49e882fd2e0aa7450e25c7b5b785dc97c725.tar.bz2
xen-c8cf49e882fd2e0aa7450e25c7b5b785dc97c725.zip
bitkeeper revision 1.1748 (42bbc14djIjScNrLp20eDhlxUjQl4g)
xenstored_transaction.c, xenstored_core.h, xenstored_core.c, TODO: Update TODO list Wrap opendir in talloc so it gets cleaned up on OOM. Remove last call to system by open-coding "cp -al" to create transaction. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
Diffstat (limited to 'tools/xenstore/xenstored_transaction.c')
-rw-r--r--tools/xenstore/xenstored_transaction.c84
1 files changed, 63 insertions, 21 deletions
diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c
index dd70579109..96d45a6b9c 100644
--- a/tools/xenstore/xenstored_transaction.c
+++ b/tools/xenstore/xenstored_transaction.c
@@ -25,6 +25,7 @@
#include <time.h>
#include <stdarg.h>
#include <stdlib.h>
+#include <fcntl.h>
#include "talloc.h"
#include "list.h"
#include "xenstored_transaction.h"
@@ -137,7 +138,7 @@ void add_change_node(struct transaction *trans, const char *node)
char *node_dir_inside_transaction(struct transaction *trans, const char *node)
{
- return talloc_asprintf(node, "%s%s", trans->divert,
+ return talloc_asprintf(node, "%s/%s", trans->divert,
node + strlen(trans->node));
}
@@ -170,33 +171,74 @@ void check_transaction_timeout(void)
}
}
-/* FIXME: Eliminate all uses of this */
-static bool do_command(const char *cmd)
+static int destroy_transaction(void *_transaction)
+{
+ struct transaction *trans = _transaction;
+
+ list_del(&trans->list);
+ return destroy_path(trans->divert);
+}
+
+static bool copy_file(const char *src, const char *dst)
{
- int ret;
+ int *infd, *outfd;
+ void *data;
+ unsigned int size;
- ret = system(cmd);
- if (ret == -1)
+ infd = talloc_open(src, O_RDONLY, 0);
+ if (!infd)
return false;
- if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
- errno = EIO;
+ outfd = talloc_open(dst, O_WRONLY|O_CREAT|O_EXCL, 0640);
+ if (!outfd)
return false;
- }
- return true;
+ data = read_all(infd, &size);
+ if (!data)
+ return false;
+ return xs_write_all(*outfd, data, size);
}
-static int destroy_transaction(void *_transaction)
+static bool copy_dir(const char *src, const char *dst)
{
- struct transaction *trans = _transaction;
+ DIR **dir;
+ struct dirent *dirent;
- list_del(&trans->list);
- return destroy_path(trans->divert);
+ if (mkdir(dst, 0750) != 0)
+ return false;
+
+ dir = talloc_opendir(src);
+ if (!dir)
+ return false;
+
+ while ((dirent = readdir(*dir)) != NULL) {
+ struct stat st;
+ char *newsrc, *newdst;
+
+ if (streq(dirent->d_name, ".") || streq(dirent->d_name, ".."))
+ continue;
+
+ newsrc = talloc_asprintf(src, "%s/%s", src, dirent->d_name);
+ newdst = talloc_asprintf(src, "%s/%s", dst, dirent->d_name);
+ if (stat(newsrc, &st) != 0)
+ return false;
+
+ if (S_ISDIR(st.st_mode)) {
+ if (!copy_dir(newsrc, newdst))
+ return false;
+ } else {
+ if (!copy_file(newsrc, newdst))
+ return false;
+ }
+ /* Free now so we don't run out of file descriptors */
+ talloc_free(newsrc);
+ talloc_free(newdst);
+ }
+ return true;
}
bool do_transaction_start(struct connection *conn, const char *node)
{
struct transaction *transaction;
- char *dir, *cmd;
+ char *dir;
if (conn->transaction)
return send_error(conn, EBUSY);
@@ -213,14 +255,9 @@ bool do_transaction_start(struct connection *conn, const char *node)
/* Attach transaction to node for autofree until it's complete */
transaction = talloc(node, struct transaction);
transaction->node = talloc_strdup(transaction, node);
- transaction->divert = talloc_asprintf(transaction, "%s/%p/",
+ transaction->divert = talloc_asprintf(transaction, "%s/%p",
xs_daemon_transactions(),
transaction);
- cmd = talloc_asprintf(node, "cp -a %s %s", dir, transaction->divert);
- if (!do_command(cmd))
- corrupt(conn, "Creating transaction %s", transaction->divert);
-
- talloc_steal(conn, transaction);
INIT_LIST_HEAD(&transaction->changes);
transaction->conn = conn;
timerclear(&transaction->timeout);
@@ -228,6 +265,11 @@ bool do_transaction_start(struct connection *conn, const char *node)
list_add_tail(&transaction->list, &transactions);
conn->transaction = transaction;
talloc_set_destructor(transaction, destroy_transaction);
+
+ if (!copy_dir(dir, transaction->divert))
+ return send_error(conn, errno);
+
+ talloc_steal(conn, transaction);
return send_ack(transaction->conn, XS_TRANSACTION_START);
}