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
Line 
1/* $Id: kLdrRdrFile.c 2857 2006-11-05 04:12:13Z bird $ */
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*******************************************************************************/
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);
88static int kldrRdrFileRefreshMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile);
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);
91static size_t kldrRdrFilePageSize(PKLDRRDR pRdr);
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,
117 kldrRdrFileName,
118 kldrRdrFilePageSize,
119 kldrRdrFilePrepare,
120 kldrRdrFileMap,
121 kldrRdrFileRefreshMap,
122 kldrRdrFileProtect,
123 kldrRdrFileUnmap,
124 kldrRdrFileUnprepare,
125 kldrRdrFileDone,
126 42
127};
128
129
130/** @copydoc KLDRRDR::pfnDone */
131static void kldrRdrFileDone(PKLDRRDR pRdr)
132{
133}
134
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
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
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
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
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 {
443 char *psz = (char *)kLdrHlpAllocA(cchFilename + 1);
444 kLdrHlpMemCopy(psz, pszFilename, cchFilename + 1);
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 */
495 cchFilename = kLdrHlpStrLen(pszFilename);
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;
518 kLdrHlpMemCopy(&pRdrFile->szFilename[0], pszFilename, cchFilename + 1);
519
520 *ppRdr = &pRdrFile->Core;
521 return 0;
522}
523
Note: See TracBrowser for help on using the repository browser.