source: trunk/kLdr/kLdrRdrFile.c@ 2826

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

keyword expansion: Id

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