[launchd-changes] [23232] trunk/launchd/src/liblaunch.c

source_changes at macosforge.org source_changes at macosforge.org
Tue Apr 24 10:56:25 PDT 2007


Revision: 23232
          http://trac.macosforge.org/projects/launchd/changeset/23232
Author:   zarzycki at apple.com
Date:     2007-04-24 10:56:25 -0700 (Tue, 24 Apr 2007)

Log Message:
-----------
Getting ready for growth again...

This is a redesign of the pack and unpack routines. We're about to mix them with MIG calls.

Modified Paths:
--------------
    trunk/launchd/src/liblaunch.c

Modified: trunk/launchd/src/liblaunch.c
===================================================================
--- trunk/launchd/src/liblaunch.c	2007-04-23 20:11:59 UTC (rev 23231)
+++ trunk/launchd/src/liblaunch.c	2007-04-24 17:56:25 UTC (rev 23232)
@@ -37,6 +37,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <pwd.h>
+#include <assert.h>
 
 #include "libbootstrap_public.h"
 #include "libvproc_public.h"
@@ -138,8 +139,8 @@
 	int	fd;
 };
 
-static void launch_data_pack(launch_data_t, void **, size_t *, int **, size_t *);
-static launch_data_t launch_data_unpack(launch_t, size_t *, size_t *);
+static size_t launch_data_pack(launch_data_t d, void *where, size_t len, int *fd_where, size_t *fdslotsleft);
+static launch_data_t launch_data_unpack(void *data, size_t data_size, int *fds, size_t fd_cnt, size_t *data_offset, size_t *fdoffset);
 static launch_data_t launch_data_array_pop_first(launch_data_t where);
 static int _fd(int fd);
 static void launch_client_init(void);
@@ -576,17 +577,17 @@
 
 #define ROUND_TO_64BIT_WORD_SIZE(x)	((x + 7) & ~7)
 
-void
-launch_data_pack(launch_data_t d, void **where, size_t *len, int **fd_where, size_t *fdcnt)
+size_t
+launch_data_pack(launch_data_t d, void *where, size_t len, int *fd_where, size_t *fd_cnt)
 {
-	launch_data_t o_in_w;
-	size_t i;
+	launch_data_t o_in_w = where;
+	size_t i, rsz, total_data_len = sizeof(struct _launch_data);
 
-	*where = reallocf(*where, *len + sizeof(struct _launch_data));
+	if (total_data_len > len) {
+		return 0;
+	}
 
-	o_in_w = *where + *len;
-	memset(o_in_w, 0, sizeof(struct _launch_data));
-	*len += sizeof(struct _launch_data);
+	where += total_data_len;
 
 	o_in_w->type = host2big(d->type);
 
@@ -605,46 +606,62 @@
 		break;
 	case LAUNCH_DATA_FD:
 		o_in_w->fd = host2big(d->fd);
-		if (d->fd != -1) {
-			*fd_where = reallocf(*fd_where, (*fdcnt + 1) * sizeof(int));
-			(*fd_where)[*fdcnt] = d->fd;
-			(*fdcnt)++;
+		if (!fd_where) {
+			return 0;
+		} else if (d->fd != -1) {
+			fd_where[*fd_cnt] = d->fd;
+			(*fd_cnt)++;
 		}
 		break;
 	case LAUNCH_DATA_STRING:
 		o_in_w->string_len = host2big(d->string_len);
-		*where = reallocf(*where, ROUND_TO_64BIT_WORD_SIZE(*len + strlen(d->string) + 1));
-		memcpy(*where + *len, d->string, strlen(d->string) + 1);
-		*len += ROUND_TO_64BIT_WORD_SIZE(strlen(d->string) + 1);
+		total_data_len += ROUND_TO_64BIT_WORD_SIZE(strlen(d->string) + 1);
+		if (total_data_len > len) {
+			return 0;
+		}
+		memcpy(where, d->string, strlen(d->string) + 1);
 		break;
 	case LAUNCH_DATA_OPAQUE:
 		o_in_w->opaque_size = host2big(d->opaque_size);
-		*where = reallocf(*where, ROUND_TO_64BIT_WORD_SIZE(*len + d->opaque_size));
-		memcpy(*where + *len, d->opaque, d->opaque_size);
-		*len += ROUND_TO_64BIT_WORD_SIZE(d->opaque_size);
+		total_data_len += ROUND_TO_64BIT_WORD_SIZE(d->opaque_size);
+		if (total_data_len > len) {
+			return 0;
+		}
+		memcpy(where, d->opaque, d->opaque_size);
 		break;
 	case LAUNCH_DATA_DICTIONARY:
 	case LAUNCH_DATA_ARRAY:
 		o_in_w->_array_cnt = host2big(d->_array_cnt);
-		*where = reallocf(*where, *len + (d->_array_cnt * sizeof(uint64_t)));
-		memset(*where + *len, 0, d->_array_cnt * sizeof(uint64_t));
-		*len += d->_array_cnt * sizeof(uint64_t);
+		total_data_len += d->_array_cnt * sizeof(uint64_t);
+		if (total_data_len > len) {
+			return 0;
+		}
 
-		for (i = 0; i < d->_array_cnt; i++)
-			launch_data_pack(d->_array[i], where, len, fd_where, fdcnt);
+		where += d->_array_cnt * sizeof(uint64_t);
+
+		for (i = 0; i < d->_array_cnt; i++) {
+			rsz = launch_data_pack(d->_array[i], where, len - total_data_len, fd_where, fd_cnt);
+			if (rsz == 0) {
+				return 0;
+			}
+			where += rsz;
+			total_data_len += rsz;
+		}
 		break;
 	default:
 		break;
 	}
+
+	return total_data_len;
 }
 
 launch_data_t
-launch_data_unpack(launch_t conn, size_t *data_offset, size_t *fdoffset)
+launch_data_unpack(void *data, size_t data_size, int *fds, size_t fd_cnt, size_t *data_offset, size_t *fdoffset)
 {
-	launch_data_t r = conn->recvbuf + *data_offset;
+	launch_data_t r = data + *data_offset;
 	size_t i, tmpcnt;
 
-	if ((conn->recvlen - *data_offset) < sizeof(struct _launch_data))
+	if ((data_size - *data_offset) < sizeof(struct _launch_data))
 		return NULL;
 	*data_offset += sizeof(struct _launch_data);
 
@@ -652,14 +669,14 @@
 	case LAUNCH_DATA_DICTIONARY:
 	case LAUNCH_DATA_ARRAY:
 		tmpcnt = big2host(r->_array_cnt);
-		if ((conn->recvlen - *data_offset) < (tmpcnt * sizeof(uint64_t))) {
+		if ((data_size - *data_offset) < (tmpcnt * sizeof(uint64_t))) {
 			errno = EAGAIN;
 			return NULL;
 		}
-		r->_array = conn->recvbuf + *data_offset;
+		r->_array = data + *data_offset;
 		*data_offset += tmpcnt * sizeof(uint64_t);
 		for (i = 0; i < tmpcnt; i++) {
-			r->_array[i] = launch_data_unpack(conn, data_offset, fdoffset);
+			r->_array[i] = launch_data_unpack(data, data_size, fds, fd_cnt, data_offset, fdoffset);
 			if (r->_array[i] == NULL)
 				return NULL;
 		}
@@ -667,27 +684,27 @@
 		break;
 	case LAUNCH_DATA_STRING:
 		tmpcnt = big2host(r->string_len);
-		if ((conn->recvlen - *data_offset) < (tmpcnt + 1)) {
+		if ((data_size - *data_offset) < (tmpcnt + 1)) {
 			errno = EAGAIN;
 			return NULL;
 		}
-		r->string = conn->recvbuf + *data_offset;
+		r->string = data + *data_offset;
 		r->string_len = tmpcnt;
 		*data_offset += ROUND_TO_64BIT_WORD_SIZE(tmpcnt + 1);
 		break;
 	case LAUNCH_DATA_OPAQUE:
 		tmpcnt = big2host(r->opaque_size);
-		if ((conn->recvlen - *data_offset) < tmpcnt) {
+		if ((data_size - *data_offset) < tmpcnt) {
 			errno = EAGAIN;
 			return NULL;
 		}
-		r->opaque = conn->recvbuf + *data_offset;
+		r->opaque = data + *data_offset;
 		r->opaque_size = tmpcnt;
 		*data_offset += ROUND_TO_64BIT_WORD_SIZE(tmpcnt);
 		break;
 	case LAUNCH_DATA_FD:
-		if (r->fd != -1) {
-			r->fd = _fd(conn->recvfds[*fdoffset]);
+		if (r->fd != -1 && fd_cnt > *fdoffset) {
+			r->fd = _fd(fds[*fdoffset]);
 			*fdoffset += 1;
 		}
 		break;
@@ -726,12 +743,30 @@
 
 	memset(&mh, 0, sizeof(mh));
 
+	/* confirm that the next hack works */
+	assert((d && lh->sendlen == 0) || (!d && lh->sendlen));
+
 	if (d) {
-		uint64_t msglen = lh->sendlen;
+		size_t fd_slots_used = 0;
+		size_t good_enough_size = 10 * 1024 * 1024;
+		uint64_t msglen;
 
-		launch_data_pack(d, &lh->sendbuf, &lh->sendlen, &lh->sendfds, &lh->sendfdcnt);
+		/* hack, see the above assert to verify "correctness" */
+		free(lh->sendbuf);
+		lh->sendbuf = malloc(good_enough_size);
+		free(lh->sendfds);
+		lh->sendfds = malloc(4 * 1024);
 
-		msglen = (lh->sendlen - msglen) + sizeof(struct launch_msg_header);
+		lh->sendlen = launch_data_pack(d, lh->sendbuf, good_enough_size, lh->sendfds, &fd_slots_used);
+
+		if (lh->sendlen == 0) {
+			errno = ENOMEM;
+			return -1;
+		}
+
+		lh->sendfdcnt = fd_slots_used;
+
+		msglen = lh->sendlen + sizeof(struct launch_msg_header); /* type promotion to make the host2big() macro work right */
 		lmh.len = host2big(msglen);
 		lmh.magic = host2big(LAUNCH_MSG_HEADER_MAGIC);
 
@@ -966,7 +1001,7 @@
 			goto need_more_data;
 		}
 
-		if ((rmsg = launch_data_unpack(lh, &data_offset, &fd_offset)) == NULL) {
+		if ((rmsg = launch_data_unpack(lh->recvbuf, lh->recvlen, lh->recvfds, lh->recvfdcnt, &data_offset, &fd_offset)) == NULL) {
 			errno = EBADRPC;
 			goto out_bad;
 		}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20070424/00045341/attachment.html


More information about the launchd-changes mailing list