static void RAFwrite(raf_t raf,void*buf,size_t len,off_t ofs){ ssize_t res=pwrite(raf->fd,buf,len,ofs); if (res<0) { FatalCall(1,error,"could not write %s",raf->shared.name); } if (res!=(ssize_t)len) { FatalCall(1,error,"short write to %s",raf->shared.name); } }
static void RAFread(raf_t raf,void*buf,size_t len,off_t ofs){ ssize_t res=pread(raf->fd,buf,len,ofs); if (res<0) { FatalCall(1,error,"could not read %s",raf->shared.name); } if (res!=(ssize_t)len) { FatalCall(1,error,"short read %u/%u from %s at %llu",res,len,raf->shared.name,ofs); } }
static void AIOwait(raf_t raf){ if(raf->pending==0) return; const struct aiocb* list[1]; list[0]=&(raf->request); // TODO check out why aio_suspend complains about 1st argument. if (aio_suspend((void*)list,1,NULL)){ FatalCall(1,error,"aio_suspend for %s",raf->shared.name); } if (aio_error(list[0])){ FatalCall(1,error,"aio_error for %s",raf->shared.name); } raf->pending=0; }
static void RAFclose(raf_t *raf){ if (close((*raf)->fd)==-1){ FatalCall(1,error,"could not close %s",(*raf)->shared.name); } free(*raf); *raf=NULL; }
static off_t RAFsize(raf_t raf){ struct stat info; if (fstat(raf->fd,&info)==-1){ FatalCall(1,error,"could not get size of %s",raf->shared.name); } return info.st_size; }
static void AIOwrite(raf_t raf,void*buf,size_t len,off_t ofs){ if(raf->pending) { Fatal(1,error,"There may not be more than one asynchronous call pending."); } raf->pending=1; raf->request.aio_buf=buf; raf->request.aio_nbytes=len; raf->request.aio_offset=ofs; if (aio_write(&(raf->request))){ FatalCall(1,error,"aio_write to %s",raf->shared.name); } }
raf_t raf_unistd(char *name){ int fd=open(name,O_RDWR|O_CREAT,DEFFILEMODE); if (fd==-1) FatalCall(1,error,"could not open %s",name); raf_t raf=(raf_t)RTmalloc(sizeof(struct raf_struct_s)); raf_init(raf,name); raf->fd=fd; raf->shared.read=RAFread; raf->shared.write=RAFwrite; raf->shared.awrite=RAFwrite; raf->shared.await=RAFwait; raf->shared.size=RAFsize; raf->shared.resize=RAFresize; raf->shared.close=RAFclose; return raf; }
raf_t raf_aio(char *name){ int fd=open(name,O_RDWR|O_CREAT,DEFFILEMODE); if (fd==-1) FatalCall(1,error,"could not open %s",name); raf_t raf=(raf_t)RTmalloc(sizeof(struct raf_struct_s)); raf_init(raf,name); raf->fd=fd; raf->shared.read=RAFread; raf->shared.write=RAFwrite; raf->shared.awrite=AIOwrite; raf->shared.await=AIOwait; raf->shared.size=RAFsize; raf->shared.resize=RAFresize; raf->shared.close=RAFclose; raf->request.aio_fildes=fd; raf->request.aio_reqprio=0; raf->pending=0; return raf; }
static void RAFresize(raf_t raf,off_t size){ if (ftruncate(raf->fd,size)==-1){ FatalCall(1,error,"could not resize %s",raf->shared.name); } }
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpOriginalCmdLine, int nCmdShow) { int i; LOADED_IMAGE oImg; LPWSTR lpCmdLine; wchar_t parentDir[MAX_PATH+1] = L"", exePath[MAX_PATH+1] = L""; size_t szParentDir, szExeStr, szCmdLine, szPlatExe; PROCESS_INFORMATION pi; STARTUPINFO si; LPWSTR *argv = __wargv; int argc = __argc; // Zero out our loaded image struct. ZeroMemory(&oImg, sizeof(oImg)); /* Make sure we have args. */ if(argc == 1) { Fatal(1L, L"No images specified."); } /* Get our exe's parent folder. */ if(!GetParentDir(parentDir, &szParentDir)) { Fatal(1L, L"Could not get parent folder of image, \"%s\". This should not happen ever.", argv[0]); } /* Iterate through our arguments */ for(i = 1; i < argc; i++) { /* Verify file exists. */ if(_waccess(argv[i], 00) == -1) { Fatal(1L, L"File does not exist.\nFile: %s", argv[i]); } /* Get the binary type. */ if(!MapAndLoadW(argv[i], &oImg)) { Fatal(1L, L"Unable to get binary type for image.\nImage: %s", argv[i]); } lstrcpyW(exePath, parentDir); switch(oImg.FileHeader->FileHeader.Machine) { case IMAGE_FILE_MACHINE_I386: lstrcatW(exePath, x86exe); szPlatExe = SZ_86_EXE; break; // TODO: Differentiate between x64 platforms. case IMAGE_FILE_MACHINE_AMD64: lstrcatW(exePath, amd64exe); szPlatExe = SZ_AMD_EXE; break; case IMAGE_FILE_MACHINE_IA64: lstrcatW(exePath, ia64exe); szPlatExe = SZ_IA_EXE; break; default: Fatal(1L, L"Unknown binary type returned for image.\nImage: %s\n\nBinary Type: %d", argv[i], oImg.FileHeader->FileHeader.Machine); } if(!UnMapAndLoad(&oImg)) { Fatal(1L, L"Failed to unload/unmap image.\nImage: %s", argv[i]); } /* Calculate the length of the eventual exe path with surrounding quotes. */ lstrcatW(exePath, depsexe); szExeStr = szParentDir + szPlatExe + 2; // +2 for the two "s surrounding the image path. /* Allocate our command line string. */ // szExeStr+ 1 +1+wcslen(argv)+1 // "(path)depends.exe" "argv" szCmdLine = szExeStr + lstrlenW(argv[i]) + 3; lpCmdLine = (LPWSTR)LocalAlloc(LPTR, sizeof(wchar_t) * (szCmdLine + 1)); if(lpCmdLine == NULL) { Fatal(1L, L"Could not allocate memory.\nMemory required (bytes): %d", sizeof(wchar_t) * (szCmdLine + 1)); } if(swprintf(lpCmdLine, szCmdLine+1, L"\"%s\" \"%s\"", exePath, argv[i]) == -1) { LocalFree(lpCmdLine); FatalCall(L"swprintf"); } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); /* Depends launching. */ if (!CreateProcessW( NULL, /* No module name (use command line) */ lpCmdLine, /* Command line */ NULL, /* Process handle not inheritable */ NULL, /* Thread handle not inheritable */ FALSE, /* Set handle inheritance to FALSE */ 0, /* No creation flags */ NULL, /* Use parent's environment block */ NULL, /* Use parent's starting directory */ &si, /* Pointer to STARTUPINFO structure */ &pi /* Pointer to PROCESS_INFORMATION structure */ )) { // len("CreateProcessW") + len(" - ") + len(cmdline) szCmdLine += 17; LocalFree(lpCmdLine); lpCmdLine = (LPWSTR)LocalAlloc(LPTR, sizeof(wchar_t) * (szCmdLine + 1)); swprintf(lpCmdLine, szCmdLine+1, L"CreateProcessW - \"%s\" \"%s\"", exePath, argv[i]); FatalCall(lpCmdLine); } LocalFree(lpCmdLine); } return 0; }