libite: Simplify and fix another memleak in copyfile()

- Simplify: reduce indentation depth
- Always check for error condition first, cleaner code
- Make sure buffer is always freed, use same exit everyhere
- Use readable, but still short, local variable names

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2014-04-12 16:11:59 +02:00
1 parent 7ada824e3e
commit 9f91b4c050
1 file changed
+42 -48
+42 -48
View File
@@ -34,7 +34,7 @@
#include "lite.h" #include "lite.h"
static int __isdir_and_append_filename(char *src, char **dst); static int adjust_target(char *src, char **dst);
/** /**
* copyfile - Copy a file to another. * copyfile - Copy a file to another.
@@ -58,71 +58,67 @@ static int __isdir_and_append_filename(char *src, char **dst);
ssize_t copyfile(char *src, char *dst, int len, int sym) ssize_t copyfile(char *src, char *dst, int len, int sym)
{ {
char *buffer; char *buffer;
int s, d, n, result, isdir = 0, saved_errno = 0; int in, out, isdir = 0, saved_errno = 0;
ssize_t size = 0; ssize_t num, size = 0;
errno = 0; /* Reset before leaving this function. */ errno = 0;
// fprintf (stderr, "%s() src: %s, dst: %s, len: %d\n", __func__, src, dst, len);
buffer = malloc(BUFSIZ); buffer = malloc(BUFSIZ);
if (!buffer) if (!buffer)
return 0; return 0;
if (fisdir(src)) { if (fisdir(src)) {
errno = EISDIR; /* Error: source is a directory */ saved_errno = EISDIR; /* Error: source is a directory */
return 0; goto exit;
} }
/* Check if target is a directory, then append the src base filename. */ /* Check if target is a directory, then append src filename. */
isdir = __isdir_and_append_filename(src, &dst); isdir = adjust_target(src, &dst);
if (sym) { if (sym) {
if ((size = readlink(src, buffer, BUFSIZ)) > 0) { size = readlink(src, buffer, BUFSIZ);
if (size > 0) {
if (size >= (ssize_t) BUFSIZ) { if (size >= (ssize_t) BUFSIZ) {
free(buffer); saved_errno = ENOBUFS;
if (isdir) goto exit;
free(dst);
errno = ENOBUFS;
return 0;
} }
buffer[size] = 0; buffer[size] = 0;
result = !symlink(buffer, dst); size = !symlink(buffer, dst);
free(buffer); goto exit;
if (isdir)
free(dst);
return result;
} }
} }
/* Len == 0 means copy entire file */ /* 0: copy entire file */
if (len == 0) { if (len == 0)
/* XXX: This feels a bit unsafe, but 2047 MiB may be sufficient for us. len = INT_MAX; /* XXX: 2047 MiB should sufficient ... */
* --Jocke 2008-08-11 */
len = INT_MAX;
}
if ((s = open(src, O_RDONLY)) >= 0) { in = open(src, O_RDONLY);
if ((d = open(dst, O_WRONLY | O_CREAT | O_TRUNC, fmode(src))) >= 0) { if (in < 0) {
do {
int clen = len > BUFSIZ ? BUFSIZ : len;
if ((n = read(s, buffer, clen)) > 0)
size += write(d, buffer, n);
len -= clen;
} while (len > 0 && n == BUFSIZ);
close(d);
} else {
saved_errno = errno;
}
close(s);
} else {
saved_errno = errno; saved_errno = errno;
goto exit;
} }
out = open(dst, O_WRONLY | O_CREAT | O_TRUNC, fmode(src));
if (out < 0) {
close(in);
saved_errno = errno;
goto exit;
}
do {
int clen = len > BUFSIZ ? BUFSIZ : len;
num = read(in, buffer, clen);
if (num > 0)
size += write(out, buffer, num);
len -= clen;
} while (len > 0 && num == BUFSIZ);
close(out);
close(in);
exit:
free(buffer); free(buffer);
if (isdir) if (isdir)
free(dst); free(dst);
@@ -152,7 +148,7 @@ int movefile(char *src, char *dst)
int isdir, result = 0; int isdir, result = 0;
/* Check if target is a directory, then append the src base filename. */ /* Check if target is a directory, then append the src base filename. */
isdir = __isdir_and_append_filename(src, &dst); isdir = adjust_target(src, &dst);
if (rename(src, dst)) { if (rename(src, dst)) {
if (errno == EXDEV) { if (errno == EXDEV) {
@@ -274,7 +270,7 @@ size_t fsendfile (FILE *out, FILE *in, size_t sz)
} }
/* Tests if dst is a directory, if so, reallocates dst and appends src filename returning 1 */ /* Tests if dst is a directory, if so, reallocates dst and appends src filename returning 1 */
static int __isdir_and_append_filename(char *src, char **dst) static int adjust_target(char *src, char **dst)
{ {
int isdir = 0; int isdir = 0;
@@ -287,7 +283,6 @@ static int __isdir_and_append_filename(char *src, char **dst)
else else
ptr++; ptr++;
// fprintf (stderr, "Yes %s is a dir --> add %s\n", *dst, ptr);
tmp = malloc(strlen(*dst) + strlen(ptr) + 2); tmp = malloc(strlen(*dst) + strlen(ptr) + 2);
if (!tmp) { if (!tmp) {
errno = EISDIR; errno = EISDIR;
@@ -299,7 +294,6 @@ static int __isdir_and_append_filename(char *src, char **dst)
sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr); sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr);
*dst = tmp; *dst = tmp;
// fprintf (stderr, "NEW DST:%s\n", *dst);
} }
return isdir; return isdir;