Skip to content

Instantly share code, notes, and snippets.

@clarete
Created December 12, 2012 20:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clarete/4271479 to your computer and use it in GitHub Desktop.
Save clarete/4271479 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#elif defined(__linux__)
#include <sys/stat.h>
#include <sys/mman.h>
#endif
#define InFile argv[1]
#define TargetPath argv[2]
#define ARRAYCOUNT(array) sizeof(array)/sizeof(array[0])
typedef struct
{
char *find;
char *add;
} sdata;
#if defined(_WIN32)
#define PATHSEP "\\"
#elif defined(__linux__)
#define PATHSEP "/"
#endif
sdata Searches[] = {{"qt_prfxpath=", ""},
{"qt_docspath=", PATHSEP "doc"},
{"qt_hdrspath=", PATHSEP "include"},
{"qt_libspath=", PATHSEP "lib"},
{"qt_binspath=", PATHSEP "bin"},
{"qt_plugpath=", PATHSEP "plugins"},
{"qt_datapath=", ""},
{"qt_trnspath=", PATHSEP "translations"},
{"qt_xmplpath=", PATHSEP "examples"},
// {"qt_demopath=", PATHSEP "demos"},
{"qt_lbexpath=", PATHSEP "libexec"},
{"qt_impspath=", PATHSEP "imports"},
{"qt_qml2path=", PATHSEP "qml"},
{"qt_adatpath=", ""},
{"qt_tstspath=", PATHSEP "tests"},
{"qt_hpfxpath=", ""},
{"qt_hbinpath=", PATHSEP "bin"},
{"qt_hdatpath=", ""}
};
// This is Win32 code currently, but could easily be adapted to use mmap
char *MapFile(char *file, size_t *FileLen)
{
static void* lpMapAddress = NULL;
#if defined(_WIN32)
static HANDLE hQMake = NULL;
static HANDLE hMapFile = NULL;
// If this is an open
if (file != NULL)
{
hQMake = CreateFile(file, // File name
GENERIC_READ | GENERIC_WRITE, // Desired access
FILE_SHARE_READ, // Sharing allowed
NULL, // Default security
OPEN_EXISTING, // Do not create a new file
FILE_ATTRIBUTE_NORMAL, // File attributes
NULL);
if (hQMake == INVALID_HANDLE_VALUE)
{
printf("Could not open file.\n");
return NULL;
}
*FileLen = GetFileSize(hQMake, NULL);
if (*FileLen == INVALID_FILE_SIZE)
{
printf("Could not get file size.\n");
CloseHandle(hQMake);
return NULL;
}
hMapFile = CreateFileMapping(hQMake, // Current file handle.
NULL, // Default security.
PAGE_READWRITE, // Read/write permission.
0, // Max. object size.
0, // Size of hFile.
"QMake"); // Name of mapping object.
if (hMapFile == INVALID_HANDLE_VALUE)
{
printf("Could not create file-mapping object.\n");
CloseHandle(hQMake);
return NULL;
}
lpMapAddress = MapViewOfFile(hMapFile, // Handle to mapping object.
FILE_MAP_ALL_ACCESS, // Read/write permission
0, // Max. object size.
0, // Size of hFile.
0); // Map entire file.
if (lpMapAddress == INVALID_HANDLE_VALUE)
{
printf("Could not map view of file.\n");
CloseHandle(hMapFile);
CloseHandle(hQMake);
return NULL;
}
return (char*) lpMapAddress;
}
// This is a close
else
{
if (!UnmapViewOfFile(lpMapAddress))
{
printf("Could not unmap view of file.\n");
}
CloseHandle(hMapFile);
CloseHandle(hQMake);
return NULL;
}
#elif defined(__linux__)
static FILE *hQMake = NULL;
static void *map = NULL;
struct stat filesize;
// If this is an open
if (file != NULL)
{
hQMake = fopen(file, "rb+");
if (hQMake == NULL)
{
printf("Could not open file.\n");
return NULL;
}
if (fstat(fileno(hQMake), &filesize))
{
printf("Could not get file size.\n");
fclose(hQMake);
return NULL;
}
*FileLen = filesize.st_size;
lpMapAddress = mmap(0, // Don't care what address we get
*FileLen, // Map the whole file
PROT_READ | PROT_WRITE, // Read/write permission
MAP_SHARED, // Shared mapping, stores affect original file
fileno(hQMake), // File number
0);
if (lpMapAddress == MAP_FAILED)
{
printf("Could not map view of file.\n");
fclose(hQMake);
return NULL;
}
map = lpMapAddress;
return (char*) lpMapAddress;
}
// This is a close
else
{
munmap(map, *FileLen);
fclose(hQMake);
return NULL;
}
#endif
}
int main(int argc, char* argv[])
{
char *filedata;
size_t filesize;
char *match;
char *end;
char *nextbeg;
int i;
#if defined(__linux__)
FILE *backup = NULL;
#endif
if (argc < 2)
{
printf ("Usage: patchqmake <path to qmake> <install path>\n\n");
return 255;
}
// Map the file
filedata = MapFile(InFile, &filesize);
if (filedata == NULL)
return 1;
// Back up the file
match = (char*) malloc(strlen(InFile) + 5);
if (match == NULL)
return 2;
strcpy(match, InFile);
strcat(match, ".bak");
#if defined(_WIN32)
if (!CopyFile(InFile, match, FALSE))
{
printf("Couldn't make backup of file!\n");
MapFile(NULL, &filesize);
return 3;
}
#elif defined(__linux__)
backup = fopen(match, "wb");
if (backup == NULL)
{
printf("Couldn't make backup of file!\n");
MapFile(NULL, &filesize);
return 3;
}
fwrite(filedata, 1, filesize, backup);
fclose(backup);
#endif
free(match);
for (i = 0; i < ARRAYCOUNT(Searches); i++)
{
printf("Searching for '%s'...", Searches[i].find);
for (match = filedata; match < filedata + filesize; match++)
{
// See if we've found the string to change
if (memcmp(match, Searches[i].find, strlen(Searches[i].find)) == 0)
{
// Move past the string key
match += strlen(Searches[i].find);
// Find the end of space used, clearing it as we go
for (end = match; *end; end++)
*end = '\0';
// Find the end of the allotted space
for (nextbeg = end; !*nextbeg; nextbeg++);
if ((size_t) (nextbeg - match) < strlen(TargetPath))
{
printf("not enough room for %s!\n", TargetPath);
MapFile(NULL, &filesize);
return 4;
}
printf("patching.\n");
// Copy in the path they asked for
strcpy(match, TargetPath);
strcat(match, Searches[i].add);
break;
}
}
// Did we find it?
if (match >= filedata + filesize)
{
printf("couldn't find it!\n");
MapFile(NULL, &filesize);
return 5;
}
}
// Unmap the file
MapFile(NULL, &filesize);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment