summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Disseldorp <ddiss@suse.de>2010-12-30 15:58:48 +0100
committerAndreas Schneider <asn@samba.org>2011-03-04 15:46:23 +0100
commit2b635949a210fd1d8d8906f5185581d566064888 (patch)
treee66a1dcacce50538d39794358ce290ab4dbbda5e
parent624e33f8697a7c9215028d4d70edd70ee49ad005 (diff)
downloadsamba-2b635949a210fd1d8d8906f5185581d566064888.tar.gz
samba-2b635949a210fd1d8d8906f5185581d566064888.tar.bz2
samba-2b635949a210fd1d8d8906f5185581d566064888.zip
s3-printing: fix cups pcap reload with no printers
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. https://bugzilla.samba.org/show_bug.cgi?id=7915 Signed-off-by: Andreas Schneider <asn@samba.org>
-rw-r--r--source3/printing/print_cups.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c
index d2df2587e2..3031a88e5d 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,27 +551,35 @@ 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.
+ * FIXME The child process does not currently propagate cups
+ * errors back up to the parent, therefore we cannot
+ * differentiate between an empty printer list and a failure.
+ */
+ 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 != NULL) {
+ } else if (cb_args->post_cache_fill_fn != NULL) {
+ /* 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);