File: loadfile.inc

package info (click to toggle)
libhtml-template-pro-perl 0.9524-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,512 kB
  • sloc: ansic: 1,841; perl: 1,474; yacc: 404; pascal: 118; makefile: 6
file content (171 lines) | stat: -rw-r--r-- 4,891 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* -*- c -*- 
 * File: loadfile.h
 * Author: Igor Vlasenko <vlasenko@imath.kiev.ua>
 * Created: Thu Sep  8 17:16:48 2005
 *
 * $Id$
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef USE_MMAP

#ifdef WIN32
/* 
 * the win32 code of Viacheslav Sheveliov <slavash@aha.ru>
 * viy: should work for win64 too.
 */

#include <windows.h>
#include <stdio.h>

static PSTRING mmap_load_file(const char *filepath) {
        PSTRING memarea = { NULL, NULL };
        HANDLE hFile, hMapObject = NULL;

        hFile = CreateFile(
                TEXT(filepath), 
                GENERIC_READ, 
                FILE_SHARE_READ, 
                NULL,                      
                OPEN_EXISTING, 
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 
                NULL
        );

        if (hFile != INVALID_HANDLE_VALUE) {
                hMapObject = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);

                if (hMapObject) {
                        // Get a pointer to the file-mapped shared memory.
                        LPCTSTR lpvMem = (LPTSTR) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0);

                        if (lpvMem) {       
                                // Everything OK!

                                memarea.begin = (char *) lpvMem;
                                memarea.endnext = memarea.begin + GetFileSize(hFile, NULL);
                                // After MapViewOfFile we don't need file handles no more.
                                // Undocumented, but it works! (In read-only mode?)
                                CloseHandle(hMapObject);
                                CloseHandle(hFile);

                                return memarea;

                        }
                }
        }

        // Something goes wrong

        {
                // Save last error code, before any system call
                DWORD dwLastError = GetLastError();

                // Report error, if file size != 0
                // Mapping of zero-length file cause CreateFileMapping to fail.
                // So skip error messages in this case.
                if (hFile == INVALID_HANDLE_VALUE && GetFileSize(hFile, NULL) != 0)
                        fprintf(stderr, "Could not open file '%s'. (system error#%ld)\n", filepath, dwLastError);

        }
        // Close all opened handles
        if (hMapObject) CloseHandle(hMapObject);
        if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);  

        return memarea;
}

/* we use function, not define, because someday we may need its address */
static int mmap_unload_file(PSTRING memarea) { return UnmapViewOfFile((void*) memarea.begin) ? 0 : -1; };
/* define mmap_unload_file(map) (UnmapViewOfFile((LPCVOID) map.begin) ? 0 : -1) */

#else /* unix, sweet unix :) */
#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_SYS_STAT_H)

/* # define NULL 0 */
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>  /* open  */
#include <unistd.h> /* close */

static 
PSTRING 
mmap_load_file (const char* filepath) {
  int fd;
  struct stat st;
  size_t size_in_bytes;
  PSTRING memarea={NULL,NULL};
  fd = open(filepath, O_RDONLY);
  if (fd == -1) return memarea; /* {NULL,NULL} */
  fstat(fd, &st);
  size_in_bytes = st.st_size;
  /* mmap size_in_bytes+1 to avoid crash with empty file */
  memarea.begin = (char *) mmap(0, size_in_bytes+1,  PROT_READ,  MAP_SHARED, fd, 0);
  close(fd);
  memarea.endnext=memarea.begin+size_in_bytes;
  return memarea;
}

static 
int 
mmap_unload_file (PSTRING memarea) {
  /* destroying */
  return munmap((void *)memarea.begin, memarea.endnext-memarea.begin);
}

#endif /* UNIX */
#endif /* WIN32 */

#else 
/*
 * system seems to have no mmap ;
 * we use standard C buffered read
 */
#include <stdio.h> 
static 
PSTRING 
mmap_load_file (const char* filepath) {
  FILE *stream;
  size_t size_in_bytes=0;
  size_t realsize;
  size_t chunksize=4096;
  size_t memsize=chunksize;
  PSTRING memarea={NULL,NULL};
  char* writepoint;
  /* text mode for HTML::Template compatibility */
  stream = fopen(filepath, "r");
  if (stream == NULL) return memarea; /* {NULL,NULL} */
  /* mmap size_in_bytes+1 to avoid crash with empty file */
  memarea.begin=(const char*) malloc(memsize+1);
  writepoint=(char*)memarea.begin;

  while (1) {
    realsize=fread(writepoint, 1, chunksize, stream);
    size_in_bytes+=realsize;
    if (realsize==chunksize) {
      writepoint+=chunksize;
      if (size_in_bytes+chunksize>memsize) {
	memsize*=2;
	memarea.begin=(char*) realloc((char*)memarea.begin, memsize+1);
	writepoint=((char*)memarea.begin)+size_in_bytes;
      }
    } else {
      fclose(stream);
      memarea.endnext=memarea.begin+size_in_bytes;
      return memarea;
    }
  }
}

static 
int 
mmap_unload_file (PSTRING memarea) {
  /* destroying */
  free((char*)memarea.begin);
  return 0;
}

#endif /* USE_MMAP */