summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-06-08 15:47:34 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-06-10 10:17:38 -0400
commit06247775aa9c49ffce72827921eb45e2d04c6aa1 (patch)
treec3e53abf07faa3c8e161cff30746d54af6a78791 /src/util
parente5196fd7da44e4ae04ab8b5d2e7191167762cf0b (diff)
downloadsssd-06247775aa9c49ffce72827921eb45e2d04c6aa1.tar.gz
sssd-06247775aa9c49ffce72827921eb45e2d04c6aa1.tar.bz2
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')
-rw-r--r--src/util/backup_file.c4
-rw-r--r--src/util/find_uid.c13
-rw-r--r--src/util/server.c52
3 files changed, 57 insertions, 12 deletions
diff --git a/src/util/backup_file.c b/src/util/backup_file.c
index cf9ddf30..99079327 100644
--- a/src/util/backup_file.c
+++ b/src/util/backup_file.c
@@ -86,7 +86,7 @@ int backup_file(const char *src_file, int dbglvl)
while (1) {
num = read(src_fd, buf, BUFFER_SIZE);
if (num < 0) {
- if (errno == EINTR) continue;
+ if (errno == EINTR || errno == EAGAIN) continue;
ret = errno;
DEBUG(dbglvl, ("Error (%d [%s]) reading from source %s\n",
ret, strerror(ret), src_file));
@@ -101,7 +101,7 @@ int backup_file(const char *src_file, int dbglvl)
errno = 0;
num = write(dst_fd, &buf[pos], count);
if (num < 0) {
- if (errno == EINTR) continue;
+ if (errno == EINTR || errno == EAGAIN) continue;
ret = errno;
DEBUG(dbglvl, ("Error (%d [%s]) writing to destination %s\n",
ret, strerror(ret), dst_file));
diff --git a/src/util/find_uid.c b/src/util/find_uid.c
index 965966ef..952aeea4 100644
--- a/src/util/find_uid.c
+++ b/src/util/find_uid.c
@@ -100,10 +100,15 @@ static errno_t get_uid_from_pid(const pid_t pid, uid_t *uid)
DEBUG(1, ("open failed [%d][%s].\n", errno, strerror(errno)));
return errno;
}
- ret = read(fd, buf, BUFSIZE);
- if (ret == -1) {
- DEBUG(1, ("read failed [%d][%s].\n", errno, strerror(errno)));
- return errno;
+
+ while ((ret = read(fd, buf, BUFSIZE)) != 0) {
+ if (ret == -1) {
+ if (errno == EINTR || errno == EAGAIN) {
+ continue;
+ }
+ DEBUG(1, ("read failed [%d][%s].\n", errno, strerror(errno)));
+ return errno;
+ }
}
ret = close(fd);
diff --git a/src/util/server.c b/src/util/server.c
index 007b3624..8f5b4414 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;
}