diff options
author | Corey Farrell <git@cfware.com> | 2017-12-20 22:11:48 -0500 |
---|---|---|
committer | Corey Farrell <git@cfware.com> | 2017-12-20 22:19:29 -0500 |
commit | f2f51ff4eaed436d1585d9832e0559b1097edca8 (patch) | |
tree | d735c8dcb469b58c3776ceed56cc02e5e030fc75 /apps/app_voicemail.c | |
parent | 4815be9aeb17afd650af184a272d73b63ff98774 (diff) |
app_voicemail: Fix file copy error handling.
Fix error where input/output file descriptors would be closed multiple
times.
Change-Id: Iba5140b60cb7de79e3d5d92be3c256947aa99da9
Diffstat (limited to 'apps/app_voicemail.c')
-rw-r--r-- | apps/app_voicemail.c | 75 |
1 files changed, 41 insertions, 34 deletions
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index af2174ba9..1c54e2e97 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -4647,49 +4647,56 @@ static int copy(char *infile, char *outfile) { int ifd; int ofd; - int res; + int res = -1; int len; char buf[4096]; #ifdef HARDLINK_WHEN_POSSIBLE /* Hard link if possible; saves disk space & is faster */ - if (link(infile, outfile)) { + if (!link(infile, outfile)) { + return 0; + } #endif - if ((ifd = open(infile, O_RDONLY)) < 0) { - ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno)); - return -1; + + if ((ifd = open(infile, O_RDONLY)) < 0) { + ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno)); + return -1; + } + + if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) { + ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno)); + close(ifd); + return -1; + } + + for (;;) { + int wrlen; + + len = read(ifd, buf, sizeof(buf)); + if (!len) { + res = 0; + break; } - if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) { - ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno)); - close(ifd); - return -1; + + if (len < 0) { + ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno)); + break; + } + + wrlen = write(ofd, buf, len); + if (errno == ENOMEM || errno == ENOSPC || wrlen != len) { + ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, wrlen, len, strerror(errno)); + break; } - do { - len = read(ifd, buf, sizeof(buf)); - if (len < 0) { - ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno)); - close(ifd); - close(ofd); - unlink(outfile); - } else if (len) { - res = write(ofd, buf, len); - if (errno == ENOMEM || errno == ENOSPC || res != len) { - ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno)); - close(ifd); - close(ofd); - unlink(outfile); - } - } - } while (len); - close(ifd); - close(ofd); - return 0; -#ifdef HARDLINK_WHEN_POSSIBLE - } else { - /* Hard link succeeded */ - return 0; } -#endif + + close(ifd); + close(ofd); + if (res) { + unlink(outfile); + } + + return res; } /*! |