Skip to content

Instantly share code, notes, and snippets.

@pandax381
Created July 4, 2016 08:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pandax381/fc3260682f0aa16f69c86fffb8d89e9a to your computer and use it in GitHub Desktop.
Save pandax381/fc3260682f0aa16f69c86fffb8d89e9a to your computer and use it in GitHub Desktop.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define BLOCKSIZ 512
#define WRITABLEN(x) (BLOCKSIZ*((x)/BLOCKSIZ))
static ssize_t
writen (int fd, const void *buf, size_t n) {
size_t done = 0;
ssize_t ret;
while (done < n) {
ret = write(fd, (caddr_t)buf + done, n - done);
if (ret == -1) {
if (errno == EINTR) {
continue;
}
if (errno == EAGAIN || errno == EWOULDBLOCK) {
return (ssize_t)done;
}
return -1;
}
done += ret;
}
return (ssize_t)done;
}
static void
usage (void) {
fprintf(stderr, "usage: directcopy [-b buffer-num] [-n] [-s] source-file destination-file\n");
}
int
main (int argc, char *argv[]) {
char *buf;
int opt, num = 1024, nodirect = 0, syncmode = 0, flags;
int src, dst1, dst2;
size_t size, len = 0;
ssize_t n;
off_t cur = 0;
while ((opt = getopt(argc, argv, "b:ns")) != -1) {
switch (opt) {
case 'b':
if ((num = atoi(optarg)) <= 0) {
usage();
return -1;
}
break;
case 'n':
nodirect = 1;
break;
case 's':
syncmode = 1;
break;
default:
usage();
return -1;
}
}
if (argc - optind != 2) {
usage();
return -1;
}
size = BLOCKSIZ * num;
if ((errno = posix_memalign((void **)&buf, BLOCKSIZ, size)) != 0) {
perror("posix_memalign");
return -1;
}
flags = nodirect ? 0 : O_DIRECT;
if ((src = open(argv[optind], O_RDONLY | flags)) == -1) {
perror("open");
free(buf);
return -1;
}
flags = (nodirect ? 0 : O_DIRECT) | (syncmode ? O_SYNC : 0);
if ((dst1 = open(argv[optind+1], O_WRONLY | O_CREAT | O_TRUNC | flags, 0664)) == -1) {
perror("open");
close(src);
free(buf);
return -1;
}
flags = syncmode ? O_SYNC : 0;
if ((dst2 = open(argv[optind+1], O_WRONLY | flags)) == -1) {
perror("open");
close(dst1);
close(src);
free(buf);
return -1;
}
while (1) {
if (size - len > 0) {
if ((n = read(src, buf + len, size - len)) == -1) {
perror("read");
break;
}
if (!n) {
if (len) {
if ((cur = lseek(dst1, 0, SEEK_CUR)) == (off_t)-1) {
perror("lseek");
break;
}
if (lseek(dst2, cur, SEEK_SET) == (off_t)-1) {
perror("lseek");
break;
}
/* normal io */
if ((n = writen(dst2, buf, len)) == -1) {
perror("write");
break;
}
len -= n;
fprintf(stderr, "write: %d, len: %d\n", n, len);
}
break;
}
}
len += n;
fprintf(stderr, "read: %d, len: %d\n", n, len);
/* direct io */
if ((n = writen(dst1, buf, WRITABLEN(len))) == -1) {
perror("write");
break;
}
len -= n;
fprintf(stderr, "write: %d, len: %d\n", n, len);
}
fprintf(stderr, "len: %d\n", len);
close(dst2);
close(dst1);
close(src);
free(buf);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment