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
Line 
1/* $Id: kLdrRdrFile.c 2829 2006-10-23 17:04:04Z 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 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);
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,
115 kldrRdrFileName,
116 kldrRdrFilePrepare,
117 kldrRdrFileMap,
118 kldrRdrFileProtect,
119 kldrRdrFileUnmap,
120 kldrRdrFileUnprepare,
121 kldrRdrFileDone,
122 42
123};
124
125
126/** @copydoc KLDRRDR::pfnDone */
127static void kldrRdrFileDone(PKLDRRDR pRdr)
128{
129}
130
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
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 {
414 char *psz = (char *)kLdrHlpAllocA(cchFilename + 1);
415 kLdrHlpMemCopy(psz, pszFilename, cchFilename + 1);
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 */
466 cchFilename = kLdrHlpStrLen(pszFilename);
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;
489 kLdrHlpMemCopy(&pRdrFile->szFilename[0], pszFilename, cchFilename + 1);
490
491 *ppRdr = &pRdrFile->Core;
492 return 0;
493}
494
Note: See TracBrowser for help on using the repository browser.