#include #include #include #include #include #include #include #include #include #define OPEN(fd, file, args) \ do{ \ fd = open(file, args); \ if(fd == -1) { \ fprintf(stderr, "Can't open file %s\n", file); \ exit(EXIT_FAILURE); \ } \ }while(0) #define CLOSE(fd, name) \ do{ \ if(close(fd) == -1) { \ fprintf(stderr, "Cant close file descriptor " name "\n"); \ exit(EXIT_FAILURE); \ } \ }while(0) #define MMAP(address, length, prot, flags, fd, name) \ do{ \ address = mmap(NULL, length, prot, flags, fd, 0); \ if(address == MAP_FAILED) { \ fprintf(stderr, "Can't do mapping of " name "\n"); \ exit(EXIT_FAILURE); \ } \ }while(0) #define MUNMAP(start, length, name) \ do{ \ if(munmap(start, length) == -1) { \ fprintf(stderr, "Can't unmap the mapping " name "\n"); \ exit(EXIT_FAILURE); \ } \ }while(0) #define SIZE stats.st_size void parseArgs(int, char**); int main(int argc, char** argv) { int fd1, fd2; void *map1, *map2; struct stat stats; parseArgs(argc, argv); OPEN(fd1, argv[1], O_RDONLY); OPEN(fd2, argv[2], O_RDWR | O_CREAT | O_TRUNC); if(fstat(fd1, &stats) == -1) { fprintf(stderr, "Can't stat file %s\n", argv[1]); exit(EXIT_FAILURE); } if(lseek(fd2, SIZE - 1, SEEK_SET) == (off_t)-1) { fprintf(stderr, "Can't do lseek\n"); exit(EXIT_FAILURE); } if(write(fd2, '\0', 1) == -1) { fprintf(stderr, "Can't write last byte of file %s\n", argv[2]); switch(errno) { case EAGAIN: printf("The file descriptor fd has been marked non-blocking (O_NONBLOCK) and the write would block."); break; case EBADF: printf("fd is not a valid file descriptor or is not open for writing."); break; case EFAULT: printf("buf is outside your accessible address space."); break; case EFBIG: printf("An attempt was made to write a file that exceeds the implementation-defined maximum file size or the process's\ file size limit, or to write at a position past the maximum allowed offset."); break; case EINTR: printf("The call was interrupted by a signal before any data was written."); break; case EINVAL: printf("fd is attached to an object which is unsuitable for writing; or the file was opened with the O_DIRECT flag, and\ either the address specified in buf, the value specified in count, or the current file offset is not suitably\ aligned."); break; case EIO: printf("A low-level I/O error occurred while modifying the inode."); break; case ENOSPC: printf("The device containing the file referred to by fd has no room for the data."); break; case EPIPE: printf("fd is connected to a pipe or socket whose reading end is closed. When this happens the writing process will also\ receive a SIGPIPE signal. (Thus, the write return value is seen only if the program catches, blocks or ignores\ this signal.)"); break; } printf("\n"); exit(EXIT_FAILURE); } MMAP(map1, SIZE, PROT_READ, MAP_SHARED, fd1, "fd1"); MMAP(map2, SIZE, PROT_WRITE, MAP_SHARED, fd2, "fd2"); memcpy(map2, map1, SIZE); MUNMAP(map1, SIZE, "map1"); MUNMAP(map2, SIZE, "map2"); CLOSE(fd1, "fd1"); CLOSE(fd2, "fd2"); return EXIT_SUCCESS; } void parseArgs(int argc, char** argv) { if(argc == 3) return; printf("Usage: %s SOURCE DEST\n", argv[0]); exit(EXIT_FAILURE); }