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
RevLine 
[2826]1/* $Id: kLdrRdrFile.c 2858 2006-11-06 00:23:14Z 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);
[2858]234 offLow = SetFilePointer(pRdrFile->File, 0, &offHigh, FILE_CURRENT);
[2825]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;
[2858]327 APIRET rc;
328
329 rc = DosSetFilePtr(pRdrFile->File, off, FILE_BEGIN, &ulNew);
[2825]330 if (rc)
331 {
332 pRdrFile->off = -1;
333 return rc;
334 }
335
336#elif defined(__WIN__)
[2858]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);
[2825]342 if ( offLow != (LONG)off
[2858]343 || offHigh != (LONG)(sizeof(off_t) == 4 ? 0 : (off >> 32)))
[2825]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__)
[2858]412 rc = 0;
[2825]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__
[2858]441 ULONG ulAction = 0;
442 FILESTATUS3 Info;
443 APIRET rc;
444 HFILE File = 0;
445 off_t cb;
446 char szFilename[CCHMAXPATH];
[2825]447
448 if ((uintptr_t)pszFilename >= 0x20000000)
449 {
[2828]450 char *psz = (char *)kLdrHlpAllocA(cchFilename + 1);
451 kLdrHlpMemCopy(psz, pszFilename, cchFilename + 1);
[2825]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
[2858]461 rc = DosQueryPathInfo(pszFilename, FIL_QUERYFULLNAME, szFilename, sizeof(szFilename));
462 if (rc)
463 {
464 DosClose(File);
465 return rc;
466 }
467
[2825]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;
[2858]483 char szFilename[MAX_PATH];
[2825]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
[2858]492 if (!GetFullPathName(pszFilename, sizeof(szFilename), szFilename, NULL))
493 {
494 rc = GetLastError();
495 CloseHandle(File);
496 return rc;
497 }
498
[2825]499 SetLastError(0);
500 Low = GetFileSize(File, &High);
501 rc = GetLastError();
502 if (rc)
503 {
504 CloseHandle(File);
505 return rc;
506 }
[2858]507 if (sizeof(off_t) == 4)
508 cb = High ? 0x7fffffff : Low;
509 else
510 cb = ((off_t)High << 32) | Low;
[2825]511
512#else
513# error "port me"
514#endif
515
516
517 /*
518 * Allocate the reader instance.
519 */
[2858]520 cchFilename = kLdrHlpStrLen(szFilename);
[2825]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 */
[2858]540 pRdrFile->Core.u32Magic = KLDRRDR_MAGIC;
[2825]541 pRdrFile->Core.pOps = &g_kLdrRdrFileOps;
542 pRdrFile->File = File;
[2858]543 pRdrFile->cb = cb;
[2825]544 pRdrFile->off = 0;
[2858]545 kLdrHlpMemCopy(&pRdrFile->szFilename[0], szFilename, cchFilename + 1);
[2825]546
547 *ppRdr = &pRdrFile->Core;
548 return 0;
549}
550
Note: See TracBrowser for help on using the repository browser.