From 719e8eee03e8d62c20c8378a8324778fcaa19788 Mon Sep 17 00:00:00 2001 From: Corey Farrell Date: Wed, 20 Dec 2017 22:11:48 -0500 Subject: app_voicemail: Fix file copy error handling. Fix error where input/output file descriptors would be closed multiple times. Change-Id: Iba5140b60cb7de79e3d5d92be3c256947aa99da9 --- apps/app_voicemail.c | 75 ++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 4a0dacc05..4bd450327 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -4630,49 +4630,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; } /*! -- cgit v1.2.3