concat: Use plain read/write instead of buffered stdio
If we are just copying data from one file to another, we don't need to fill a complete buffer, just read a chunk at a time, and write it to the output.
This commit is contained in:
committed by
Anselm R Garbe
parent
9a3b12525b
commit
3276fbea1c
@@ -1,19 +1,23 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../text.h"
|
||||
#include "../util.h"
|
||||
|
||||
void
|
||||
concat(FILE *fp1, const char *s1, FILE *fp2, const char *s2)
|
||||
int
|
||||
concat(int f1, const char *s1, int f2, const char *s2)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
size_t n;
|
||||
ssize_t n;
|
||||
|
||||
while ((n = fread(buf, 1, sizeof(buf), fp1))) {
|
||||
fwrite(buf, 1, n, fp2);
|
||||
|
||||
if (feof(fp1) || ferror(fp1) || ferror(fp2))
|
||||
break;
|
||||
while ((n = read(f1, buf, sizeof(buf))) > 0) {
|
||||
if (writeall(f2, buf, n) < 0) {
|
||||
weprintf("write %s:", s2);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
if (n < 0) {
|
||||
weprintf("read %s:", s1);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
55
libutil/cp.c
55
libutil/cp.c
@@ -12,7 +12,6 @@
|
||||
#include <utime.h>
|
||||
|
||||
#include "../fs.h"
|
||||
#include "../text.h"
|
||||
#include "../util.h"
|
||||
|
||||
int cp_aflag = 0;
|
||||
@@ -27,7 +26,7 @@ int
|
||||
cp(const char *s1, const char *s2, int depth)
|
||||
{
|
||||
DIR *dp;
|
||||
FILE *f1, *f2;
|
||||
int f1, f2;
|
||||
struct dirent *d;
|
||||
struct stat st;
|
||||
struct timespec times[2];
|
||||
@@ -113,46 +112,38 @@ cp(const char *s1, const char *s2, int depth)
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!(f1 = fopen(s1, "r"))) {
|
||||
weprintf("fopen %s:", s1);
|
||||
if ((f1 = open(s1, O_RDONLY)) < 0) {
|
||||
weprintf("open %s:", s1);
|
||||
cp_status = 1;
|
||||
return 0;
|
||||
}
|
||||
if (!(f2 = fopen(s2, "w"))) {
|
||||
if (cp_fflag) {
|
||||
if (unlink(s2) < 0 && errno != ENOENT) {
|
||||
weprintf("unlink %s:", s2);
|
||||
cp_status = 1;
|
||||
fclose(f1);
|
||||
return 0;
|
||||
} else if (!(f2 = fopen(s2, "w"))) {
|
||||
weprintf("fopen %s:", s2);
|
||||
cp_status = 1;
|
||||
fclose(f1);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
weprintf("fopen %s:", s2);
|
||||
if ((f2 = creat(s2, st.st_mode)) < 0 && cp_fflag) {
|
||||
if (unlink(s2) < 0 && errno != ENOENT) {
|
||||
weprintf("unlink %s:", s2);
|
||||
cp_status = 1;
|
||||
fclose(f1);
|
||||
close(f1);
|
||||
return 0;
|
||||
}
|
||||
f2 = creat(s2, st.st_mode);
|
||||
}
|
||||
if (f2 < 0) {
|
||||
weprintf("creat %s:", s2);
|
||||
cp_status = 1;
|
||||
close(f1);
|
||||
return 0;
|
||||
}
|
||||
if (concat(f1, s1, f2, s2) < 0) {
|
||||
cp_status = 1;
|
||||
close(f1);
|
||||
close(f2);
|
||||
return 0;
|
||||
}
|
||||
concat(f1, s1, f2, s2);
|
||||
|
||||
/* preserve permissions by default */
|
||||
fchmod(fileno(f2), st.st_mode);
|
||||
fchmod(f2, st.st_mode);
|
||||
|
||||
if (fclose(f2) == EOF) {
|
||||
weprintf("fclose %s:", s2);
|
||||
cp_status = 1;
|
||||
return 0;
|
||||
}
|
||||
if (fclose(f1) == EOF) {
|
||||
weprintf("fclose %s:", s1);
|
||||
cp_status = 1;
|
||||
return 0;
|
||||
}
|
||||
close(f1);
|
||||
close(f2);
|
||||
}
|
||||
|
||||
if (cp_aflag || cp_pflag) {
|
||||
|
Reference in New Issue
Block a user