diff options
author | Stephen Gallagher <sgallagh@redhat.com> | 2010-06-08 15:47:34 -0400 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2010-06-10 10:17:38 -0400 |
commit | 06247775aa9c49ffce72827921eb45e2d04c6aa1 (patch) | |
tree | c3e53abf07faa3c8e161cff30746d54af6a78791 /src/util/server.c | |
parent | e5196fd7da44e4ae04ab8b5d2e7191167762cf0b (diff) | |
download | sssd-06247775aa9c49ffce72827921eb45e2d04c6aa1.tar.gz sssd-06247775aa9c49ffce72827921eb45e2d04c6aa1.tar.xz sssd-06247775aa9c49ffce72827921eb45e2d04c6aa1.zip |
Properly handle read() and write() throughout the SSSD
We need to guarantee at all times that reads and writes complete
successfully. This means that they must be checked for returning
EINTR and EAGAIN, and all writes must be wrapped in a loop to
ensure that they do not truncate their output.
Diffstat (limited to 'src/util/server.c')
-rw-r--r-- | src/util/server.c | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/src/util/server.c b/src/util/server.c index 007b36241..8f5b44146 100644 --- a/src/util/server.c +++ b/src/util/server.c @@ -104,6 +104,10 @@ int pidfile(const char *path, const char *name) char *file; int fd; int ret, err; + ssize_t len; + ssize_t size; + ssize_t written; + ssize_t pidlen = sizeof(pid_str - 1); file = talloc_asprintf(NULL, "%s/%s.pid", path, name); if (!file) { @@ -114,9 +118,30 @@ int pidfile(const char *path, const char *name) err = errno; if (fd != -1) { - pid_str[sizeof(pid_str) -1] = '\0'; - ret = read(fd, pid_str, sizeof(pid_str) -1); - if (ret > 0) { + pid_str[pidlen] = '\0'; + + + while ((ret = read(fd, pid_str + len, pidlen - len)) != 0) { + if (ret == -1) { + if (errno == EINTR || errno == EAGAIN) { + continue; + } + DEBUG(1, ("read failed [%d][%s].\n", errno, strerror(errno))); + break; + } else if (ret > 0) { + len += ret; + if (len > pidlen) { + DEBUG(1, ("read too much, this should never happen.\n")); + break; + } + continue; + } else { + DEBUG(1, ("unexpected return code of read [%d].\n", ret)); + break; + } + } + + if (ret == 0) { /* let's check the pid */ pid = (pid_t)atoi(pid_str); @@ -159,10 +184,25 @@ int pidfile(const char *path, const char *name) memset(pid_str, 0, sizeof(pid_str)); snprintf(pid_str, sizeof(pid_str) -1, "%u\n", (unsigned int) getpid()); + size = strlen(pid_str); + + written = 0; + while (written < size) { + ret = write(fd, pid_str+written, size-written); + if (ret == -1) { + err = errno; + if (err == EINTR || err == EAGAIN) { + continue; + } + DEBUG(1, ("write failed [%d][%s]\n", err, strerror(err))); + break; + } + else { + written += ret; + } + } - ret = write(fd, pid_str, strlen(pid_str)); - err = errno; - if (ret != strlen(pid_str)) { + if (written != size) { close(fd); return err; } |