ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Urlader/urlib.c
Revision: 1.1
Committed: Fri Dec 30 23:34:08 2011 UTC (12 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "urlib.h"
2
3 #include <fcntl.h>
4
5 #ifdef _WIN32
6
7 #include <windows.h>
8 //#include <winbase.h>
9 #include <shlobj.h>
10 #include <shlwapi.h>
11 #include <wininet.h>
12
13 static DWORD dword;
14
15 #define u_handle HANDLE
16 #define u_invalid_handle 0
17 #define u_valid(handle) (!!handle)
18
19 #define u_setenv(name,value) SetEnvironmentVariable (name, value)
20 #define u_mkdir(path) !CreateDirectory (path, NULL)
21 #define u_chdir(path) !SetCurrentDirectory (path)
22 #define u_rename(fr,to) !MoveFile (fr, to)
23 #define u_open(path) CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)
24 #define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)
25 #define u_creat(path,exec) CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)
26 #define u_close(handle) CloseHandle (handle)
27 #define u_append(path,add) PathAppend (path, add)
28 #define u_write(handle,data,len) (WriteFile (handle, data, len, &dword, 0) ? dword : -1)
29
30 #define u_fsync(handle) FlushFileBuffers (handle)
31 #define u_sync()
32
33 #define u_lockfile(path) CreateFile (path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
34 #define u_cloexec(handle)
35
36 #else
37
38 #define _GNU_SOURCE 1
39 #define _BSD_SOURCE 1
40 // the above increases our chances of getting MAP_ANONYMOUS
41
42 #include <sys/mman.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46 #include <pwd.h>
47
48 #if defined (MAP_ANON) && !defined (MAP_ANONYMOUS)
49 #define MAP_ANONYMOUS MAP_ANON
50 #endif
51
52 #ifdef PATH_MAX
53 #define MAX_PATH (PATH_MAX < 4096 ? 4096 : PATH_MAX)
54 #else
55 #define MAX_PATH 4096
56 #endif
57
58 #define u_handle int
59 #define u_invalid_handle -1
60 #define u_valid(fd) ((fd) >= 0)
61
62 #define u_setenv(name,value) setenv (name, value, 1)
63 #define u_mkdir(path) mkdir (path, 0777)
64 #define u_chdir(path) chdir (path)
65 #define u_rename(fr,to) rename (fr, to)
66 #define u_open(path) open (path, O_RDONLY)
67 #define u_creat(path,exec) open (path, O_WRONLY | O_CREAT | O_TRUNC, (exec) ? 0777 : 0666)
68 #define u_close(handle) close (handle)
69 #define u_append(path,add) strcat (strcat (path, "/"), add)
70 #define u_write(handle,data,len) write (handle, data, len)
71
72 // on a mostly idle system, a sync at the end is certainly faster, hope for the best
73 #define u_fsync(handle)
74 #define u_sync() sync ()
75
76 #define u_lockfile(path) open (path, O_RDWR | O_CREAT, 0666)
77 #define u_cloexec(handle) fcntl (handle, F_SETFD, FD_CLOEXEC)
78
79 #endif
80
81 #define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1])
82 #define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3])
83
84 static void *
85 u_malloc (unsigned int size)
86 {
87 void *addr;
88
89 #ifdef _WIN32
90 HANDLE handle = CreateFileMapping (0, 0, PAGE_READWRITE, 0, size, NULL);
91
92 if (!handle)
93 return 0;
94
95 addr = MapViewOfFile (handle, FILE_MAP_WRITE, 0, 0, size);
96
97 CloseHandle (handle);
98 #elif defined (MAP_ANONYMOUS)
99 addr = mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
100
101 if (addr == (void *)-1)
102 addr = 0;
103 #else
104 addr = malloc (size);
105 #endif
106
107 return addr;
108 }
109
110 static void
111 u_free (void *addr, unsigned int size)
112 {
113 #ifdef _WIN32
114 UnmapViewOfFile (addr);
115 #elif defined (MAP_ANONYMOUS)
116 munmap (addr, size);
117 #else
118 free (addr);
119 #endif
120 }
121
122 static void *
123 u_mmap (u_handle h, unsigned int size)
124 {
125 void *addr;
126
127 #ifdef _WIN32
128 HANDLE handle = CreateFileMapping (h, 0, PAGE_READONLY, 0, size, NULL);
129
130 if (!handle)
131 return 0;
132
133 addr = MapViewOfFile (handle, FILE_MAP_READ, 0, 0, size);
134
135 CloseHandle (handle);
136 #else
137 addr = mmap (0, size, PROT_READ, MAP_SHARED, h, 0);
138
139 if (addr == (void *)-1)
140 addr = 0;
141 #endif
142
143 return addr;
144 }
145
146 static void
147 u_munmap (void *addr, unsigned int len)
148 {
149 #ifdef _WIN32
150 UnmapViewOfFile (addr);
151 #else
152 munmap (addr, len);
153 #endif
154 }
155 static u_handle
156 u_lock (const char *path, int excl, int dowait)
157 {
158 u_handle h;
159
160 h = u_lockfile (path);
161 if (!u_valid (h))
162 return h;
163
164 u_cloexec (h);
165
166 for (;;)
167 {
168 int success;
169
170 // acquire the lock
171 #ifdef _WIN32
172 OVERLAPPED ov = { 0 };
173
174 success = LockFileEx (h,
175 (excl ? LOCKFILE_EXCLUSIVE_LOCK : 0)
176 | (dowait ? 0 : LOCKFILE_FAIL_IMMEDIATELY),
177 0,
178 1, 0,
179 &ov);
180 #else
181 struct flock lck = { 0 };
182
183 lck.l_type = excl ? F_WRLCK : F_RDLCK;
184 lck.l_whence = SEEK_SET;
185 lck.l_len = 1;
186
187 success = !fcntl (h, dowait ? F_SETLKW : F_SETLK, &lck);
188 #endif
189
190 if (!success)
191 break;
192
193 // we have the lock, now verify that the lockfile still exists
194
195 #ifdef _WIN32
196 // apparently, we have to open the file to get its info :(
197 BY_HANDLE_FILE_INFORMATION s1, s2;
198 u_handle h2 = u_lockfile (path);
199 if (!u_valid (h))
200 break;
201
202 success = GetFileInformationByHandle (h, &s1)
203 && GetFileInformationByHandle (h2, &s2);
204
205 u_close (h2);
206
207 if (!success)
208 break;
209
210 success = s1.dwVolumeSerialNumber == s2.dwVolumeSerialNumber
211 && s1.nFileIndexHigh == s2.nFileIndexHigh
212 && s1.nFileIndexLow == s2.nFileIndexLow;
213 #else
214 struct stat s1, s2;
215
216 if (fstat (h, &s1) || stat (path, &s2))
217 break;
218
219 success = s1.st_dev == s2.st_dev
220 && s1.st_ino == s2.st_ino;
221 #endif
222
223 if (success)
224 return h; // lock successfully acquired
225
226 // files differ, close and retry - should be very rare
227 u_close (h);
228 }
229
230 // failure
231 u_close (h);
232 return u_invalid_handle;
233 }
234