source: trunk/kLdr/kLdrRdrFile.c@ 2857

Last change on this file since 2857 was 2857, checked in by bird, 19 years ago

Only the mapping left now.

  • Property svn:keywords set to Id
File size: 13.1 KB
RevLine 
[2826]1/* $Id: kLdrRdrFile.c 2857 2006-11-05 04:12:13Z bird $ */
[2825]2/** @file
3 *
4 * kLdr - The Dynamic Loader, file abstraction.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
7 *
8 *
9 * This file is part of kLdr.
10 *
11 * kLdr is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kLdr is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kLdr; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#ifdef __OS2__
32# define INCL_ERRORS
33# define INCL_BASE
34# include <os2.h>
35
36#elif defined(__WIN32__) || defined(__WIN64__) || defined(__WIN__)
37# include <Windows.h>
38# ifndef __WIN__
39# define __WIN__
40# endif
41
42#else
43# error "port me"
44#endif
45
46#include <kLdr.h>
47#include "kLdrHlp.h"
48
49
50/*******************************************************************************
51* Structures and Typedefs *
52*******************************************************************************/
53/**
54 * The file provier instance for native files.
55 */
56typedef struct KLDRRDRFILE
57{
58 /** The file reader vtable. */
59 KLDRRDR Core;
60 /** The file handle. */
61#ifdef __OS2__
62 HFILE File;
63#elif defined(__WIN__) || defined(__NT__)
64 HANDLE File;
65#else
66# error "Port me!"
67#endif
68 /** The current file offset. */
69 off_t off;
70 /** The file size. */
71 off_t cb;
72 /** Number of mapping references. */
73 int32_t cMappings;
74 /** The memory mapping. */
75 void *pvMapping;
76 /** The filename. */
77 char szFilename[1];
78} KLDRRDRFILE, *PKLDRRDRFILE;
79
80
81/*******************************************************************************
82* Internal Functions *
83*******************************************************************************/
[2829]84static void kldrRdrFileDone(PKLDRRDR pRdr);
85static int kldrRdrFileUnprepare(PKLDRRDR pRdr, void *pv, size_t cb);
86static int kldrRdrFileUnmap(PKLDRRDR pRdr, void *pv, size_t cb);
87static int kldrRdrFileProtect(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt);
[2857]88static int kldrRdrFileRefreshMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile);
[2829]89static int kldrRdrFileMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile);
90static int kldrRdrFilePrepare(PKLDRRDR pRdr, void **ppv, size_t cb, unsigned fFixed);
[2857]91static size_t kldrRdrFilePageSize(PKLDRRDR pRdr);
[2825]92static const char *kldrRdrFileName(PKLDRRDR pRdr);
93static off_t kldrRdrFileTell(PKLDRRDR pRdr);
94static off_t kldrRdrFileSize(PKLDRRDR pRdr);
95static int kldrRdrFileAllUnmap(PKLDRRDR pRdr, const void *pvBits);
96static int kldrRdrFileAllMap(PKLDRRDR pRdr, const void **ppvBits);
97static int kldrRdrFileRead(PKLDRRDR pRdr, void *pvBuf, size_t cb, off_t off);
98static int kldrRdrFileDestroy(PKLDRRDR pRdr);
99static int kldrRdrFileCreate(PPKLDRRDR ppRdr, const char *pszFilename);
100
101
102/*******************************************************************************
103* Global Variables *
104*******************************************************************************/
105/** Native file provider operations. */
106const KLDRRDROPS g_kLdrRdrFileOps =
107{
108 "native file",
109 NULL,
110 kldrRdrFileCreate,
111 kldrRdrFileDestroy,
112 kldrRdrFileRead,
113 kldrRdrFileAllMap,
114 kldrRdrFileAllUnmap,
115 kldrRdrFileSize,
116 kldrRdrFileTell,
[2829]117 kldrRdrFileName,
[2857]118 kldrRdrFilePageSize,
[2829]119 kldrRdrFilePrepare,
120 kldrRdrFileMap,
[2857]121 kldrRdrFileRefreshMap,
[2829]122 kldrRdrFileProtect,
123 kldrRdrFileUnmap,
124 kldrRdrFileUnprepare,
125 kldrRdrFileDone,
126 42
[2825]127};
128
129
[2829]130/** @copydoc KLDRRDR::pfnDone */
131static void kldrRdrFileDone(PKLDRRDR pRdr)
132{
133}
[2825]134
[2829]135/** @copydoc KLDRRDR::pfnUnprepare */
136static int kldrRdrFileUnprepare(PKLDRRDR pRdr, void *pv, size_t cb)
137{
138 return -1;
139}
140
141
142/** @copydoc KLDRRDR::pfnUnmap */
143static int kldrRdrFileUnmap(PKLDRRDR pRdr, void *pv, size_t cb)
144{
145 return -1;
146}
147
148
149/** @copydoc KLDRRDR::pfnProtect */
150static int kldrRdrFileProtect(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt)
151{
152 return -1;
153}
154
155
[2857]156/** @copydoc KLDRRDR::pfnRefreshMap */
157static int kldrRdrFileRefreshMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile)
158{
159 return -1;
160}
161
162
[2829]163/** @copydoc KLDRRDR::pfnMap */
164static int kldrRdrFileMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile)
165{
166 return -1;
167}
168
169
170/** @copydoc KLDRRDR:pfnPrepare */
171static int kldrRdrFilePrepare(PKLDRRDR pRdr, void **ppv, size_t cb, unsigned fFixed)
172{
173#ifdef __OS2__
174
175
176#elif defined(__WIN__)
177
178#else
179# error "port me."
180#endif
181 return -1;
182}
183
184
[2857]185/** @copydoc KLDRRDR::pfnPageSize */
186static size_t kldrRdrFilePageSize(PKLDRRDR pRdr)
187{
188#ifdef __OS2__
189 /* The page size on OS/2 wont change anytime soon. :-) */
190 return 0x1000;
191
192#elif defined(__WIN__)
193 SYSTEM_INFO SysInfo;
194 GetSystemInfo(&SysInfo);
195 return SysInfo.dwPageSize;
196 /*return SysInfo.dwAllocationGranularity;*/
197#else
198# error "port me"
199#endif
200}
201
202
[2825]203/** @copydoc KLDRRDR::pfnName */
204static const char *kldrRdrFileName(PKLDRRDR pRdr)
205{
206 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
207 return &pRdrFile->szFilename[0];
208}
209
210
211/** @copydoc KLDRRDR::pfnTell */
212static off_t kldrRdrFileTell(PKLDRRDR pRdr)
213{
214 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
215
216 /*
217 * If the offset is undefined, try figure out what it is.
218 */
219 if (pRdrFile->off == -1)
220 {
221#ifdef __OS2__
222 ULONG ulNew;
223 APIRET rc = DosSetFilePtr(pRdrFile->File, 0, FILE_CURRENT, &ulNew);
224 if (rc)
225 return -1;
226 pRdrFile->off = ulNew;
227
228#elif defined(__WIN__)
229 LONG offHigh = 0;
230 LONG offLow;
231 int rc;
232
233 SetLastError(0);
234 offLow = SetFilePointer(pRdrFile->File, 0, &offHigh, FILE_BEGIN);
235 rc = GetLastError();
236 if (rc)
237 return -1;
238 pRdrFile->off = ((off_t)offHigh << 32) | offLow;
239
240#else
241# error "port me."
242#endif
243 }
244 return pRdrFile->off;
245}
246
247
248/** @copydoc KLDRRDR::pfnSize */
249static off_t kldrRdrFileSize(PKLDRRDR pRdr)
250{
251 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
252 return pRdrFile->cb;
253}
254
255
256/** @copydoc KLDRRDR::pfnAllUnmap */
257static int kldrRdrFileAllUnmap(PKLDRRDR pRdr, const void *pvBits)
258{
259 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
260
261 /* check for underflow */
262 if (pRdrFile->cMappings <= 0)
263#if defined(__OS2__) || defined(__WIN__)
264 return ERROR_INVALID_PARAMETER;
265#else
266# error "port me"
267#endif
268
269 /* decrement usage counter, free mapping if no longer in use. */
270 if (!--pRdrFile->cMappings)
271 {
272 kldrHlpFree(pRdrFile->pvMapping);
273 pRdrFile->pvMapping = NULL;
274 }
275
276 return 0;
277}
278
279
280/** @copydoc KLDRRDR::pfnAllMap */
281static int kldrRdrFileAllMap(PKLDRRDR pRdr, const void **ppvBits)
282{
283 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
284
285 /*
286 * Do we need to map it?
287 */
288 if (!pRdrFile->pvMapping)
289 {
290 int rc;
291 off_t cb = pRdrFile->Core.pOps->pfnSize(pRdr);
292
293 pRdrFile->pvMapping = kldrHlpAlloc(cb);
294 if (!pRdrFile->pvMapping)
295#if defined(__OS2__) || defined(__WIN__)
296 return ERROR_NOT_ENOUGH_MEMORY;
297#else
298# error "port me"
299#endif
300 rc = pRdrFile->Core.pOps->pfnRead(pRdr, pRdrFile->pvMapping, cb, 0);
301 if (rc)
302 {
303 kldrHlpFree(pRdrFile->pvMapping);
304 pRdrFile->pvMapping = NULL;
305 return rc;
306 }
307 pRdrFile->cMappings = 0;
308 }
309
310 pRdrFile->cMappings++;
311 return 0;
312}
313
314
315/** @copydoc KLDRRDR::pfnRead */
316static int kldrRdrFileRead(PKLDRRDR pRdr, void *pvBuf, size_t cb, off_t off)
317{
318 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
319
320 /*
321 * Do a seek if needed.
322 */
323 if (pRdrFile->off != off)
324 {
325#ifdef __OS2__
326 ULONG ulNew;
327 APIRET rc = DosSetFilePtr(pRdrFile->File, off, FILE_BEGIN, &ulNew);
328 if (rc)
329 {
330 pRdrFile->off = -1;
331 return rc;
332 }
333
334#elif defined(__WIN__)
335 LONG offHigh = (LONG)(off >> 32);
336 LONG offLow = SetFilePointer(pRdrFile->File, (LONG)off, &offHigh, FILE_BEGIN);
337 if ( offLow != (LONG)off
338 && offHigh != (LONG)(off >> 32))
339 {
340 int rc = GetLastError();
341 if (!rc)
342 rc = ERROR_GEN_FAILURE;
343 pRdrFile->off = -1;
344 return rc;
345 }
346
347#else
348# error "port me."
349#endif
350 }
351
352 /*
353 * Do the read.
354 */
355#ifdef __OS2__
356 {
357 ULONG cbRead = 0;
358 APIRET rc = DosRead(pRdrFile->File, pvBuf, cb, &cbRead);
359 if (rc)
360 {
361 pRdrFile->off = -1;
362 return rc;
363 }
364 if (cbRead != cb)
365 {
366 pRdrFile->off = -1;
367 return ERROR_GEN_FAILURE;
368 }
369 }
370
371#elif defined(__WIN__)
372 {
373 DWORD cbRead = 0;
374 if (!ReadFile(pRdrFile->File, pvBuf, cb, &cbRead, NULL))
375 {
376 int rc = GetLastError();
377 if (!rc)
378 rc = ERROR_GEN_FAILURE;
379 pRdrFile->off = -1;
380 return rc;
381 }
382 if (cbRead != cb)
383 {
384 pRdrFile->off = -1;
385 return ERROR_GEN_FAILURE;
386 }
387 }
388
389#else
390# error "port me."
391#endif
392
393 pRdrFile->off = off + cb;
394 return 0;
395}
396
397
398/** @copydoc KLDRRDR::pfnDestroy */
399static int kldrRdrFileDestroy(PKLDRRDR pRdr)
400{
401 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
402 int rc;
403#ifdef __OS2__
404 rc = DosClose(pRdrFile->File);
405
406#elif defined(__WIN__)
407 if (!CloseHandle(pRdrFile->File))
408 rc = GetLastError();
409
410#else
411# error "port me"
412#endif
413
414 if (pRdrFile->pvMapping)
415 {
416 kldrHlpFree(pRdrFile->pvMapping);
417 pRdrFile->pvMapping = NULL;
418 }
419
420 kldrHlpFree(pRdr);
421 return rc;
422}
423
424
425/** @copydoc KLDRRDROPS::pfnCreate */
426static int kldrRdrFileCreate(PPKLDRRDR ppRdr, const char *pszFilename)
427{
428 size_t cchFilename;
429 PKLDRRDRFILE pRdrFile;
430
431 /*
432 * Open the file and determin its size.
433 */
434#ifdef __OS2__
435 ULONG ulAction = 0;
436 FILESTATUS3 Info;
437 APIRET rc;
438 HFILE File = 0;
439 off_t cb;
440
441 if ((uintptr_t)pszFilename >= 0x20000000)
442 {
[2828]443 char *psz = (char *)kLdrHlpAllocA(cchFilename + 1);
444 kLdrHlpMemCopy(psz, pszFilename, cchFilename + 1);
[2825]445 pszFilename = psz;
446 }
447 rc = DosOpen((PCSZ)pszFilename, &File, &ulAction, 0, FILE_NORMAL,
448 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
449 OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY | OPEN_FLAGS_RANDOMSEQUENTIAL,
450 NULL);
451 if (rc)
452 return rc;
453
454 rc = DosQueryFileInfo(File, FIL_STANDARD, &Info, sizeof(Info));
455 if (rc)
456 {
457 DosClose(File);
458 return rc;
459 }
460 cb = Info.cbFile;
461
462#elif defined(__WIN__)
463 SECURITY_ATTRIBUTES SecAttr;
464 DWORD High;
465 DWORD Low;
466 int rc;
467 HANDLE File;
468 off_t cb;
469
470 SecAttr.bInheritHandle = FALSE;
471 SecAttr.lpSecurityDescriptor = NULL;
472 SecAttr.nLength = 0;
473 File = CreateFile(pszFilename, GENERIC_READ, FILE_SHARE_READ, &SecAttr, OPEN_ALWAYS, 0, NULL);
474 if (File == INVALID_HANDLE_VALUE)
475 return GetLastError();
476
477 SetLastError(0);
478 Low = GetFileSize(File, &High);
479 rc = GetLastError();
480 if (rc)
481 {
482 CloseHandle(File);
483 return rc;
484 }
485 cb = ((off_t)High << 32) | Low;
486
487#else
488# error "port me"
489#endif
490
491
492 /*
493 * Allocate the reader instance.
494 */
[2828]495 cchFilename = kLdrHlpStrLen(pszFilename);
[2825]496 pRdrFile = (PKLDRRDRFILE)kldrHlpAlloc(sizeof(*pRdrFile) + cchFilename);
497 if (!pRdrFile)
498#if defined(__OS2__)
499 {
500 DosClose(File);
501 return ERROR_NOT_ENOUGH_MEMORY;
502 }
503#elif defined(__WIN__)
504 {
505 CloseHandle(File);
506 return ERROR_NOT_ENOUGH_MEMORY;
507 }
508#else
509# error "port me"
510#endif
511
512 /*
513 * Initialize it and return successfully.
514 */
515 pRdrFile->Core.pOps = &g_kLdrRdrFileOps;
516 pRdrFile->File = File;
517 pRdrFile->off = 0;
[2828]518 kLdrHlpMemCopy(&pRdrFile->szFilename[0], pszFilename, cchFilename + 1);
[2825]519
520 *ppRdr = &pRdrFile->Core;
521 return 0;
522}
523
Note: See TracBrowser for help on using the repository browser.