[PATCH 2/2] s3-printing: fix cups pcap reload with no printers

David Disseldorp ddiss at suse.de
Thu Dec 30 07:58:48 MST 2010


cups_async_callback() is called to receive new printcap data from a
child process which requests the information from cupsd.
Newly received printcap information is stored in a temporary printcap
cache (tmp_pcap_cache). Once the child process closes the printcap IPC
file descriptor, the system printcap cache is replaced with the newly
populated tmp_pcap_cache, however this only occurs if tmp_pcap_cache is
non null (has at least one printer).

If the printcap cache is empty, which is the case when cups is not
exporting any printers, the printcap cache is not replaced resulting in
stale data.
---
 source3/printing/print_cups.c |   37 +++++++++++++++++++++++++------------
 1 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c
index a925b65..50be7cd 100644
--- a/source3/printing/print_cups.c
+++ b/source3/printing/print_cups.c
@@ -465,6 +465,7 @@ static void cups_async_callback(struct event_context *event_ctx,
 	struct cups_async_cb_args *cb_args = (struct cups_async_cb_args *)p;
 	int fd = cb_args->pipe_fd;
 	struct pcap_cache *tmp_pcap_cache = NULL;
+	bool ret_ok = true;
 
 	DEBUG(5,("cups_async_callback: callback received for printer data. "
 		"fd = %d\n", fd));
@@ -482,6 +483,7 @@ static void cups_async_callback(struct event_context *event_ctx,
 		if (ret != sizeof(namelen)) {
 			DEBUG(10,("cups_async_callback: namelen read failed %d %s\n",
 				errno, strerror(errno)));
+			ret_ok = false;
 			break;
 		}
 
@@ -496,6 +498,7 @@ static void cups_async_callback(struct event_context *event_ctx,
 		if (ret != sizeof(infolen)) {
 			DEBUG(10,("cups_async_callback: infolen read failed %s\n",
 				strerror(errno)));
+			ret_ok = false;
 			break;
 		}
 
@@ -505,6 +508,7 @@ static void cups_async_callback(struct event_context *event_ctx,
 		if (namelen) {
 			name = TALLOC_ARRAY(frame, char, namelen);
 			if (!name) {
+				ret_ok = false;
 				break;
 			}
 			ret = sys_read(fd, name, namelen);
@@ -515,6 +519,7 @@ static void cups_async_callback(struct event_context *event_ctx,
 			if (ret != namelen) {
 				DEBUG(10,("cups_async_callback: name read failed %s\n",
 					strerror(errno)));
+				ret_ok = false;
 				break;
 			}
 			DEBUG(11,("cups_async_callback: read name %s\n",
@@ -525,6 +530,7 @@ static void cups_async_callback(struct event_context *event_ctx,
 		if (infolen) {
 			info = TALLOC_ARRAY(frame, char, infolen);
 			if (!info) {
+				ret_ok = false;
 				break;
 			}
 			ret = sys_read(fd, info, infolen);
@@ -535,6 +541,7 @@ static void cups_async_callback(struct event_context *event_ctx,
 			if (ret != infolen) {
 				DEBUG(10,("cups_async_callback: info read failed %s\n",
 					strerror(errno)));
+				ret_ok = false;
 				break;
 			}
 			DEBUG(11,("cups_async_callback: read info %s\n",
@@ -544,26 +551,32 @@ static void cups_async_callback(struct event_context *event_ctx,
 		}
 
 		/* Add to our local pcap cache. */
-		pcap_cache_add_specific(&tmp_pcap_cache, name, info);
+		ret_ok = pcap_cache_add_specific(&tmp_pcap_cache, name, info);
 		TALLOC_FREE(name);
 		TALLOC_FREE(info);
+		if (!ret_ok) {
+			DEBUG(0, ("failed to add to tmp pcap cache\n"));
+			break;
+		}
 	}
 
 	TALLOC_FREE(frame);
-	if (tmp_pcap_cache) {
-		bool ret;
-		/* replace the systemwide pcap cache. */
-		ret = pcap_cache_replace(tmp_pcap_cache);
-		if (!ret)
+	if (!ret_ok) {
+		DEBUG(0, ("failed to read a new printer list\n"));
+		pcap_cache_destroy_specific(&tmp_pcap_cache);
+	} else {
+		/*
+		 * replace the system-wide pcap cache with a (possibly empty)
+		 * new one
+		 */
+		ret_ok = pcap_cache_replace(tmp_pcap_cache);
+		if (!ret_ok)
 			DEBUG(0, ("failed to replace pcap cache\n"));
-
-		/* Caller may have requested post cache fill callback */
-		if (ret && cb_args->post_cache_fill_fn)
+		else if (cb_args->post_cache_fill_fn) {
+			/* Caller requested post cache fill callback */
 			cb_args->post_cache_fill_fn(cb_args->event_ctx,
 						    cb_args->msg_ctx);
-	} else {
-		DEBUG(2,("cups_async_callback: failed to read a new "
-			"printer list\n"));
+		}
 	}
 	close(fd);
 	TALLOC_FREE(cb_args);
-- 
1.7.1


--MP_/Jp8DfTXRj5lPy_Is6hQeJpG--


More information about the samba-technical mailing list