CpMM - Memory-Mapped File Copy
This program, contributed by Andrew Savige, completes Chapter 2's collection of file
copy programs and is very similar to Chapter 6's atouMM.
- The performance, based on several quick, informal tests, is very good for NTFS files,
often producing twice the performance of cpCF, the nearest
competitor (see Appendix C in the book). The performance with FAT files is about the same
as for cpCF.
- This program illustrates some alternatives to the coding styles I elected to use in the
book. (People have strong opinions on this subject! Use your own taste and judgement.)
First, notice how the Win32 function calls are spaced vertically over several lines. This
aids readability, at least locally, but consumes vertical space, which was scarce in the
book. Secondly, notice the use of the form which I did not elect to use (many writers do
not recommend it, but it does save a line):
If ((Status = Func ()) != GOOD) ReportError ();
/* cpmm.c. memory-mapped file implementation. Author: Andrew Savige */
/* This will have performance advantages with NTFS files */
/* and is about the same as cfCF with FAT files. */
/* cp file1 file2: Copy file1 to file2. */
#include <windows.h>
#include <stdio.h>
#include <errno.h>
int main (int argc, char *argv [])
{
HANDLE hInFile, hOutFile;
HANDLE hInMap, hOutMap;
const void *pIn;
void *pOut;
DWORD dwSize;
if (argc != 3) {
printf ("Usage: cp file1 file2\n");
return 1;
}
if ((hInFile=CreateFile(argv[1],
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
0))==INVALID_HANDLE_VALUE) {
printf ("Error opening input file: %s. Error Number: %d",
argv [1], GetLastError());
return 2;
}
if ((dwSize=GetFileSize(hInFile, NULL))==0xffffffff) {
printf ("Error getting input file size: %s. Error Number: %d",
argv [1], GetLastError());
return 2;
}
if ((hInMap=CreateFileMapping(hInFile,
NULL,
PAGE_READONLY,
0,
dwSize,
NULL))==NULL) {
printf ("Error creating input file mapping: %s. Error Number: %d",
argv [1], GetLastError());
return 2;
}
if ((pIn=MapViewOfFile(
hInMap,
FILE_MAP_READ,
0, 0, dwSize))==NULL) {
printf ("Error mapping view of input file: %s. Error Number: %d",
argv [1], GetLastError());
return 2;
}
if ((hOutFile=CreateFile(argv[2],
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_FLAG_NO_BUFFERING,
0))==INVALID_HANDLE_VALUE) {
printf ("Error opening output file: %s. Error Number: %d",
argv [2], GetLastError());
return 2;
}
if ((hOutMap=CreateFileMapping(hOutFile,
NULL,
PAGE_READWRITE,
0,
dwSize,
NULL))==NULL) {
printf ("Error creating output file mapping. %s: Error Number: %d",
argv [2], GetLastError());
return 2;
}
if ((pOut=MapViewOfFile(
hOutMap,
FILE_MAP_WRITE,
0, 0, dwSize))==NULL) {
printf ("Error mapping view of output file. %s: Error Number: %d",
argv [2], GetLastError());
return 2;
}
CopyMemory(pOut, pIn, dwSize); /* Alternative to C library memcpy */
UnmapViewOfFile (pIn);
UnmapViewOfFile (pOut);
CloseHandle (hInMap);
CloseHandle (hOutMap);
CloseHandle (hInFile);
CloseHandle (hOutFile);
return 0;
}
|