Skip to content

Instantly share code, notes, and snippets.

@pandax381
Created July 4, 2016 08:38
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/e041c24babf9747613b82c2ccd0dee98 to your computer and use it in GitHub Desktop.
Save pandax381/e041c24babf9747613b82c2ccd0dee98 to your computer and use it in GitHub Desktop.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.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, dst;
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 ((dst = open(argv[optind+1], O_WRONLY | O_CREAT | O_TRUNC | flags, 0664)) == -1) {
perror("open");
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(dst, 0, SEEK_CUR)) == (off_t)-1) {
perror("lseek");
break;
}
memset(buf + len, 0, BLOCKSIZ - len);
if ((n = writen(dst, buf, BLOCKSIZ)) == -1) {
perror("write");
break;
}
if (ftruncate(dst, cur + len) == -1) {
perror("ftruncate");
break;
}
}
break;
}
}
len += n;
if ((n = writen(dst, buf, WRITABLEN(len))) == -1) {
perror("write");
break;
}
len -= n;
}
close(dst);
close(src);
free(buf);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment