s3-printing: an empty cups printer list is treated as an error
authorDavid Disseldorp <ddiss@suse.de>
Tue, 24 May 2011 09:34:59 +0000 (11:34 +0200)
committerKarolin Seeger <kseeger@samba.org>
Tue, 14 Jun 2011 10:58:24 +0000 (12:58 +0200)
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.

Signed-off-by: Günther Deschner <gd@samba.org>
(cherry picked from commit 683b0652e23b787c5038ff5d7466fdc2a8b3c07f)

source3/printing/print_cups.c

index 49932e32a474d266fd07a2a35d53a0386e6f1496..a62ea91c1f6b9ebd40e320476517d33fcd5e0c94 100644 (file)
@@ -459,6 +459,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));
@@ -476,6 +477,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;
                }
 
@@ -490,6 +492,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;
                }
 
@@ -499,6 +502,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);
@@ -509,6 +513,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",
@@ -519,6 +524,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);
@@ -529,6 +535,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",
@@ -538,14 +545,21 @@ 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) {
-               /* We got a namelist, replace our local cache. */
+       if (!ret_ok) {
+               DEBUG(0,("failed to read a new printer list\n"));
+               pcap_cache_destroy_specific(&tmp_pcap_cache);
+       } else {
+               /* We got a possibly empty namelist, replace our local cache. */
                pcap_cache_destroy_specific(&local_pcap_copy);
                local_pcap_copy = tmp_pcap_cache;
 
@@ -556,9 +570,6 @@ static void cups_async_callback(struct event_context *event_ctx,
                if (cb_args->post_cache_fill_fn) {
                        cb_args->post_cache_fill_fn();
                }
-       } else {
-               DEBUG(2,("cups_async_callback: failed to read a new "
-                       "printer list\n"));
        }
        close(fd);
        TALLOC_FREE(cb_args);