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;}