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
52bac5ffeea8ecbd2a5ecca023b3e2014c1350da)
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;
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;
DEBUG(5,("cups_async_callback: callback received for printer data. "
"fd = %d\n", fd));
DEBUG(5,("cups_async_callback: callback received for printer data. "
"fd = %d\n", fd));
if (ret != sizeof(namelen)) {
DEBUG(10,("cups_async_callback: namelen read failed %d %s\n",
errno, strerror(errno)));
if (ret != sizeof(namelen)) {
DEBUG(10,("cups_async_callback: namelen read failed %d %s\n",
errno, strerror(errno)));
if (ret != sizeof(infolen)) {
DEBUG(10,("cups_async_callback: infolen read failed %s\n",
strerror(errno)));
if (ret != sizeof(infolen)) {
DEBUG(10,("cups_async_callback: infolen read failed %s\n",
strerror(errno)));
if (namelen) {
name = TALLOC_ARRAY(frame, char, namelen);
if (!name) {
if (namelen) {
name = TALLOC_ARRAY(frame, char, namelen);
if (!name) {
break;
}
ret = sys_read(fd, name, namelen);
break;
}
ret = sys_read(fd, name, namelen);
if (ret != namelen) {
DEBUG(10,("cups_async_callback: name read failed %s\n",
strerror(errno)));
if (ret != namelen) {
DEBUG(10,("cups_async_callback: name read failed %s\n",
strerror(errno)));
break;
}
DEBUG(11,("cups_async_callback: read name %s\n",
break;
}
DEBUG(11,("cups_async_callback: read name %s\n",
if (infolen) {
info = TALLOC_ARRAY(frame, char, infolen);
if (!info) {
if (infolen) {
info = TALLOC_ARRAY(frame, char, infolen);
if (!info) {
break;
}
ret = sys_read(fd, info, infolen);
break;
}
ret = sys_read(fd, info, infolen);
if (ret != infolen) {
DEBUG(10,("cups_async_callback: info read failed %s\n",
strerror(errno)));
if (ret != infolen) {
DEBUG(10,("cups_async_callback: info read failed %s\n",
strerror(errno)));
break;
}
DEBUG(11,("cups_async_callback: read info %s\n",
break;
}
DEBUG(11,("cups_async_callback: read info %s\n",
}
/* Add to our local pcap cache. */
}
/* 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);
TALLOC_FREE(name);
TALLOC_FREE(info);
+ if (!ret_ok) {
+ DEBUG(0, ("failed to add to tmp pcap cache\n"));
+ break;
+ }
- 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;
pcap_cache_destroy_specific(&local_pcap_copy);
local_pcap_copy = tmp_pcap_cache;
if (cb_args->post_cache_fill_fn) {
cb_args->post_cache_fill_fn();
}
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);
}
close(fd);
TALLOC_FREE(cb_args);