/src/xpdf-4.03/goo/gfile.cc
Line | Count | Source (jump to first uncovered line) |
1 | | //======================================================================== |
2 | | // |
3 | | // gfile.cc |
4 | | // |
5 | | // Miscellaneous file and directory name manipulation. |
6 | | // |
7 | | // Copyright 1996-2003 Glyph & Cog, LLC |
8 | | // |
9 | | //======================================================================== |
10 | | |
11 | | #include <aconf.h> |
12 | | |
13 | | #ifdef _WIN32 |
14 | | # undef WIN32_LEAN_AND_MEAN |
15 | | # include <windows.h> |
16 | | # include <time.h> |
17 | | # include <direct.h> |
18 | | # include <shobjidl.h> |
19 | | # include <shlguid.h> |
20 | | #else |
21 | | # if !defined(ACORN) |
22 | | # include <sys/types.h> |
23 | | # include <sys/stat.h> |
24 | | # include <fcntl.h> |
25 | | # endif |
26 | | # include <time.h> |
27 | | # include <limits.h> |
28 | | # include <string.h> |
29 | | # if !defined(VMS) && !defined(ACORN) |
30 | | # include <pwd.h> |
31 | | # endif |
32 | | # if defined(VMS) && (__DECCXX_VER < 50200000) |
33 | | # include <unixlib.h> |
34 | | # endif |
35 | | #endif // _WIN32 |
36 | | #include "gmem.h" |
37 | | #include "gmempp.h" |
38 | | #include "GString.h" |
39 | | #include "gfile.h" |
40 | | |
41 | | // Some systems don't define this, so just make it something reasonably |
42 | | // large. |
43 | | #ifndef PATH_MAX |
44 | | #define PATH_MAX 1024 |
45 | | #endif |
46 | | |
47 | | //------------------------------------------------------------------------ |
48 | | |
49 | 108 | GString *getHomeDir() { |
50 | | #ifdef VMS |
51 | | //---------- VMS ---------- |
52 | | return new GString("SYS$LOGIN:"); |
53 | | |
54 | | #elif defined(__EMX__) || defined(_WIN32) |
55 | | //---------- OS/2+EMX and Win32 ---------- |
56 | | char *s; |
57 | | GString *ret; |
58 | | |
59 | | if ((s = getenv("HOME"))) |
60 | | ret = new GString(s); |
61 | | else |
62 | | ret = new GString("."); |
63 | | return ret; |
64 | | |
65 | | #elif defined(ACORN) |
66 | | //---------- RISCOS ---------- |
67 | | return new GString("@"); |
68 | | |
69 | | #else |
70 | | //---------- Unix ---------- |
71 | 108 | char *s; |
72 | 108 | struct passwd *pw; |
73 | 108 | GString *ret; |
74 | | |
75 | 108 | if ((s = getenv("HOME"))) { |
76 | 108 | ret = new GString(s); |
77 | 108 | } else { |
78 | 0 | if ((s = getenv("USER"))) |
79 | 0 | pw = getpwnam(s); |
80 | 0 | else |
81 | 0 | pw = getpwuid(getuid()); |
82 | 0 | if (pw) |
83 | 0 | ret = new GString(pw->pw_dir); |
84 | 0 | else |
85 | 0 | ret = new GString("."); |
86 | 0 | } |
87 | 108 | return ret; |
88 | 108 | #endif |
89 | 108 | } |
90 | | |
91 | 0 | GString *getCurrentDir() { |
92 | 0 | char buf[PATH_MAX+1]; |
93 | |
|
94 | | #if defined(__EMX__) |
95 | | if (_getcwd2(buf, sizeof(buf))) |
96 | | #elif defined(_WIN32) |
97 | | if (GetCurrentDirectoryA(sizeof(buf), buf)) |
98 | | #elif defined(ACORN) |
99 | | if (strcpy(buf, "@")) |
100 | | #else |
101 | 0 | if (getcwd(buf, sizeof(buf))) |
102 | 0 | #endif |
103 | 0 | return new GString(buf); |
104 | 0 | return new GString(); |
105 | 0 | } |
106 | | |
107 | 2.62k | GString *appendToPath(GString *path, const char *fileName) { |
108 | | #if defined(VMS) |
109 | | //---------- VMS ---------- |
110 | | //~ this should handle everything necessary for file |
111 | | //~ requesters, but it's certainly not complete |
112 | | char *p0, *p1, *p2; |
113 | | char *q1; |
114 | | |
115 | | p0 = path->getCString(); |
116 | | p1 = p0 + path->getLength() - 1; |
117 | | if (!strcmp(fileName, "-")) { |
118 | | if (*p1 == ']') { |
119 | | for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ; |
120 | | if (*p2 == '[') |
121 | | ++p2; |
122 | | path->del(p2 - p0, p1 - p2); |
123 | | } else if (*p1 == ':') { |
124 | | path->append("[-]"); |
125 | | } else { |
126 | | path->clear(); |
127 | | path->append("[-]"); |
128 | | } |
129 | | } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) { |
130 | | if (*p1 == ']') { |
131 | | path->insert(p1 - p0, '.'); |
132 | | path->insert(p1 - p0 + 1, fileName, q1 - fileName); |
133 | | } else if (*p1 == ':') { |
134 | | path->append('['); |
135 | | path->append(']'); |
136 | | path->append(fileName, q1 - fileName); |
137 | | } else { |
138 | | path->clear(); |
139 | | path->append(fileName, q1 - fileName); |
140 | | } |
141 | | } else { |
142 | | if (*p1 != ']' && *p1 != ':') |
143 | | path->clear(); |
144 | | path->append(fileName); |
145 | | } |
146 | | return path; |
147 | | |
148 | | #elif defined(_WIN32) |
149 | | //---------- Win32 ---------- |
150 | | GString *tmp; |
151 | | char buf[256]; |
152 | | char *fp; |
153 | | |
154 | | tmp = new GString(path); |
155 | | tmp->append('/'); |
156 | | tmp->append(fileName); |
157 | | GetFullPathNameA(tmp->getCString(), sizeof(buf), buf, &fp); |
158 | | delete tmp; |
159 | | path->clear(); |
160 | | path->append(buf); |
161 | | return path; |
162 | | |
163 | | #elif defined(ACORN) |
164 | | //---------- RISCOS ---------- |
165 | | char *p; |
166 | | int i; |
167 | | |
168 | | path->append("."); |
169 | | i = path->getLength(); |
170 | | path->append(fileName); |
171 | | for (p = path->getCString() + i; *p; ++p) { |
172 | | if (*p == '/') { |
173 | | *p = '.'; |
174 | | } else if (*p == '.') { |
175 | | *p = '/'; |
176 | | } |
177 | | } |
178 | | return path; |
179 | | |
180 | | #elif defined(__EMX__) |
181 | | //---------- OS/2+EMX ---------- |
182 | | int i; |
183 | | |
184 | | // appending "." does nothing |
185 | | if (!strcmp(fileName, ".")) |
186 | | return path; |
187 | | |
188 | | // appending ".." goes up one directory |
189 | | if (!strcmp(fileName, "..")) { |
190 | | for (i = path->getLength() - 2; i >= 0; --i) { |
191 | | if (path->getChar(i) == '/' || path->getChar(i) == '\\' || |
192 | | path->getChar(i) == ':') |
193 | | break; |
194 | | } |
195 | | if (i <= 0) { |
196 | | if (path->getChar(0) == '/' || path->getChar(0) == '\\') { |
197 | | path->del(1, path->getLength() - 1); |
198 | | } else if (path->getLength() >= 2 && path->getChar(1) == ':') { |
199 | | path->del(2, path->getLength() - 2); |
200 | | } else { |
201 | | path->clear(); |
202 | | path->append(".."); |
203 | | } |
204 | | } else { |
205 | | if (path->getChar(i-1) == ':') |
206 | | ++i; |
207 | | path->del(i, path->getLength() - i); |
208 | | } |
209 | | return path; |
210 | | } |
211 | | |
212 | | // otherwise, append "/" and new path component |
213 | | if (path->getLength() > 0 && |
214 | | path->getChar(path->getLength() - 1) != '/' && |
215 | | path->getChar(path->getLength() - 1) != '\\') |
216 | | path->append('/'); |
217 | | path->append(fileName); |
218 | | return path; |
219 | | |
220 | | #else |
221 | | //---------- Unix ---------- |
222 | 2.62k | int i; |
223 | | |
224 | | // appending "." does nothing |
225 | 2.62k | if (!strcmp(fileName, ".")) |
226 | 0 | return path; |
227 | | |
228 | | // appending ".." goes up one directory |
229 | 2.62k | if (!strcmp(fileName, "..")) { |
230 | 0 | for (i = path->getLength() - 2; i >= 0; --i) { |
231 | 0 | if (path->getChar(i) == '/') |
232 | 0 | break; |
233 | 0 | } |
234 | 0 | if (i <= 0) { |
235 | 0 | if (path->getChar(0) == '/') { |
236 | 0 | path->del(1, path->getLength() - 1); |
237 | 0 | } else { |
238 | 0 | path->clear(); |
239 | 0 | path->append(".."); |
240 | 0 | } |
241 | 0 | } else { |
242 | 0 | path->del(i, path->getLength() - i); |
243 | 0 | } |
244 | 0 | return path; |
245 | 0 | } |
246 | | |
247 | | // otherwise, append "/" and new path component |
248 | 2.62k | if (path->getLength() > 0 && |
249 | 2.62k | path->getChar(path->getLength() - 1) != '/') |
250 | 2.62k | path->append('/'); |
251 | 2.62k | path->append(fileName); |
252 | 2.62k | return path; |
253 | 2.62k | #endif |
254 | 2.62k | } |
255 | | |
256 | 0 | GString *grabPath(char *fileName) { |
257 | | #ifdef VMS |
258 | | //---------- VMS ---------- |
259 | | char *p; |
260 | | |
261 | | if ((p = strrchr(fileName, ']'))) |
262 | | return new GString(fileName, p + 1 - fileName); |
263 | | if ((p = strrchr(fileName, ':'))) |
264 | | return new GString(fileName, p + 1 - fileName); |
265 | | return new GString(); |
266 | | |
267 | | #elif defined(__EMX__) || defined(_WIN32) |
268 | | //---------- OS/2+EMX and Win32 ---------- |
269 | | char *p; |
270 | | |
271 | | if ((p = strrchr(fileName, '/'))) |
272 | | return new GString(fileName, (int)(p - fileName)); |
273 | | if ((p = strrchr(fileName, '\\'))) |
274 | | return new GString(fileName, (int)(p - fileName)); |
275 | | if ((p = strrchr(fileName, ':'))) |
276 | | return new GString(fileName, (int)(p + 1 - fileName)); |
277 | | return new GString(); |
278 | | |
279 | | #elif defined(ACORN) |
280 | | //---------- RISCOS ---------- |
281 | | char *p; |
282 | | |
283 | | if ((p = strrchr(fileName, '.'))) |
284 | | return new GString(fileName, p - fileName); |
285 | | return new GString(); |
286 | | |
287 | | #else |
288 | | //---------- Unix ---------- |
289 | 0 | char *p; |
290 | |
|
291 | 0 | if ((p = strrchr(fileName, '/'))) |
292 | 0 | return new GString(fileName, (int)(p - fileName)); |
293 | 0 | return new GString(); |
294 | 0 | #endif |
295 | 0 | } |
296 | | |
297 | 0 | GBool isAbsolutePath(char *path) { |
298 | | #ifdef VMS |
299 | | //---------- VMS ---------- |
300 | | return strchr(path, ':') || |
301 | | (path[0] == '[' && path[1] != '.' && path[1] != '-'); |
302 | | |
303 | | #elif defined(__EMX__) || defined(_WIN32) |
304 | | //---------- OS/2+EMX and Win32 ---------- |
305 | | return path[0] == '/' || path[0] == '\\' || path[1] == ':'; |
306 | | |
307 | | #elif defined(ACORN) |
308 | | //---------- RISCOS ---------- |
309 | | return path[0] == '$'; |
310 | | |
311 | | #else |
312 | | //---------- Unix ---------- |
313 | 0 | return path[0] == '/'; |
314 | 0 | #endif |
315 | 0 | } |
316 | | |
317 | 0 | GString *makePathAbsolute(GString *path) { |
318 | | #ifdef VMS |
319 | | //---------- VMS ---------- |
320 | | char buf[PATH_MAX+1]; |
321 | | |
322 | | if (!isAbsolutePath(path->getCString())) { |
323 | | if (getcwd(buf, sizeof(buf))) { |
324 | | path->insert(0, buf); |
325 | | } |
326 | | } |
327 | | return path; |
328 | | |
329 | | #elif defined(_WIN32) |
330 | | //---------- Win32 ---------- |
331 | | char buf[_MAX_PATH]; |
332 | | char *fp; |
333 | | |
334 | | buf[0] = '\0'; |
335 | | if (!GetFullPathNameA(path->getCString(), _MAX_PATH, buf, &fp)) { |
336 | | path->clear(); |
337 | | return path; |
338 | | } |
339 | | path->clear(); |
340 | | path->append(buf); |
341 | | return path; |
342 | | |
343 | | #elif defined(ACORN) |
344 | | //---------- RISCOS ---------- |
345 | | path->insert(0, '@'); |
346 | | return path; |
347 | | |
348 | | #else |
349 | | //---------- Unix and OS/2+EMX ---------- |
350 | 0 | struct passwd *pw; |
351 | 0 | char buf[PATH_MAX+1]; |
352 | 0 | GString *s; |
353 | 0 | char *p1, *p2; |
354 | 0 | int n; |
355 | |
|
356 | 0 | if (path->getChar(0) == '~') { |
357 | 0 | if (path->getChar(1) == '/' || |
358 | | #ifdef __EMX__ |
359 | | path->getChar(1) == '\\' || |
360 | | #endif |
361 | 0 | path->getLength() == 1) { |
362 | 0 | path->del(0, 1); |
363 | 0 | s = getHomeDir(); |
364 | 0 | path->insert(0, s); |
365 | 0 | delete s; |
366 | 0 | } else { |
367 | 0 | p1 = path->getCString() + 1; |
368 | | #ifdef __EMX__ |
369 | | for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ; |
370 | | #else |
371 | 0 | for (p2 = p1; *p2 && *p2 != '/'; ++p2) ; |
372 | 0 | #endif |
373 | 0 | if ((n = (int)(p2 - p1)) > PATH_MAX) |
374 | 0 | n = PATH_MAX; |
375 | 0 | strncpy(buf, p1, n); |
376 | 0 | buf[n] = '\0'; |
377 | 0 | if ((pw = getpwnam(buf))) { |
378 | 0 | path->del(0, (int)(p2 - p1 + 1)); |
379 | 0 | path->insert(0, pw->pw_dir); |
380 | 0 | } |
381 | 0 | } |
382 | 0 | } else if (!isAbsolutePath(path->getCString())) { |
383 | 0 | if (getcwd(buf, sizeof(buf))) { |
384 | 0 | #ifndef __EMX__ |
385 | 0 | path->insert(0, '/'); |
386 | 0 | #endif |
387 | 0 | path->insert(0, buf); |
388 | 0 | } |
389 | 0 | } |
390 | 0 | return path; |
391 | 0 | #endif |
392 | 0 | } |
393 | | |
394 | 0 | time_t getModTime(char *fileName) { |
395 | | #ifdef _WIN32 |
396 | | //~ should implement this, but it's (currently) only used in xpdf |
397 | | return 0; |
398 | | #else |
399 | 0 | struct stat statBuf; |
400 | |
|
401 | 0 | if (stat(fileName, &statBuf)) { |
402 | 0 | return 0; |
403 | 0 | } |
404 | 0 | return statBuf.st_mtime; |
405 | 0 | #endif |
406 | 0 | } |
407 | | |
408 | | GBool openTempFile(GString **name, FILE **f, |
409 | 0 | const char *mode, const char *ext) { |
410 | | #if defined(_WIN32) |
411 | | //---------- Win32 ---------- |
412 | | char tempPath[MAX_PATH + 1]; |
413 | | GString *s, *s2; |
414 | | FILE *f2; |
415 | | DWORD n; |
416 | | int t, i; |
417 | | |
418 | | // this has the standard race condition problem, but I haven't found |
419 | | // a better way to generate temp file names with extensions on |
420 | | // Windows |
421 | | n = GetTempPathA(sizeof(tempPath), tempPath); |
422 | | if (n > 0 && n <= sizeof(tempPath)) { |
423 | | s = new GString(tempPath); |
424 | | if (tempPath[n-1] != '\\') { |
425 | | s->append('\\'); |
426 | | } |
427 | | } else { |
428 | | s = new GString(".\\"); |
429 | | } |
430 | | s->appendf("xpdf_{0:d}_{1:d}_", |
431 | | (int)GetCurrentProcessId(), (int)GetCurrentThreadId()); |
432 | | t = (int)time(NULL); |
433 | | for (i = 0; i < 1000; ++i) { |
434 | | s2 = GString::format("{0:t}{1:d}", s, t + i); |
435 | | if (ext) { |
436 | | s2->append(ext); |
437 | | } |
438 | | if (!(f2 = fopen(s2->getCString(), "r"))) { |
439 | | if (!(f2 = fopen(s2->getCString(), mode))) { |
440 | | delete s2; |
441 | | delete s; |
442 | | return gFalse; |
443 | | } |
444 | | *name = s2; |
445 | | *f = f2; |
446 | | delete s; |
447 | | return gTrue; |
448 | | } |
449 | | fclose(f2); |
450 | | delete s2; |
451 | | } |
452 | | delete s; |
453 | | return gFalse; |
454 | | #elif defined(VMS) || defined(__EMX__) || defined(ACORN) |
455 | | //---------- non-Unix ---------- |
456 | | char *s; |
457 | | |
458 | | // There is a security hole here: an attacker can create a symlink |
459 | | // with this file name after the tmpnam call and before the fopen |
460 | | // call. I will happily accept fixes to this function for non-Unix |
461 | | // OSs. |
462 | | if (!(s = tmpnam(NULL))) { |
463 | | return gFalse; |
464 | | } |
465 | | *name = new GString(s); |
466 | | if (ext) { |
467 | | (*name)->append(ext); |
468 | | } |
469 | | if (!(*f = fopen((*name)->getCString(), mode))) { |
470 | | delete (*name); |
471 | | *name = NULL; |
472 | | return gFalse; |
473 | | } |
474 | | return gTrue; |
475 | | #else |
476 | | //---------- Unix ---------- |
477 | 0 | char *s; |
478 | 0 | int fd; |
479 | |
|
480 | 0 | if (ext) { |
481 | 0 | #if HAVE_MKSTEMPS |
482 | 0 | if ((s = getenv("TMPDIR"))) { |
483 | 0 | *name = new GString(s); |
484 | 0 | } else { |
485 | 0 | *name = new GString("/tmp"); |
486 | 0 | } |
487 | 0 | (*name)->append("/XXXXXX")->append(ext); |
488 | 0 | fd = mkstemps((*name)->getCString(), (int)strlen(ext)); |
489 | | #else |
490 | | if (!(s = tmpnam(NULL))) { |
491 | | return gFalse; |
492 | | } |
493 | | *name = new GString(s); |
494 | | (*name)->append(ext); |
495 | | fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600); |
496 | | #endif |
497 | 0 | } else { |
498 | 0 | #if HAVE_MKSTEMP |
499 | 0 | if ((s = getenv("TMPDIR"))) { |
500 | 0 | *name = new GString(s); |
501 | 0 | } else { |
502 | 0 | *name = new GString("/tmp"); |
503 | 0 | } |
504 | 0 | (*name)->append("/XXXXXX"); |
505 | 0 | fd = mkstemp((*name)->getCString()); |
506 | | #else // HAVE_MKSTEMP |
507 | | if (!(s = tmpnam(NULL))) { |
508 | | return gFalse; |
509 | | } |
510 | | *name = new GString(s); |
511 | | fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600); |
512 | | #endif // HAVE_MKSTEMP |
513 | 0 | } |
514 | 0 | if (fd < 0 || !(*f = fdopen(fd, mode))) { |
515 | 0 | delete *name; |
516 | 0 | *name = NULL; |
517 | 0 | return gFalse; |
518 | 0 | } |
519 | 0 | return gTrue; |
520 | 0 | #endif |
521 | 0 | } |
522 | | |
523 | 0 | GBool createDir(char *path, int mode) { |
524 | | #ifdef _WIN32 |
525 | | return !mkdir(path); |
526 | | #else |
527 | 0 | return !mkdir(path, mode); |
528 | 0 | #endif |
529 | 0 | } |
530 | | |
531 | 0 | GBool executeCommand(char *cmd) { |
532 | | #ifdef VMS |
533 | | return system(cmd) ? gTrue : gFalse; |
534 | | #else |
535 | 0 | return system(cmd) ? gFalse : gTrue; |
536 | 0 | #endif |
537 | 0 | } |
538 | | |
539 | | #ifdef _WIN32 |
540 | | GString *fileNameToUTF8(char *path) { |
541 | | GString *s; |
542 | | char *p; |
543 | | |
544 | | s = new GString(); |
545 | | for (p = path; *p; ++p) { |
546 | | if (*p & 0x80) { |
547 | | s->append((char)(0xc0 | ((*p >> 6) & 0x03))); |
548 | | s->append((char)(0x80 | (*p & 0x3f))); |
549 | | } else { |
550 | | s->append(*p); |
551 | | } |
552 | | } |
553 | | return s; |
554 | | } |
555 | | |
556 | | GString *fileNameToUTF8(wchar_t *path) { |
557 | | GString *s; |
558 | | wchar_t *p; |
559 | | |
560 | | s = new GString(); |
561 | | for (p = path; *p; ++p) { |
562 | | if (*p < 0x80) { |
563 | | s->append((char)*p); |
564 | | } else if (*p < 0x800) { |
565 | | s->append((char)(0xc0 | ((*p >> 6) & 0x1f))); |
566 | | s->append((char)(0x80 | (*p & 0x3f))); |
567 | | } else { |
568 | | s->append((char)(0xe0 | ((*p >> 12) & 0x0f))); |
569 | | s->append((char)(0x80 | ((*p >> 6) & 0x3f))); |
570 | | s->append((char)(0x80 | (*p & 0x3f))); |
571 | | } |
572 | | } |
573 | | return s; |
574 | | } |
575 | | |
576 | | wchar_t *fileNameToUCS2(const char *path, wchar_t *out, size_t outSize) { |
577 | | const char *p; |
578 | | size_t i; |
579 | | |
580 | | for (p = path, i = 0; *p && i < outSize - 1; ++i) { |
581 | | if ((p[0] & 0xe0) == 0xc0 && |
582 | | p[1] && (p[1] & 0xc0) == 0x80) { |
583 | | out[i] = (wchar_t)(((p[0] & 0x1f) << 6) | |
584 | | (p[1] & 0x3f)); |
585 | | p += 2; |
586 | | } else if ((p[0] & 0xf0) == 0xe0 && |
587 | | (p[1] & 0xc0) == 0x80 && |
588 | | (p[2] & 0xc0) == 0x80) { |
589 | | out[i] = (wchar_t)(((p[0] & 0x0f) << 12) | |
590 | | ((p[1] & 0x3f) << 6) | |
591 | | (p[2] & 0x3f)); |
592 | | p += 3; |
593 | | } else { |
594 | | out[i] = (wchar_t)(p[0] & 0xff); |
595 | | p += 1; |
596 | | } |
597 | | } |
598 | | out[i] = (wchar_t)0; |
599 | | return out; |
600 | | } |
601 | | #endif |
602 | | |
603 | 0 | FILE *openFile(const char *path, const char *mode) { |
604 | | #if defined(_WIN32) |
605 | | wchar_t wPath[_MAX_PATH + 1]; |
606 | | wchar_t wMode[8]; |
607 | | int i; |
608 | | |
609 | | fileNameToUCS2(path, wPath, sizeof(wPath) / sizeof(wchar_t)); |
610 | | for (i = 0; mode[i] && i < sizeof(wMode)/sizeof(wchar_t) - 1; ++i) { |
611 | | wMode[i] = (wchar_t)(mode[i] & 0xff); |
612 | | } |
613 | | wMode[i] = (wchar_t)0; |
614 | | readWindowsShortcut(wPath, _MAX_PATH + 1); |
615 | | return _wfopen(wPath, wMode); |
616 | | #elif defined(VMS) |
617 | | return fopen(path, mode, "ctx=stm"); |
618 | | #else |
619 | 0 | return fopen(path, mode); |
620 | 0 | #endif |
621 | 0 | } |
622 | | |
623 | | #ifdef _WIN32 |
624 | | void readWindowsShortcut(wchar_t *wPath, size_t wPathSize) { |
625 | | size_t n = wcslen(wPath); |
626 | | if (n < 4 || wcscmp(wPath + n - 4, L".lnk")) { |
627 | | return; |
628 | | } |
629 | | IShellLinkW *shellLink; |
630 | | HRESULT hres; |
631 | | hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, |
632 | | IID_IShellLinkW, (LPVOID *)&shellLink); |
633 | | bool needCoUninit = false; |
634 | | if (hres == CO_E_NOTINITIALIZED) { |
635 | | CoInitialize(NULL); |
636 | | needCoUninit = true; |
637 | | hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, |
638 | | IID_IShellLinkW, (LPVOID *)&shellLink); |
639 | | } |
640 | | if (FAILED(hres)) { |
641 | | return; |
642 | | } |
643 | | IPersistFile *persistFile; |
644 | | hres = shellLink->QueryInterface(IID_IPersistFile, (LPVOID *)&persistFile); |
645 | | if (FAILED(hres)) { |
646 | | return; |
647 | | } |
648 | | hres = persistFile->Load(wPath, STGM_READ); |
649 | | if (FAILED(hres)) { |
650 | | fprintf(stderr, "IPersistFile.Load failed: 0x%08x\n", hres); |
651 | | exit(1); |
652 | | } |
653 | | wchar_t target[_MAX_PATH + 1]; |
654 | | hres = shellLink->GetPath(target, _MAX_PATH + 1, NULL, 0); |
655 | | if (FAILED(hres)) { |
656 | | return; |
657 | | } |
658 | | shellLink->Release(); |
659 | | if (needCoUninit) { |
660 | | CoUninitialize(); |
661 | | } |
662 | | if (wcslen(target) > wPathSize - 1) { |
663 | | return; |
664 | | } |
665 | | wcscpy(wPath, target); |
666 | | } |
667 | | #endif |
668 | | |
669 | 0 | int makeDir(const char *path, int mode) { |
670 | | #ifdef _WIN32 |
671 | | wchar_t wPath[_MAX_PATH + 1]; |
672 | | return _wmkdir(fileNameToUCS2(path, wPath, sizeof(wPath) / sizeof(wchar_t))); |
673 | | #else |
674 | 0 | return mkdir(path, (mode_t)mode); |
675 | 0 | #endif |
676 | 0 | } |
677 | | |
678 | 0 | char *getLine(char *buf, int size, FILE *f) { |
679 | 0 | int c, i; |
680 | |
|
681 | 0 | i = 0; |
682 | 0 | while (i < size - 1) { |
683 | 0 | if ((c = fgetc(f)) == EOF) { |
684 | 0 | break; |
685 | 0 | } |
686 | 0 | buf[i++] = (char)c; |
687 | 0 | if (c == '\x0a') { |
688 | 0 | break; |
689 | 0 | } |
690 | 0 | if (c == '\x0d') { |
691 | 0 | c = fgetc(f); |
692 | 0 | if (c == '\x0a' && i < size - 1) { |
693 | 0 | buf[i++] = (char)c; |
694 | 0 | } else if (c != EOF) { |
695 | 0 | ungetc(c, f); |
696 | 0 | } |
697 | 0 | break; |
698 | 0 | } |
699 | 0 | } |
700 | 0 | buf[i] = '\0'; |
701 | 0 | if (i == 0) { |
702 | 0 | return NULL; |
703 | 0 | } |
704 | 0 | return buf; |
705 | 0 | } |
706 | | |
707 | 0 | int gfseek(FILE *f, GFileOffset offset, int whence) { |
708 | 0 | #if HAVE_FSEEKO |
709 | 0 | return fseeko(f, offset, whence); |
710 | | #elif HAVE_FSEEK64 |
711 | | return fseek64(f, offset, whence); |
712 | | #elif HAVE_FSEEKI64 |
713 | | return _fseeki64(f, offset, whence); |
714 | | #else |
715 | | return fseek(f, offset, whence); |
716 | | #endif |
717 | 0 | } |
718 | | |
719 | 0 | GFileOffset gftell(FILE *f) { |
720 | 0 | #if HAVE_FSEEKO |
721 | 0 | return ftello(f); |
722 | | #elif HAVE_FSEEK64 |
723 | | return ftell64(f); |
724 | | #elif HAVE_FSEEKI64 |
725 | | return _ftelli64(f); |
726 | | #else |
727 | | return ftell(f); |
728 | | #endif |
729 | 0 | } |
730 | | |
731 | 0 | void fixCommandLine(int *argc, char **argv[]) { |
732 | | #ifdef _WIN32 |
733 | | int argcw; |
734 | | wchar_t **argvw; |
735 | | GString *arg; |
736 | | int i; |
737 | | |
738 | | argvw = CommandLineToArgvW(GetCommandLineW(), &argcw); |
739 | | if (!argvw || argcw < 0) { |
740 | | return; |
741 | | } |
742 | | |
743 | | *argc = argcw; |
744 | | |
745 | | *argv = (char **)gmallocn(argcw + 1, sizeof(char *)); |
746 | | for (i = 0; i < argcw; ++i) { |
747 | | arg = fileNameToUTF8(argvw[i]); |
748 | | (*argv)[i] = copyString(arg->getCString()); |
749 | | delete arg; |
750 | | } |
751 | | (*argv)[argcw] = NULL; |
752 | | |
753 | | LocalFree(argvw); |
754 | | #endif |
755 | 0 | } |