提交 b59d9c85 编写于 作者: J Jim Meyering

Use safewrite in place of write, in many cases.

Also add "make syntax-check" rules to ensure no new uses sneak in.

There are many uses of write like this:

    if (write (fd, xml, towrite) != towrite)
        return -1;

The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.

This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process.  Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.

* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file.  Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
上级 a178a4e7
^src/util\.c$
^src/xend_internal\.c$
Fri Feb 22 13:32:11 CET 2008 Jim Meyering <meyering@redhat.com> Fri Feb 22 13:32:11 CET 2008 Jim Meyering <meyering@redhat.com>
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite,
not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
Move safewrite and saferead to a separate file. Move safewrite and saferead to a separate file.
* src/util.c (saferead, safewrite): Move function definitions to * src/util.c (saferead, safewrite): Move function definitions to
util-lib.c and include that .c file. util-lib.c and include that .c file.
......
...@@ -46,6 +46,17 @@ sc_avoid_if_before_free: ...@@ -46,6 +46,17 @@ sc_avoid_if_before_free:
{ echo '$(ME): found useless "if" before "free" above' 1>&2; \ { echo '$(ME): found useless "if" before "free" above' 1>&2; \
exit 1; } || : exit 1; } || :
# Avoid uses of write(2). Either switch to streams (fwrite), or use
# the safewrite wrapper.
sc_avoid_write:
@if $(CVS_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then \
grep '\<write *(' $$($(CVS_LIST_EXCEPT) | grep '\.c$$') && \
{ echo "$(ME): the above files use write;" \
" consider using the safewrite wrapper instead" \
1>&2; exit 1; } || :; \
else :; \
fi
sc_cast_of_argument_to_free: sc_cast_of_argument_to_free:
@grep -nE '\<free \(\(' $$($(CVS_LIST_EXCEPT)) && \ @grep -nE '\<free \(\(' $$($(CVS_LIST_EXCEPT)) && \
{ echo '$(ME): don'\''t cast free argument' 1>&2; \ { echo '$(ME): don'\''t cast free argument' 1>&2; \
......
...@@ -118,7 +118,7 @@ static void sig_handler(int sig) { ...@@ -118,7 +118,7 @@ static void sig_handler(int sig) {
return; return;
origerrno = errno; origerrno = errno;
r = write(sigwrite, &sigc, 1); r = safewrite(sigwrite, &sigc, 1);
if (r == -1) { if (r == -1) {
sig_errors++; sig_errors++;
sig_lasterrno = errno; sig_lasterrno = errno;
...@@ -1360,11 +1360,9 @@ static int qemudClientWriteBuf(struct qemud_server *server, ...@@ -1360,11 +1360,9 @@ static int qemudClientWriteBuf(struct qemud_server *server,
const char *data, int len) { const char *data, int len) {
int ret; int ret;
if (!client->tlssession) { if (!client->tlssession) {
if ((ret = write(client->fd, data, len)) == -1) { if ((ret = safewrite(client->fd, data, len)) == -1) {
if (errno != EAGAIN) { qemudLog (QEMUD_ERR, _("write: %s"), strerror (errno));
qemudLog (QEMUD_ERR, _("write: %s"), strerror (errno)); qemudDispatchClientFailure(server, client);
qemudDispatchClientFailure(server, client);
}
return -1; return -1;
} }
} else { } else {
......
...@@ -904,7 +904,7 @@ __virConfWriteFile(const char *filename, virConfPtr conf) ...@@ -904,7 +904,7 @@ __virConfWriteFile(const char *filename, virConfPtr conf)
goto error; goto error;
} }
ret = write(fd, buf->content, buf->use); ret = safewrite(fd, buf->content, buf->use);
close(fd); close(fd);
if (ret != (int) buf->use) { if (ret != (int) buf->use) {
virConfError(NULL, VIR_ERR_WRITE_FAILED, _("failed to save content"), 0); virConfError(NULL, VIR_ERR_WRITE_FAILED, _("failed to save content"), 0);
......
/* /*
* console.c: A dumb serial console client * console.c: A dumb serial console client
* *
* Copyright (C) 2007 Red Hat, Inc. * Copyright (C) 2007, 2008 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "console.h" #include "console.h"
#include "internal.h" #include "internal.h"
#include "util-lib.h"
/* ie Ctrl-] as per telnet */ /* ie Ctrl-] as per telnet */
#define CTRL_CLOSE_BRACKET '\35' #define CTRL_CLOSE_BRACKET '\35'
...@@ -161,7 +162,8 @@ int vshRunConsole(const char *tty) { ...@@ -161,7 +162,8 @@ int vshRunConsole(const char *tty) {
while (sent < got) { while (sent < got) {
int done; int done;
if ((done = write(destfd, buf + sent, got - sent)) <= 0) { if ((done = safewrite(destfd, buf + sent, got - sent))
<= 0) {
fprintf(stderr, _("failure writing output: %s\n"), fprintf(stderr, _("failure writing output: %s\n"),
strerror(errno)); strerror(errno));
goto cleanup; goto cleanup;
......
/* /*
* proxy_client.c: client side of the communication with the libvirt proxy. * proxy_client.c: client side of the communication with the libvirt proxy.
* *
* Copyright (C) 2006 Red Hat, Inc. * Copyright (C) 2006, 2008 Red Hat, Inc.
* *
* See COPYING.LIB for the License of this software * See COPYING.LIB for the License of this software
* *
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "internal.h" #include "internal.h"
#include "driver.h" #include "driver.h"
#include "proxy_internal.h" #include "proxy_internal.h"
#include "util.h"
#include "xen_unified.h" #include "xen_unified.h"
#define STANDALONE #define STANDALONE
...@@ -345,17 +346,10 @@ virProxyWriteClientSocket(int fd, const char *data, int len) { ...@@ -345,17 +346,10 @@ virProxyWriteClientSocket(int fd, const char *data, int len) {
if ((fd < 0) || (data == NULL) || (len < 0)) if ((fd < 0) || (data == NULL) || (len < 0))
return(-1); return(-1);
retry: ret = safewrite(fd, data, len);
ret = write(fd, data, len);
if (ret < 0) { if (ret < 0) {
if (errno == EINTR) {
if (debug > 0)
fprintf(stderr, "write socket %d, %d bytes interrupted\n",
fd, len);
goto retry;
}
fprintf(stderr, _("Failed to write to socket %d\n"), fd); fprintf(stderr, _("Failed to write to socket %d\n"), fd);
return(-1); return(-1);
} }
if (debug) if (debug)
fprintf(stderr, "wrote %d bytes to socket %d\n", fprintf(stderr, "wrote %d bytes to socket %d\n",
......
...@@ -1866,7 +1866,7 @@ static int qemudSaveConfig(virConnectPtr conn, ...@@ -1866,7 +1866,7 @@ static int qemudSaveConfig(virConnectPtr conn,
} }
towrite = strlen(xml); towrite = strlen(xml);
if (write(fd, xml, towrite) != towrite) { if (safewrite(fd, xml, towrite) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"cannot write config file %s: %s", "cannot write config file %s: %s",
vm->configFile, strerror(errno)); vm->configFile, strerror(errno));
...@@ -2089,7 +2089,7 @@ static int qemudSaveNetworkConfig(virConnectPtr conn, ...@@ -2089,7 +2089,7 @@ static int qemudSaveNetworkConfig(virConnectPtr conn,
} }
towrite = strlen(xml); towrite = strlen(xml);
if (write(fd, xml, towrite) != towrite) { if (safewrite(fd, xml, towrite) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"cannot write config file %s: %s", "cannot write config file %s: %s",
network->configFile, strerror(errno)); network->configFile, strerror(errno));
......
...@@ -539,11 +539,9 @@ static int qemudWaitForMonitor(virConnectPtr conn, ...@@ -539,11 +539,9 @@ static int qemudWaitForMonitor(virConnectPtr conn,
"console"); "console");
buf[sizeof(buf)-1] = '\0'; buf[sizeof(buf)-1] = '\0';
retry:
if (write(vm->logfile, buf, strlen(buf)) < 0) { if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
/* Log, but ignore failures to write logfile for VM */ /* Log, but ignore failures to write logfile for VM */
if (errno == EINTR)
goto retry;
qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s"), qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s"),
strerror(errno)); strerror(errno));
} }
...@@ -656,15 +654,15 @@ static int qemudStartVMDaemon(virConnectPtr conn, ...@@ -656,15 +654,15 @@ static int qemudStartVMDaemon(virConnectPtr conn,
tmp = argv; tmp = argv;
while (*tmp) { while (*tmp) {
if (write(vm->logfile, *tmp, strlen(*tmp)) < 0) if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s"), qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s"),
errno, strerror(errno)); errno, strerror(errno));
if (write(vm->logfile, " ", 1) < 0) if (safewrite(vm->logfile, " ", 1) < 0)
qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s"), qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s"),
errno, strerror(errno)); errno, strerror(errno));
tmp++; tmp++;
} }
if (write(vm->logfile, "\n", 1) < 0) if (safewrite(vm->logfile, "\n", 1) < 0)
qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s"), qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s"),
errno, strerror(errno)); errno, strerror(errno));
...@@ -733,11 +731,8 @@ static int qemudVMData(struct qemud_driver *driver ATTRIBUTE_UNUSED, ...@@ -733,11 +731,8 @@ static int qemudVMData(struct qemud_driver *driver ATTRIBUTE_UNUSED,
} }
buf[ret] = '\0'; buf[ret] = '\0';
retry: if (safewrite(vm->logfile, buf, ret) < 0) {
if (write(vm->logfile, buf, ret) < 0) {
/* Log, but ignore failures to write logfile for VM */ /* Log, but ignore failures to write logfile for VM */
if (errno == EINTR)
goto retry;
qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s"), qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s"),
strerror(errno)); strerror(errno));
} }
...@@ -1113,7 +1108,7 @@ qemudEnableIpForwarding(void) ...@@ -1113,7 +1108,7 @@ qemudEnableIpForwarding(void)
if ((fd = open(PROC_IP_FORWARD, O_WRONLY|O_TRUNC)) == -1) if ((fd = open(PROC_IP_FORWARD, O_WRONLY|O_TRUNC)) == -1)
return 0; return 0;
if (write(fd, "1\n", 2) < 0) if (safewrite(fd, "1\n", 2) < 0)
ret = 0; ret = 0;
close (fd); close (fd);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "test.h" #include "test.h"
#include "xml.h" #include "xml.h"
#include "buf.h" #include "buf.h"
#include "util.h"
#include "uuid.h" #include "uuid.h"
/* Flags that determine the action to take on a shutdown or crash of a domain /* Flags that determine the action to take on a shutdown or crash of a domain
...@@ -1293,19 +1294,19 @@ static int testDomainSave(virDomainPtr domain, ...@@ -1293,19 +1294,19 @@ static int testDomainSave(virDomainPtr domain,
return (-1); return (-1);
} }
len = strlen(xml); len = strlen(xml);
if (write(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) != sizeof(TEST_SAVE_MAGIC)) { if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
"cannot write header"); "cannot write header");
close(fd); close(fd);
return (-1); return (-1);
} }
if (write(fd, (char*)&len, sizeof(len)) != sizeof(len)) { if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
"cannot write metadata length"); "cannot write metadata length");
close(fd); close(fd);
return (-1); return (-1);
} }
if (write(fd, xml, len) != len) { if (safewrite(fd, xml, len) < 0) {
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
"cannot write metadata"); "cannot write metadata");
free(xml); free(xml);
...@@ -1398,7 +1399,7 @@ static int testDomainCoreDump(virDomainPtr domain, ...@@ -1398,7 +1399,7 @@ static int testDomainCoreDump(virDomainPtr domain,
"cannot save domain core"); "cannot save domain core");
return (-1); return (-1);
} }
if (write(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) != sizeof(TEST_SAVE_MAGIC)) { if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR, testError(domain->conn, domain, NULL, VIR_ERR_INTERNAL_ERROR,
"cannot write header"); "cannot write header");
close(fd); close(fd);
......
...@@ -46,9 +46,10 @@ ...@@ -46,9 +46,10 @@
#include <readline/history.h> #include <readline/history.h>
#endif #endif
#include "buf.h"
#include "console.h" #include "console.h"
#include "util.h" #include "util.h"
#include "buf.h" #include "util-lib.h"
static char *progname; static char *progname;
...@@ -6170,7 +6171,7 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, va_list ...@@ -6170,7 +6171,7 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, va_list
snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf), "\n"); snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf), "\n");
/* write log */ /* write log */
if (write(ctl->log_fd, msg_buf, strlen(msg_buf)) == -1) { if (safewrite(ctl->log_fd, msg_buf, strlen(msg_buf)) < 0) {
vshCloseLogFile(ctl); vshCloseLogFile(ctl);
vshError(ctl, FALSE, "%s", _("failed to write the log file")); vshError(ctl, FALSE, "%s", _("failed to write the log file"));
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册