source: trunk/kLdr/kLdrRdrFile.c@ 2858

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

bugfixing - dinner break.

  • Property svn:keywords set to Id
File size: 13.8 KB
Line 
1/* $Id: kLdrRdrFile.c 2858 2006-11-06 00:23:14Z 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_CURRENT);
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;
328
329 rc = DosSetFilePtr(pRdrFile->File, off, FILE_BEGIN, &ulNew);
330 if (rc)
331 {
332 pRdrFile->off = -1;
333 return rc;
334 }
335
336#elif defined(__WIN__)
337 LONG offHigh;
338 LONG offLow;
339
340 offHigh = sizeof(off_t) == 4 ? 0 : (off >> 32);
341 offLow = SetFilePointer(pRdrFile->File, (LONG)off, &offHigh, FILE_BEGIN);
342 if ( offLow != (LONG)off
343 || offHigh != (LONG)(sizeof(off_t) == 4 ? 0 : (off >> 32)))
344 {
345 int rc = GetLastError();
346 if (!rc)
347 rc = ERROR_GEN_FAILURE;
348 pRdrFile->off = -1;
349 return rc;
350 }
351
352#else
353# error "port me."
354#endif
355 }
356
357 /*
358 * Do the read.
359 */
360#ifdef __OS2__
361 {
362 ULONG cbRead = 0;
363 APIRET rc = DosRead(pRdrFile->File, pvBuf, cb, &cbRead);
364 if (rc)
365 {
366 pRdrFile->off = -1;
367 return rc;
368 }
369 if (cbRead != cb)
370 {
371 pRdrFile->off = -1;
372 return ERROR_GEN_FAILURE;
373 }
374 }
375
376#elif defined(__WIN__)
377 {
378 DWORD cbRead = 0;
379 if (!ReadFile(pRdrFile->File, pvBuf, cb, &cbRead, NULL))
380 {
381 int rc = GetLastError();
382 if (!rc)
383 rc = ERROR_GEN_FAILURE;
384 pRdrFile->off = -1;
385 return rc;
386 }
387 if (cbRead != cb)
388 {
389 pRdrFile->off = -1;
390 return ERROR_GEN_FAILURE;
391 }
392 }
393
394#else
395# error "port me."
396#endif
397
398 pRdrFile->off = off + cb;
399 return 0;
400}
401
402
403/** @copydoc KLDRRDR::pfnDestroy */
404static int kldrRdrFileDestroy(PKLDRRDR pRdr)
405{
406 PKLDRRDRFILE pRdrFile = (PKLDRRDRFILE)pRdr;
407 int rc;
408#ifdef __OS2__
409 rc = DosClose(pRdrFile->File);
410
411#elif defined(__WIN__)
412 rc = 0;
413 if (!CloseHandle(pRdrFile->File))
414 rc = GetLastError();
415
416#else
417# error "port me"
418#endif
419
420 if (pRdrFile->pvMapping)
421 {
422 kldrHlpFree(pRdrFile->pvMapping);
423 pRdrFile->pvMapping = NULL;
424 }
425
426 kldrHlpFree(pRdr);
427 return rc;
428}
429
430
431/** @copydoc KLDRRDROPS::pfnCreate */
432static int kldrRdrFileCreate(PPKLDRRDR ppRdr, const char *pszFilename)
433{
434 size_t cchFilename;
435 PKLDRRDRFILE pRdrFile;
436
437 /*
438 * Open the file and determin its size.
439 */
440#ifdef __OS2__
441 ULONG ulAction = 0;
442 FILESTATUS3 Info;
443 APIRET rc;
444 HFILE File = 0;
445 off_t cb;
446 char szFilename[CCHMAXPATH];
447
448 if ((uintptr_t)pszFilename >= 0x20000000)
449 {
450 char *psz = (char *)kLdrHlpAllocA(cchFilename + 1);
451 kLdrHlpMemCopy(psz, pszFilename, cchFilename + 1);
452 pszFilename = psz;
453 }
454 rc = DosOpen((PCSZ)pszFilename, &File, &ulAction, 0, FILE_NORMAL,
455 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
456 OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY | OPEN_FLAGS_RANDOMSEQUENTIAL,
457 NULL);
458 if (rc)
459 return rc;
460
461 rc = DosQueryPathInfo(pszFilename, FIL_QUERYFULLNAME, szFilename, sizeof(szFilename));
462 if (rc)
463 {
464 DosClose(File);
465 return rc;
466 }
467
468 rc = DosQueryFileInfo(File, FIL_STANDARD, &Info, sizeof(Info));
469 if (rc)
470 {
471 DosClose(File);
472 return rc;
473 }
474 cb = Info.cbFile;
475
476#elif defined(__WIN__)
477 SECURITY_ATTRIBUTES SecAttr;
478 DWORD High;
479 DWORD Low;
480 int rc;
481 HANDLE File;
482 off_t cb;
483 char szFilename[MAX_PATH];
484
485 SecAttr.bInheritHandle = FALSE;
486 SecAttr.lpSecurityDescriptor = NULL;
487 SecAttr.nLength = 0;
488 File = CreateFile(pszFilename, GENERIC_READ, FILE_SHARE_READ, &SecAttr, OPEN_ALWAYS, 0, NULL);
489 if (File == INVALID_HANDLE_VALUE)
490 return GetLastError();
491
492 if (!GetFullPathName(pszFilename, sizeof(szFilename), szFilename, NULL))
493 {
494 rc = GetLastError();
495 CloseHandle(File);
496 return rc;
497 }
498
499 SetLastError(0);
500 Low = GetFileSize(File, &High);
501 rc = GetLastError();
502 if (rc)
503 {
504 CloseHandle(File);
505 return rc;
506 }
507 if (sizeof(off_t) == 4)
508 cb = High ? 0x7fffffff : Low;
509 else
510 cb = ((off_t)High << 32) | Low;
511
512#else
513# error "port me"
514#endif
515
516
517 /*
518 * Allocate the reader instance.
519 */
520 cchFilename = kLdrHlpStrLen(szFilename);
521 pRdrFile = (PKLDRRDRFILE)kldrHlpAlloc(sizeof(*pRdrFile) + cchFilename);
522 if (!pRdrFile)
523#if defined(__OS2__)
524 {
525 DosClose(File);
526 return ERROR_NOT_ENOUGH_MEMORY;
527 }
528#elif defined(__WIN__)
529 {
530 CloseHandle(File);
531 return ERROR_NOT_ENOUGH_MEMORY;
532 }
533#else
534# error "port me"
535#endif
536
537 /*
538 * Initialize it and return successfully.
539 */
540 pRdrFile->Core.u32Magic = KLDRRDR_MAGIC;
541 pRdrFile->Core.pOps = &g_kLdrRdrFileOps;
542 pRdrFile->File = File;
543 pRdrFile->cb = cb;
544 pRdrFile->off = 0;
545 kLdrHlpMemCopy(&pRdrFile->szFilename[0], szFilename, cchFilename + 1);
546
547 *ppRdr = &pRdrFile->Core;
548 return 0;
549}
550
Note: See TracBrowser for help on using the repository browser.