All pastes #1282584 Raw Edit

sfcp-0.4.4.c

public c v1 · immutable
#1282584 ·published 2008-12-11 12:06 UTC
rendered paste body
/** Description: a simple utility for fast file copying within one physical HDD* Copyright (c) 2005-2008 Artem S. Tashkinov* License: GPL2** Features:* 1) Uses LARGE file buffer (10Mb) for transfers* 2) Checks output file consistency (bit-by-bit comparison with the original file)* 3) Preserves file owner, access rights and modification times (atime and mtime)* 4) Works fine with files larger than 2GB** Should be compiled with '-Wall -O2 -Werror -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE' flags*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <libgen.h>#include <utime.h>#define BUFFER (1024*1024*100) // 100 Mboff_t filesize(char* file_name) // 64bit safe{        off_t size;        FILE* fstream;        if ( ( fstream = fopen( file_name, "rb" ) ) == NULL ) {                fprintf(stderr, "Cannot open input file.\n");                exit(1);        }        fseeko( fstream, 0, SEEK_END ); // Move to the end of file        size = ftello( fstream );        fclose( fstream );        return size;}int main(int argc, char *argv[]){        int fd_in, fd_out;        ssize_t bytes_read;        off_t fsize;        void *buffer, *buffer_chk;        char *base_name;        char *dest_path;        struct stat64 *stat_dest = (struct stat64 *) malloc(sizeof(struct stat64));        struct stat64 *stat_src = (struct stat64 *) malloc(sizeof(struct stat64));        struct utimbuf touch_time;        if (argc<3) {                printf("Usage is: sfcp source destination [skip_checking]\n");                return 1;        }        buffer = malloc(BUFFER * sizeof(char));        buffer_chk = malloc(BUFFER * sizeof(char));        if (buffer == NULL || buffer_chk == NULL) {                printf("Error: can't allocate buffers\n");                return 2;        }        memset(buffer, 0, BUFFER);        memset(buffer_chk, 0, BUFFER);        if ((fd_in  = open64(argv[1], O_RDONLY | O_LARGEFILE)) == -1) {                printf("Error: source file can't be open\n");                perror("open() ");                return 3;        }        fsize = filesize(argv[1]);        base_name = basename(argv[1]);        stat64(argv[1], stat_src);        stat64(argv[2], stat_dest);        // +2 in case of missing '/' at the end of argv[2]        dest_path = (char *) malloc(sizeof(char)*(strlen(base_name)+strlen(argv[2])+2));        strcpy(dest_path, argv[2]);        if ( stat_dest->st_mode && S_IFDIR ) {                if (argv[2][strlen(argv[2])-1]!='/') strcat(dest_path, "/");                strcat(dest_path, base_name);        }        printf("\"%s\" -> \"%s\" ... ", argv[1], dest_path);        fflush(NULL);        chown(dest_path, stat_src->st_uid, stat_src->st_gid);        chmod(dest_path, stat_src->st_mode);        if ((fd_out = open64(dest_path, O_RDWR | O_LARGEFILE | O_CREAT | O_EXCL | O_SYNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) {                printf("Error: destination file can't be created\n");                perror("open() ");                return 2;        }        bytes_read = 1;        while (bytes_read) {                bytes_read = read(fd_in, (void *) buffer, BUFFER);                posix_fadvise(fd_in, 0, fsize, POSIX_FADV_DONTNEED);                if (write(fd_out, (void *) buffer, bytes_read) != bytes_read)                {                        printf("Error: can't write data to the destination file! Possibly a target disk is full\n");                        return 3;                }        }        close(fd_in);        close(fd_out);        fdatasync(fd_out);        printf(".");        fflush(NULL);        if ((fd_in  = open64(argv[1], O_RDONLY | O_LARGEFILE)) == -1) {                printf("Error: source file can't be open\n");                perror("open() ");                return 3;        }        if ((fd_out = open64(dest_path, O_RDONLY | O_LARGEFILE)) == -1) {                printf("Error: source file can't be open\n");                perror("open() ");                return 3;        }        memset(buffer, 0, BUFFER);        memset(buffer_chk, 0, BUFFER);        bytes_read = 1;        if (argc != 4) {                printf(" C");                fflush(NULL);                while (bytes_read) {                        bytes_read = read(fd_in, (void *) buffer, BUFFER);                        posix_fadvise(fd_in,  0, fsize, POSIX_FADV_DONTNEED);                        read(fd_out, (void *) buffer_chk, bytes_read);                        posix_fadvise(fd_out, 0, fsize, POSIX_FADV_DONTNEED);                        if (memcmp(buffer, buffer_chk, bytes_read)) {                                printf("CRC Error while checking! Exiting!\n");                                return 4;                        }                }        }        close(fd_in);        close(fd_out);        touch_time.actime  = stat_src->st_atime;        touch_time.modtime = stat_src->st_mtime;        // The first chmod call sometimes fails so let's repeat        chmod(dest_path, stat_src->st_mode);        // We utime the file at last because chmod and chown change atime        utime(dest_path, &touch_time);        printf(" OK\n");        return 0;}