From d37c8beac5e753bc3417863174f8cd7abe27fa3c Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Sat, 24 Oct 2009 13:16:02 -0400 Subject: [PATCH] Improve error handling when writing --- src/dmaster.c | 3 ++- src/homedir.c | 20 ++++++++++---------- src/op-adduser.c | 4 +++- src/op-mail.c | 7 +++++-- src/util.c | 6 ++++-- src/util.h | 2 +- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/dmaster.c b/src/dmaster.c index 2e99c5786..63f0e83a1 100644 --- a/src/dmaster.c +++ b/src/dmaster.c @@ -85,7 +85,8 @@ static void setup_pidfile(void) { pidlen = snprintf(pidbuf, sizeof(pidbuf), "%d\n", getpid()); if (pidlen >= sizeof(pidbuf)) fatal("pid too long"); - full_write(fd, pidbuf, pidlen); + if (full_write(fd, pidbuf, pidlen)) + fatalpe("write: %s", pidfile); } static void setup_daemon(void) { diff --git a/src/homedir.c b/src/homedir.c index 9d544863a..23384ab61 100644 --- a/src/homedir.c +++ b/src/homedir.c @@ -91,8 +91,8 @@ int ceo_create_home(char *homedir, char *skel, uid_t uid, gid_t gid, char *acces warnpe("read"); break; } - if (write(destfd, buf, bytes) < 0) { - warnpe("write"); + if (full_write(destfd, buf, bytes)) { + warnpe("write: %s", src); break; } } @@ -131,25 +131,25 @@ int ceo_create_home(char *homedir, char *skel, uid_t uid, gid_t gid, char *acces closedir(skeldir); - if (email && strlen(email) >0) { - char dest[PATH_MAX]; - snprintf(dest, sizeof(dest), "%s/%s", homedir, ".forward"); + if (email && *email) { + char dest[PATH_MAX]; + snprintf(dest, sizeof(dest), "%s/%s", homedir, ".forward"); int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, 0644); - if (write(destfd, email, sizeof(char)*strlen(email)) < 0) { - warnpe ("write"); - } + + if (full_write(destfd, email, strlen(email))) + warnpe("write: %s", dest); if (fchown(destfd, uid, gid)) errorpe("chown: %s", dest); - close(destfd); + close(destfd); } if (chown(homedir, uid, gid)) { errorpe("failed to chown %s", homedir); return -1; } - + umask(mask); return 0; diff --git a/src/op-adduser.c b/src/op-adduser.c index 58c87171b..c7bf2dda4 100644 --- a/src/op-adduser.c +++ b/src/op-adduser.c @@ -272,7 +272,9 @@ void cmd_adduser(void) { strbuf_grow(&out, ceo__add_user_response__get_packed_size(out_proto)); strbuf_setlen(&out, ceo__add_user_response__pack(out_proto, (uint8_t *)out.buf)); - full_write(STDOUT_FILENO, out.buf, out.len); + + if (full_write(STDOUT_FILENO, out.buf, out.len)) + fatalpe("write: stdout"); ceo__add_user__free_unpacked(in_proto, &protobuf_c_default_allocator); response_delete(out_proto); diff --git a/src/op-mail.c b/src/op-mail.c index 2d10cf774..0947e55e7 100644 --- a/src/op-mail.c +++ b/src/op-mail.c @@ -150,7 +150,8 @@ static int32_t update_mail(Ceo__UpdateMail *in, Ceo__UpdateMailResponse *out, ch struct strbuf file_contents = STRBUF_INIT; strbuf_addf(&file_contents, "%s\n", in->forward); - full_write(fd, file_contents.buf, file_contents.len); + if (full_write(fd, file_contents.buf, file_contents.len)) + response_message(out, errno, "write: %s: %s", path, strerror(errno)); strbuf_release(&file_contents); @@ -190,7 +191,9 @@ void cmd_update_mail(void) { strbuf_grow(&out, ceo__update_mail_response__get_packed_size(out_proto)); strbuf_setlen(&out, ceo__update_mail_response__pack(out_proto, (uint8_t *)out.buf)); - full_write(STDOUT_FILENO, out.buf, out.len); + + if (full_write(STDOUT_FILENO, out.buf, out.len)) + fatalpe("write: stdout"); ceo__update_mail__free_unpacked(in_proto, &protobuf_c_default_allocator); response_delete(out_proto); diff --git a/src/util.c b/src/util.c index e693b197a..be862d989 100644 --- a/src/util.c +++ b/src/util.c @@ -162,15 +162,17 @@ int spawnv(const char *path, char *const argv[]) { return status; } -void full_write(int fd, const void *buf, size_t count) { +int full_write(int fd, const void *buf, size_t count) { ssize_t total = 0; while (total < count) { ssize_t wcount = write(fd, (char *)buf + total, count - total); if (wcount < 0) - fatalpe("write"); + return wcount; total += wcount; } + + return 0; } int spawnvem(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr) { diff --git a/src/util.h b/src/util.h index c633902a1..489dff151 100644 --- a/src/util.h +++ b/src/util.h @@ -29,7 +29,7 @@ int spawnv(const char *path, char *const *argv); int spawnv_msg(const char *path, char *const *argv, const struct strbuf *output); int spawnvem(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr); int spawnvemu(const char *path, char *const *argv, char *const *envp, const struct strbuf *output, struct strbuf *input, int cap_stderr, char *user); -void full_write(int fd, const void *buf, size_t count); +int full_write(int fd, const void *buf, size_t count); ssize_t full_read(int fd, void *buf, size_t len); FILE *fopenat(DIR *d, const char *path, int flags); void make_env(char **envp, ...);