source: trunk/kLdr/kLdrRdrFile.c@ 2829

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

Mapping prototypes.

  • Property svn:keywords set to Id
File size: 12.3 KB
RevLine 
[2826]1/* $Id: kLdrRdrFile.c 2829 2006-10-23 17:04:04Z 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);
88static int kldrRdrFileMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile);
89static int kldrRdrFilePrepare(PKLDRRDR pRdr, void **ppv, size_t cb, unsigned fFixed);
[2825]90static const char *kldrRdrFileName(PKLDRRDR pRdr);
91static off_t kldrRdrFileTell(PKLDRRDR pRdr);
92static off_t kldrRdrFileSize(PKLDRRDR pRdr);
93static int kldrRdrFileAllUnmap(PKLDRRDR pRdr, const void *pvBits);
94static int kldrRdrFileAllMap(PKLDRRDR pRdr, const void **ppvBits);
95static int kldrRdrFileRead(PKLDRRDR pRdr, void *pvBuf, size_t cb, off_t off);
96static int kldrRdrFileDestroy(PKLDRRDR pRdr);
97static int kldrRdrFileCreate(PPKLDRRDR ppRdr, const char *pszFilename);
98
99
100/*******************************************************************************
101* Global Variables *
102*******************************************************************************/
103/** Native file provider operations. */
104const KLDRRDROPS g_kLdrRdrFileOps =
105{
106 "native file",
107 NULL,
108 kldrRdrFileCreate,
109 kldrRdrFileDestroy,
110 kldrRdrFileRead,
111 kldrRdrFileAllMap,
112 kldrRdrFileAllUnmap,
113 kldrRdrFileSize,
114 kldrRdrFileTell,
[2829]115 kldrRdrFileName,
116 kldrRdrFilePrepare,
117 kldrRdrFileMap,
118 kldrRdrFileProtect,
119 kldrRdrFileUnmap,
120 kldrRdrFileUnprepare,
121 kldrRdrFileDone,
122 42
[2825]123};
124
125
[2829]126/** @copydoc KLDRRDR::pfnDone */
127static void kldrRdrFileDone(PKLDRRDR pRdr)
128{
129}
[2825]130
[2829]131/** @copydoc KLDRRDR::pfnUnprepare */
132static int kldrRdrFileUnprepare(PKLDRRDR pRdr, void *pv, size_t cb)
133{
134 return -1;
135}
136
137
138/** @copydoc KLDRRDR::pfnUnmap */
139static int kldrRdrFileUnmap(PKLDRRDR pRdr, void *pv, size_t cb)
140{
141 return -1;
142}
143
144
145/** @copydoc KLDRRDR::pfnProtect */
146static int kldrRdrFileProtect(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt)
147{
148 return -1;
149}
150
151
152/** @copydoc KLDRRDR::pfnMap */
153static int kldrRdrFileMap(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile)
154{
155 return -1;
156}
157
158
159/** @copydoc KLDRRDR:pfnPrepare */
160static int kldrRdrFilePrepare(PKLDRRDR pRdr, void **ppv, size_t cb, unsigned fFixed)
161{
162#ifdef __OS2__
163
164
165#elif defined(__WIN__)
166
167#else
168# error "port me."
169#endif
170 return -1;
171}
172
173
[2825]174/** @copydoc KLDRRDR::pfnName */
175static const char *kldrRdrFileName(PKLDRRDR pRdr)
176{
177 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
178 return &pRdrFile->szFilename[0];
179}
180
181
182/** @copydoc KLDRRDR::pfnTell */
183static off_t kldrRdrFileTell(PKLDRRDR pRdr)
184{
185 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
186
187 /*
188 * If the offset is undefined, try figure out what it is.
189 */
190 if (pRdrFile->off == -1)
191 {
192#ifdef __OS2__
193 ULONG ulNew;
194 APIRET rc = DosSetFilePtr(pRdrFile->File, 0, FILE_CURRENT, &ulNew);
195 if (rc)
196 return -1;
197 pRdrFile->off = ulNew;
198
199#elif defined(__WIN__)
200 LONG offHigh = 0;
201 LONG offLow;
202 int rc;
203
204 SetLastError(0);
205 offLow = SetFilePointer(pRdrFile->File, 0, &offHigh, FILE_BEGIN);
206 rc = GetLastError();
207 if (rc)
208 return -1;
209 pRdrFile->off = ((off_t)offHigh << 32) | offLow;
210
211#else
212# error "port me."
213#endif
214 }
215 return pRdrFile->off;
216}
217
218
219/** @copydoc KLDRRDR::pfnSize */
220static off_t kldrRdrFileSize(PKLDRRDR pRdr)
221{
222 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
223 return pRdrFile->cb;
224}
225
226
227/** @copydoc KLDRRDR::pfnAllUnmap */
228static int kldrRdrFileAllUnmap(PKLDRRDR pRdr, const void *pvBits)
229{
230 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
231
232 /* check for underflow */
233 if (pRdrFile->cMappings <= 0)
234#if defined(__OS2__) || defined(__WIN__)
235 return ERROR_INVALID_PARAMETER;
236#else
237# error "port me"
238#endif
239
240 /* decrement usage counter, free mapping if no longer in use. */
241 if (!--pRdrFile->cMappings)
242 {
243 kldrHlpFree(pRdrFile->pvMapping);
244 pRdrFile->pvMapping = NULL;
245 }
246
247 return 0;
248}
249
250
251/** @copydoc KLDRRDR::pfnAllMap */
252static int kldrRdrFileAllMap(PKLDRRDR pRdr, const void **ppvBits)
253{
254 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
255
256 /*
257 * Do we need to map it?
258 */
259 if (!pRdrFile->pvMapping)
260 {
261 int rc;
262 off_t cb = pRdrFile->Core.pOps->pfnSize(pRdr);
263
264 pRdrFile->pvMapping = kldrHlpAlloc(cb);
265 if (!pRdrFile->pvMapping)
266#if defined(__OS2__) || defined(__WIN__)
267 return ERROR_NOT_ENOUGH_MEMORY;
268#else
269# error "port me"
270#endif
271 rc = pRdrFile->Core.pOps->pfnRead(pRdr, pRdrFile->pvMapping, cb, 0);
272 if (rc)
273 {
274 kldrHlpFree(pRdrFile->pvMapping);
275 pRdrFile->pvMapping = NULL;
276 return rc;
277 }
278 pRdrFile->cMappings = 0;
279 }
280
281 pRdrFile->cMappings++;
282 return 0;
283}
284
285
286/** @copydoc KLDRRDR::pfnRead */
287static int kldrRdrFileRead(PKLDRRDR pRdr, void *pvBuf, size_t cb, off_t off)
288{
289 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
290
291 /*
292 * Do a seek if needed.
293 */
294 if (pRdrFile->off != off)
295 {
296#ifdef __OS2__
297 ULONG ulNew;
298 APIRET rc = DosSetFilePtr(pRdrFile->File, off, FILE_BEGIN, &ulNew);
299 if (rc)
300 {
301 pRdrFile->off = -1;
302 return rc;
303 }
304
305#elif defined(__WIN__)
306 LONG offHigh = (LONG)(off >> 32);
307 LONG offLow = SetFilePointer(pRdrFile->File, (LONG)off, &offHigh, FILE_BEGIN);
308 if ( offLow != (LONG)off
309 && offHigh != (LONG)(off >> 32))
310 {
311 int rc = GetLastError();
312 if (!rc)
313 rc = ERROR_GEN_FAILURE;
314 pRdrFile->off = -1;
315 return rc;
316 }
317
318#else
319# error "port me."
320#endif
321 }
322
323 /*
324 * Do the read.
325 */
326#ifdef __OS2__
327 {
328 ULONG cbRead = 0;
329 APIRET rc = DosRead(pRdrFile->File, pvBuf, cb, &cbRead);
330 if (rc)
331 {
332 pRdrFile->off = -1;
333 return rc;
334 }
335 if (cbRead != cb)
336 {
337 pRdrFile->off = -1;
338 return ERROR_GEN_FAILURE;
339 }
340 }
341
342#elif defined(__WIN__)
343 {
344 DWORD cbRead = 0;
345 if (!ReadFile(pRdrFile->File, pvBuf, cb, &cbRead, NULL))
346 {
347 int rc = GetLastError();
348 if (!rc)
349 rc = ERROR_GEN_FAILURE;
350 pRdrFile->off = -1;
351 return rc;
352 }
353 if (cbRead != cb)
354 {
355 pRdrFile->off = -1;
356 return ERROR_GEN_FAILURE;
357 }
358 }
359
360#else
361# error "port me."
362#endif
363
364 pRdrFile->off = off + cb;
365 return 0;
366}
367
368
369/** @copydoc KLDRRDR::pfnDestroy */
370static int kldrRdrFileDestroy(PKLDRRDR pRdr)
371{
372 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
373 int rc;
374#ifdef __OS2__
375 rc = DosClose(pRdrFile->File);
376
377#elif defined(__WIN__)
378 if (!CloseHandle(pRdrFile->File))
379 rc = GetLastError();
380
381#else
382# error "port me"
383#endif
384
385 if (pRdrFile->pvMapping)
386 {
387 kldrHlpFree(pRdrFile->pvMapping);
388 pRdrFile->pvMapping = NULL;
389 }
390
391 kldrHlpFree(pRdr);
392 return rc;
393}
394
395
396/** @copydoc KLDRRDROPS::pfnCreate */
397static int kldrRdrFileCreate(PPKLDRRDR ppRdr, const char *pszFilename)
398{
399 size_t cchFilename;
400 PKLDRRDRFILE pRdrFile;
401
402 /*
403 * Open the file and determin its size.
404 */
405#ifdef __OS2__
406 ULONG ulAction = 0;
407 FILESTATUS3 Info;
408 APIRET rc;
409 HFILE File = 0;
410 off_t cb;
411
412 if ((uintptr_t)pszFilename >= 0x20000000)
413 {
[2828]414 char *psz = (char *)kLdrHlpAllocA(cchFilename + 1);
415 kLdrHlpMemCopy(psz, pszFilename, cchFilename + 1);
[2825]416 pszFilename = psz;
417 }
418 rc = DosOpen((PCSZ)pszFilename, &File, &ulAction, 0, FILE_NORMAL,
419 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
420 OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY | OPEN_FLAGS_RANDOMSEQUENTIAL,
421 NULL);
422 if (rc)
423 return rc;
424
425 rc = DosQueryFileInfo(File, FIL_STANDARD, &Info, sizeof(Info));
426 if (rc)
427 {
428 DosClose(File);
429 return rc;
430 }
431 cb = Info.cbFile;
432
433#elif defined(__WIN__)
434 SECURITY_ATTRIBUTES SecAttr;
435 DWORD High;
436 DWORD Low;
437 int rc;
438 HANDLE File;
439 off_t cb;
440
441 SecAttr.bInheritHandle = FALSE;
442 SecAttr.lpSecurityDescriptor = NULL;
443 SecAttr.nLength = 0;
444 File = CreateFile(pszFilename, GENERIC_READ, FILE_SHARE_READ, &SecAttr, OPEN_ALWAYS, 0, NULL);
445 if (File == INVALID_HANDLE_VALUE)
446 return GetLastError();
447
448 SetLastError(0);
449 Low = GetFileSize(File, &High);
450 rc = GetLastError();
451 if (rc)
452 {
453 CloseHandle(File);
454 return rc;
455 }
456 cb = ((off_t)High << 32) | Low;
457
458#else
459# error "port me"
460#endif
461
462
463 /*
464 * Allocate the reader instance.
465 */
[2828]466 cchFilename = kLdrHlpStrLen(pszFilename);
[2825]467 pRdrFile = (PKLDRRDRFILE)kldrHlpAlloc(sizeof(*pRdrFile) + cchFilename);
468 if (!pRdrFile)
469#if defined(__OS2__)
470 {
471 DosClose(File);
472 return ERROR_NOT_ENOUGH_MEMORY;
473 }
474#elif defined(__WIN__)
475 {
476 CloseHandle(File);
477 return ERROR_NOT_ENOUGH_MEMORY;
478 }
479#else
480# error "port me"
481#endif
482
483 /*
484 * Initialize it and return successfully.
485 */
486 pRdrFile->Core.pOps = &g_kLdrRdrFileOps;
487 pRdrFile->File = File;
488 pRdrFile->off = 0;
[2828]489 kLdrHlpMemCopy(&pRdrFile->szFilename[0], pszFilename, cchFilename + 1);
[2825]490
491 *ppRdr = &pRdrFile->Core;
492 return 0;
493}
494
Note: See TracBrowser for help on using the repository browser.