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/sss_client/common.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/sss_client/common.c')
-rw-r--r-- | src/sss_client/common.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/src/sss_client/common.c b/src/sss_client/common.c index 237b90aba..a4856e088 100644 --- a/src/sss_client/common.c +++ b/src/sss_client/common.c @@ -123,6 +123,7 @@ static enum nss_status sss_nss_send_req(enum sss_cli_command cmd, return NSS_STATUS_UNAVAIL; } + errno = 0; if (datasent < SSS_NSS_HEADER_SIZE) { res = write(sss_cli_sd, (char *)header + datasent, @@ -133,8 +134,15 @@ static enum nss_status sss_nss_send_req(enum sss_cli_command cmd, (const char *)rd->data + rdsent, rd->len - rdsent); } + error = errno; if ((res == -1) || (res == 0)) { + if ((error == EINTR) || error == EAGAIN) { + /* If the write was interrupted, go back through + * the loop and try again + */ + continue; + } /* Write failed */ sss_cli_close_socket(); @@ -217,6 +225,7 @@ static enum nss_status sss_nss_recv_rep(enum sss_cli_command cmd, return NSS_STATUS_UNAVAIL; } + errno = 0; if (datarecv < SSS_NSS_HEADER_SIZE) { res = read(sss_cli_sd, (char *)header + datarecv, @@ -227,8 +236,15 @@ static enum nss_status sss_nss_recv_rep(enum sss_cli_command cmd, (char *)(*buf) + bufrecv, header[0] - datarecv); } + error = errno; if ((res == -1) || (res == 0)) { + if ((error == EINTR) || error == EAGAIN) { + /* If the read was interrupted, go back through + * the loop and try again + */ + continue; + } /* Read failed. I think the only useful thing * we can do here is just return -1 and fail |