All pastes #814034 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-12-12 23:22 UTC
rendered paste body
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

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