From ed3cd7573600bf8be2bda01ad75da8bae2f589fb Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 27 Oct 2011 16:24:30 -0500 Subject: libalpm/util: use low-level I/O for copyfile and checksum routines This removes an unnecessary level of buffering. We are not doing line-based I/O here, so we can read in blocks of 8K at a time directly from the file. Signed-off-by: Dan McGee --- lib/libalpm/util.c | 116 ++++++++++++++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 55 deletions(-) diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 5e32280f..5056b98a 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -125,46 +125,50 @@ int _alpm_makepath_mode(const char *path, mode_t mode) int _alpm_copyfile(const char *src, const char *dest) { - FILE *in, *out; - size_t len; char *buf; - int ret = 0; + int in, out, ret = 1; + ssize_t nread; + struct stat st; - in = fopen(src, "rb"); - if(in == NULL) { - return 1; - } - out = fopen(dest, "wb"); - if(out == NULL) { - fclose(in); - return 1; + MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); + + OPEN(in, src, O_RDONLY); + do { + out = open(dest, O_WRONLY | O_CREAT, 0000); + } while(out == -1 && errno == EINTR); + if(in < 0 || out < 0) { + goto cleanup; } - MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, ret = 1; goto cleanup); + if(fstat(in, &st) || fchmod(out, st.st_mode)) { + goto cleanup; + } /* do the actual file copy */ - while((len = fread(buf, 1, ALPM_BUFFER_SIZE, in))) { - size_t nwritten = 0; - nwritten = fwrite(buf, 1, len, out); - if((nwritten != len) || ferror(out)) { - ret = -1; - goto cleanup; + while((nread = read(in, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { + ssize_t nwrite = 0; + if(nread < 0) { + continue; } + do { + nwrite = write(out, buf + nwrite, nread); + if(nwrite >= 0) { + nread -= nwrite; + } else if(errno != EINTR) { + goto cleanup; + } + } while(nread > 0); } - - /* chmod dest to permissions of src */ - struct stat statbuf; - if(!fstat(fileno(in), &statbuf)) { - fchmod(fileno(out), statbuf.st_mode); - } else { - /* stat was unsuccessful */ - ret = 1; - } + ret = 0; cleanup: - fclose(in); - fclose(out); free(buf); + if(in >= 0) { + CLOSE(in); + } + if(out >= 0) { + CLOSE(out); + } return ret; } @@ -730,49 +734,51 @@ int _alpm_lstat(const char *path, struct stat *buf) #ifdef HAVE_LIBSSL static int md5_file(const char *path, unsigned char output[16]) { - FILE *f; - size_t n; MD5_CTX ctx; unsigned char *buf; + ssize_t n; + int fd; - CALLOC(buf, ALPM_BUFFER_SIZE, sizeof(unsigned char), return 1); + MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); - if((f = fopen(path, "rb")) == NULL) { + OPEN(fd, path, O_RDONLY); + if(fd < 0) { free(buf); return 1; } MD5_Init(&ctx); - while((n = fread(buf, 1, ALPM_BUFFER_SIZE, f)) > 0) { + while((n = read(fd, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { + if(n < 0) { + continue; + } MD5_Update(&ctx, buf, n); } - MD5_Final(output, &ctx); - - memset(&ctx, 0, sizeof(MD5_CTX)); + CLOSE(fd); free(buf); - if(ferror(f) != 0) { - fclose(f); + if(n < 0) { return 2; } - fclose(f); + MD5_Final(output, &ctx); return 0; } /* third param is so we match the PolarSSL definition */ static int sha2_file(const char *path, unsigned char output[32], int is224) { - FILE *f; - size_t n; SHA256_CTX ctx; unsigned char *buf; + ssize_t n; + int fd; - CALLOC(buf, ALPM_BUFFER_SIZE, sizeof(unsigned char), return 1); + MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); - if((f = fopen(path, "rb")) == NULL) { + OPEN(fd, path, O_RDONLY); + if(fd < 0) { free(buf); return 1; } @@ -783,7 +789,10 @@ static int sha2_file(const char *path, unsigned char output[32], int is224) SHA256_Init(&ctx); } - while((n = fread(buf, 1, ALPM_BUFFER_SIZE, f)) > 0) { + while((n = read(fd, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { + if(n < 0) { + continue; + } if(is224) { SHA224_Update(&ctx, buf, n); } else { @@ -791,21 +800,18 @@ static int sha2_file(const char *path, unsigned char output[32], int is224) } } - if(is224) { - SHA224_Final(output, &ctx); - } else { - SHA256_Final(output, &ctx); - } - - memset(&ctx, 0, sizeof(SHA256_CTX)); + CLOSE(fd); free(buf); - if(ferror(f) != 0) { - fclose(f); + if(n < 0) { return 2; } - fclose(f); + if(is224) { + SHA224_Final(output, &ctx); + } else { + SHA256_Final(output, &ctx); + } return 0; } #endif -- cgit v1.2.3-70-g09d2