1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
16 : | Jim Winstead <jimw@php.net> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: fopen_wrappers.c 275506 2009-02-10 16:14:27Z iliaa $ */
21 :
22 : /* {{{ includes
23 : */
24 : #include "php.h"
25 : #include "php_globals.h"
26 : #include "SAPI.h"
27 :
28 : #include <stdio.h>
29 : #include <stdlib.h>
30 : #include <errno.h>
31 : #include <sys/types.h>
32 : #include <sys/stat.h>
33 : #include <fcntl.h>
34 :
35 : #ifdef PHP_WIN32
36 : #define O_RDONLY _O_RDONLY
37 : #include "win32/param.h"
38 : #else
39 : #include <sys/param.h>
40 : #endif
41 :
42 : #include "safe_mode.h"
43 : #include "ext/standard/head.h"
44 : #include "ext/standard/php_standard.h"
45 : #include "zend_compile.h"
46 : #include "php_network.h"
47 :
48 : #if HAVE_PWD_H
49 : #include <pwd.h>
50 : #endif
51 :
52 : #include <sys/types.h>
53 : #if HAVE_SYS_SOCKET_H
54 : #include <sys/socket.h>
55 : #endif
56 :
57 : #ifndef S_ISREG
58 : #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
59 : #endif
60 :
61 : #ifdef PHP_WIN32
62 : #include <winsock2.h>
63 : #elif defined(NETWARE) && defined(USE_WINSOCK)
64 : #include <novsock2.h>
65 : #else
66 : #include <netinet/in.h>
67 : #include <netdb.h>
68 : #if HAVE_ARPA_INET_H
69 : #include <arpa/inet.h>
70 : #endif
71 : #endif
72 :
73 : #if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
74 : #undef AF_UNIX
75 : #endif
76 :
77 : #if defined(AF_UNIX)
78 : #include <sys/un.h>
79 : #endif
80 : /* }}} */
81 :
82 : /* {{{ php_check_specific_open_basedir
83 : When open_basedir is not NULL, check if the given filename is located in
84 : open_basedir. Returns -1 if error or not in the open_basedir, else 0.
85 : When open_basedir is NULL, always return 0.
86 : */
87 : PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path TSRMLS_DC)
88 1135 : {
89 : char resolved_name[MAXPATHLEN];
90 : char resolved_basedir[MAXPATHLEN];
91 : char local_open_basedir[MAXPATHLEN];
92 : char path_tmp[MAXPATHLEN];
93 : char *path_file;
94 : int resolved_basedir_len;
95 : int resolved_name_len;
96 : int path_len;
97 1135 : int nesting_level = 0;
98 :
99 : /* Special case basedir==".": Use script-directory */
100 1135 : if (strcmp(basedir, ".") || !VCWD_GETCWD(local_open_basedir, MAXPATHLEN)) {
101 : /* Else use the unmodified path */
102 9 : strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir));
103 : }
104 :
105 1135 : path_len = strlen(path);
106 1135 : if (path_len > (MAXPATHLEN - 1)) {
107 : /* empty and too long paths are invalid */
108 0 : return -1;
109 : }
110 :
111 : /* normalize and expand path */
112 1135 : if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
113 1 : return -1;
114 : }
115 :
116 1134 : path_len = strlen(resolved_name);
117 1134 : memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
118 :
119 2687 : while (VCWD_REALPATH(path_tmp, resolved_name) == NULL) {
120 : #ifdef HAVE_SYMLINK
121 419 : if (nesting_level == 0) {
122 : int ret;
123 : char buf[MAXPATHLEN];
124 :
125 419 : ret = readlink(path_tmp, buf, MAXPATHLEN - 1);
126 419 : if (ret < 0) {
127 : /* not a broken symlink, move along.. */
128 : } else {
129 : /* put the real path into the path buffer */
130 0 : memcpy(path_tmp, buf, ret);
131 0 : path_tmp[ret] = '\0';
132 : }
133 : }
134 : #endif
135 :
136 : #if defined(PHP_WIN32) || defined(NETWARE)
137 : path_file = strrchr(path_tmp, DEFAULT_SLASH);
138 : if (!path_file) {
139 : path_file = strrchr(path_tmp, '/');
140 : }
141 : #else
142 419 : path_file = strrchr(path_tmp, DEFAULT_SLASH);
143 : #endif
144 419 : if (!path_file) {
145 : /* none of the path components exist. definitely not in open_basedir.. */
146 0 : return -1;
147 : } else {
148 419 : path_len = path_file - path_tmp + 1;
149 : #if defined(PHP_WIN32) || defined(NETWARE)
150 : if (path_len > 1 && path_tmp[path_len - 2] == ':') {
151 : if (path_len != 3) {
152 : return -1;
153 : }
154 : /* this is c:\ */
155 : path_tmp[path_len] = '\0';
156 : } else {
157 : path_tmp[path_len - 1] = '\0';
158 : }
159 : #else
160 419 : path_tmp[path_len - 1] = '\0';
161 : #endif
162 : }
163 419 : nesting_level++;
164 : }
165 :
166 : /* Resolve open_basedir to resolved_basedir */
167 1134 : if (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL) {
168 : /* Handler for basedirs that end with a / */
169 1134 : resolved_basedir_len = strlen(resolved_basedir);
170 1134 : if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) {
171 8 : if (resolved_basedir[resolved_basedir_len - 1] != PHP_DIR_SEPARATOR) {
172 7 : resolved_basedir[resolved_basedir_len] = PHP_DIR_SEPARATOR;
173 7 : resolved_basedir[++resolved_basedir_len] = '\0';
174 : }
175 : }
176 :
177 1134 : resolved_name_len = strlen(resolved_name);
178 1134 : if (path_tmp[path_len - 1] == PHP_DIR_SEPARATOR) {
179 32 : if (resolved_name[resolved_name_len - 1] != PHP_DIR_SEPARATOR) {
180 0 : resolved_name[resolved_name_len] = PHP_DIR_SEPARATOR;
181 0 : resolved_name[++resolved_name_len] = '\0';
182 : }
183 : }
184 :
185 : /* Check the path */
186 : #if defined(PHP_WIN32) || defined(NETWARE)
187 : if (strncasecmp(resolved_basedir, resolved_name, resolved_basedir_len) == 0) {
188 : #else
189 1134 : if (strncmp(resolved_basedir, resolved_name, resolved_basedir_len) == 0) {
190 : #endif
191 : /* File is in the right directory */
192 748 : return 0;
193 : } else {
194 : /* /openbasedir/ and /openbasedir are the same directory */
195 386 : if (resolved_basedir_len == (resolved_name_len + 1) && resolved_basedir[resolved_basedir_len - 1] == PHP_DIR_SEPARATOR) {
196 : #if defined(PHP_WIN32) || defined(NETWARE)
197 : if (strncasecmp(resolved_basedir, resolved_name, resolved_name_len) == 0) {
198 : #else
199 5 : if (strncmp(resolved_basedir, resolved_name, resolved_name_len) == 0) {
200 : #endif
201 5 : return 0;
202 : }
203 : }
204 381 : return -1;
205 : }
206 : } else {
207 : /* Unable to resolve the real path, return -1 */
208 0 : return -1;
209 : }
210 : }
211 : /* }}} */
212 :
213 : PHPAPI int php_check_open_basedir(const char *path TSRMLS_DC)
214 331149 : {
215 331149 : return php_check_open_basedir_ex(path, 1 TSRMLS_CC);
216 : }
217 :
218 : /* {{{ php_check_open_basedir
219 : */
220 : PHPAPI int php_check_open_basedir_ex(const char *path, int warn TSRMLS_DC)
221 403108 : {
222 : /* Only check when open_basedir is available */
223 403108 : if (PG(open_basedir) && *PG(open_basedir)) {
224 : char *pathbuf;
225 : char *ptr;
226 : char *end;
227 :
228 1135 : pathbuf = estrdup(PG(open_basedir));
229 :
230 1135 : ptr = pathbuf;
231 :
232 2652 : while (ptr && *ptr) {
233 1135 : end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
234 1135 : if (end != NULL) {
235 0 : *end = '\0';
236 0 : end++;
237 : }
238 :
239 1135 : if (php_check_specific_open_basedir(ptr, path TSRMLS_CC) == 0) {
240 753 : efree(pathbuf);
241 753 : return 0;
242 : }
243 :
244 382 : ptr = end;
245 : }
246 382 : if (warn) {
247 316 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s)", path, PG(open_basedir));
248 : }
249 382 : efree(pathbuf);
250 382 : errno = EPERM; /* we deny permission to open it */
251 382 : return -1;
252 : }
253 :
254 : /* Nothing to check... */
255 401973 : return 0;
256 : }
257 : /* }}} */
258 :
259 : /* {{{ php_check_safe_mode_include_dir
260 : */
261 : PHPAPI int php_check_safe_mode_include_dir(const char *path TSRMLS_DC)
262 1580 : {
263 1580 : if (PG(safe_mode)) {
264 0 : if (PG(safe_mode_include_dir) && *PG(safe_mode_include_dir)) {
265 : char *pathbuf;
266 : char *ptr;
267 : char *end;
268 : char resolved_name[MAXPATHLEN];
269 :
270 : /* Resolve the real path into resolved_name */
271 0 : if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
272 0 : return -1;
273 : }
274 0 : pathbuf = estrdup(PG(safe_mode_include_dir));
275 0 : ptr = pathbuf;
276 :
277 0 : while (ptr && *ptr) {
278 0 : end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
279 0 : if (end != NULL) {
280 0 : *end = '\0';
281 0 : end++;
282 : }
283 :
284 : /* Check the path */
285 : #ifdef PHP_WIN32
286 : if (strncasecmp(ptr, resolved_name, strlen(ptr)) == 0)
287 : #else
288 0 : if (strncmp(ptr, resolved_name, strlen(ptr)) == 0)
289 : #endif
290 : {
291 : /* File is in the right directory */
292 0 : efree(pathbuf);
293 0 : return 0;
294 : }
295 :
296 0 : ptr = end;
297 : }
298 0 : efree(pathbuf);
299 : }
300 0 : return -1;
301 : }
302 :
303 : /* Nothing to check... */
304 1580 : return 0;
305 : }
306 : /* }}} */
307 :
308 : /* {{{ php_fopen_and_set_opened_path
309 : */
310 : static FILE *php_fopen_and_set_opened_path(const char *path, const char *mode, char **opened_path TSRMLS_DC)
311 54018 : {
312 : FILE *fp;
313 :
314 54018 : if (php_check_open_basedir((char *)path TSRMLS_CC)) {
315 0 : return NULL;
316 : }
317 54018 : fp = VCWD_FOPEN(path, mode);
318 54018 : if (fp && opened_path) {
319 13467 : *opened_path = expand_filepath(path, NULL TSRMLS_CC);
320 : }
321 54018 : return fp;
322 : }
323 : /* }}} */
324 :
325 : /* {{{ php_fopen_primary_script
326 : */
327 : PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC)
328 95 : {
329 : FILE *fp;
330 : #ifndef PHP_WIN32
331 : struct stat st;
332 : #endif
333 : char *path_info, *filename;
334 : int length;
335 :
336 95 : filename = SG(request_info).path_translated;
337 95 : path_info = SG(request_info).request_uri;
338 : #if HAVE_PWD_H
339 95 : if (PG(user_dir) && *PG(user_dir) && path_info && '/' == path_info[0] && '~' == path_info[1]) {
340 0 : char *s = strchr(path_info + 2, '/');
341 :
342 0 : filename = NULL; /* discard the original filename, it must not be used */
343 0 : if (s) { /* if there is no path name after the file, do not bother */
344 : char user[32]; /* to try open the directory */
345 : struct passwd *pw;
346 : #if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
347 : struct passwd pwstruc;
348 : long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
349 : char *pwbuf;
350 :
351 : if (pwbuflen < 1) {
352 : return FAILURE;
353 : }
354 :
355 : pwbuf = emalloc(pwbuflen);
356 : #endif
357 0 : length = s - (path_info + 2);
358 0 : if (length > (int)sizeof(user) - 1) {
359 0 : length = sizeof(user) - 1;
360 : }
361 0 : memcpy(user, path_info + 2, length);
362 0 : user[length] = '\0';
363 : #if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
364 : if (getpwnam_r(user, &pwstruc, pwbuf, pwbuflen, &pw)) {
365 : efree(pwbuf);
366 : return FAILURE;
367 : }
368 : #else
369 0 : pw = getpwnam(user);
370 : #endif
371 0 : if (pw && pw->pw_dir) {
372 0 : spprintf(&filename, 0, "%s%c%s%c%s", pw->pw_dir, PHP_DIR_SEPARATOR, PG(user_dir), PHP_DIR_SEPARATOR, s + 1); /* Safe */
373 0 : STR_FREE(SG(request_info).path_translated);
374 0 : SG(request_info).path_translated = filename;
375 : }
376 : #if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
377 : efree(pwbuf);
378 : #endif
379 : }
380 : } else
381 : #endif
382 95 : if (PG(doc_root) && path_info) {
383 0 : length = strlen(PG(doc_root));
384 0 : if (IS_ABSOLUTE_PATH(PG(doc_root), length)) {
385 0 : filename = emalloc(length + strlen(path_info) + 2);
386 0 : if (filename) {
387 0 : memcpy(filename, PG(doc_root), length);
388 0 : if (!IS_SLASH(filename[length - 1])) { /* length is never 0 */
389 0 : filename[length++] = PHP_DIR_SEPARATOR;
390 : }
391 0 : if (IS_SLASH(path_info[0])) {
392 0 : length--;
393 : }
394 0 : strcpy(filename + length, path_info);
395 0 : STR_FREE(SG(request_info).path_translated);
396 0 : SG(request_info).path_translated = filename;
397 : }
398 : }
399 : } /* if doc_root && path_info */
400 :
401 95 : if (!filename) {
402 : /* we have to free SG(request_info).path_translated here because
403 : * php_destroy_request_info assumes that it will get
404 : * freed when the include_names hash is emptied, but
405 : * we're not adding it in this case */
406 0 : STR_FREE(SG(request_info).path_translated);
407 0 : SG(request_info).path_translated = NULL;
408 0 : return FAILURE;
409 : }
410 95 : fp = VCWD_FOPEN(filename, "rb");
411 :
412 : #ifndef PHP_WIN32
413 : /* refuse to open anything that is not a regular file */
414 95 : if (fp && (0 > fstat(fileno(fp), &st) || !S_ISREG(st.st_mode))) {
415 0 : fclose(fp);
416 0 : fp = NULL;
417 : }
418 : #endif
419 :
420 95 : if (!fp) {
421 7 : STR_FREE(SG(request_info).path_translated); /* for same reason as above */
422 7 : SG(request_info).path_translated = NULL;
423 7 : return FAILURE;
424 : }
425 :
426 88 : file_handle->opened_path = expand_filepath(filename, NULL TSRMLS_CC);
427 :
428 88 : if (!(SG(options) & SAPI_OPTION_NO_CHDIR)) {
429 68 : VCWD_CHDIR_FILE(filename);
430 : }
431 88 : SG(request_info).path_translated = filename;
432 :
433 88 : file_handle->filename = SG(request_info).path_translated;
434 88 : file_handle->free_filename = 0;
435 88 : file_handle->handle.fp = fp;
436 88 : file_handle->type = ZEND_HANDLE_FP;
437 :
438 88 : return SUCCESS;
439 : }
440 : /* }}} */
441 :
442 : /* {{{ php_fopen_with_path
443 : * Tries to open a file with a PATH-style list of directories.
444 : * If the filename starts with "." or "/", the path is ignored.
445 : */
446 : PHPAPI FILE *php_fopen_with_path(const char *filename, const char *mode, const char *path, char **opened_path TSRMLS_DC)
447 26934 : {
448 : char *pathbuf, *ptr, *end;
449 : char *exec_fname;
450 : char trypath[MAXPATHLEN];
451 : struct stat sb;
452 : FILE *fp;
453 : int path_length;
454 : int filename_length;
455 : int exec_fname_length;
456 :
457 26934 : if (opened_path) {
458 26934 : *opened_path = NULL;
459 : }
460 :
461 26934 : if (!filename) {
462 0 : return NULL;
463 : }
464 :
465 26934 : filename_length = strlen(filename);
466 :
467 : /* Relative path open */
468 26934 : if (*filename == '.') {
469 0 : if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
470 0 : return NULL;
471 : }
472 0 : return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC);
473 : }
474 :
475 : /*
476 : * files in safe_mode_include_dir (or subdir) are excluded from
477 : * safe mode GID/UID checks
478 : */
479 :
480 : /* Absolute path open */
481 26934 : if (IS_ABSOLUTE_PATH(filename, filename_length)) {
482 0 : if (php_check_safe_mode_include_dir(filename TSRMLS_CC) == 0) {
483 : /* filename is in safe_mode_include_dir (or subdir) */
484 0 : return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC);
485 : }
486 0 : if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
487 0 : return NULL;
488 : }
489 0 : return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC);
490 : }
491 :
492 26934 : if (!path || (path && !*path)) {
493 0 : if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
494 0 : return NULL;
495 : }
496 0 : return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC);
497 : }
498 :
499 : /* check in provided path */
500 : /* append the calling scripts' current working directory
501 : * as a fall back case
502 : */
503 26934 : if (zend_is_executing(TSRMLS_C)) {
504 0 : exec_fname = zend_get_executed_filename(TSRMLS_C);
505 0 : exec_fname_length = strlen(exec_fname);
506 0 : path_length = strlen(path);
507 :
508 0 : while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
509 0 : if ((exec_fname && exec_fname[0] == '[') || exec_fname_length <= 0) {
510 : /* [no active file] or no path */
511 0 : pathbuf = estrdup(path);
512 : } else {
513 0 : pathbuf = (char *) emalloc(exec_fname_length + path_length + 1 + 1);
514 0 : memcpy(pathbuf, path, path_length);
515 0 : pathbuf[path_length] = DEFAULT_DIR_SEPARATOR;
516 0 : memcpy(pathbuf + path_length + 1, exec_fname, exec_fname_length);
517 0 : pathbuf[path_length + exec_fname_length + 1] = '\0';
518 : }
519 : } else {
520 26934 : pathbuf = estrdup(path);
521 : }
522 :
523 26934 : ptr = pathbuf;
524 :
525 94419 : while (ptr && *ptr) {
526 54018 : end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
527 54018 : if (end != NULL) {
528 27084 : *end = '\0';
529 27084 : end++;
530 : }
531 54018 : if (snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename) >= MAXPATHLEN) {
532 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s/%s path was truncated to %d", ptr, filename, MAXPATHLEN);
533 : }
534 54018 : if (PG(safe_mode)) {
535 0 : if (VCWD_STAT(trypath, &sb) == 0) {
536 : /* file exists ... check permission */
537 0 : if (php_check_safe_mode_include_dir(trypath TSRMLS_CC) == 0 ||
538 : php_checkuid(trypath, mode, CHECKUID_CHECK_MODE_PARAM)
539 : ) {
540 : /* UID ok, or trypath is in safe_mode_include_dir */
541 0 : fp = php_fopen_and_set_opened_path(trypath, mode, opened_path TSRMLS_CC);
542 : } else {
543 0 : fp = NULL;
544 : }
545 0 : efree(pathbuf);
546 0 : return fp;
547 : }
548 : }
549 54018 : fp = php_fopen_and_set_opened_path(trypath, mode, opened_path TSRMLS_CC);
550 54018 : if (fp) {
551 13467 : efree(pathbuf);
552 13467 : return fp;
553 : }
554 40551 : ptr = end;
555 : } /* end provided path */
556 :
557 13467 : efree(pathbuf);
558 13467 : return NULL;
559 : }
560 : /* }}} */
561 :
562 : /* {{{ php_strip_url_passwd
563 : */
564 : PHPAPI char *php_strip_url_passwd(char *url)
565 391 : {
566 : register char *p, *url_start;
567 :
568 391 : if (url == NULL) {
569 0 : return "";
570 : }
571 :
572 391 : p = url;
573 :
574 13191 : while (*p) {
575 12440 : if (*p == ':' && *(p + 1) == '/' && *(p + 2) == '/') {
576 : /* found protocol */
577 31 : url_start = p = p + 3;
578 :
579 763 : while (*p) {
580 701 : if (*p == '@') {
581 : int i;
582 :
583 0 : for (i = 0; i < 3 && url_start < p; i++, url_start++) {
584 0 : *url_start = '.';
585 : }
586 0 : for (; *p; p++) {
587 0 : *url_start++ = *p;
588 : }
589 0 : *url_start=0;
590 0 : break;
591 : }
592 701 : p++;
593 : }
594 31 : return url;
595 : }
596 12409 : p++;
597 : }
598 360 : return url;
599 : }
600 : /* }}} */
601 :
602 : /* {{{ expand_filepath
603 : */
604 : PHPAPI char *expand_filepath(const char *filepath, char *real_path TSRMLS_DC)
605 76645 : {
606 76645 : return expand_filepath_ex(filepath, real_path, NULL, 0 TSRMLS_CC);
607 : }
608 : /* }}} */
609 :
610 : /* {{{ expand_filepath_ex
611 : */
612 : PHPAPI char *expand_filepath_ex(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len TSRMLS_DC)
613 76812 : {
614 : cwd_state new_state;
615 : char cwd[MAXPATHLEN];
616 : int copy_len;
617 :
618 76812 : if (!filepath[0]) {
619 14 : return NULL;
620 76798 : } else if (IS_ABSOLUTE_PATH(filepath, strlen(filepath))) {
621 73217 : cwd[0] = '\0';
622 : } else {
623 3581 : const char *iam = SG(request_info).path_translated;
624 : const char *result;
625 3581 : if (relative_to) {
626 32 : if (relative_to_len > MAXPATHLEN-1U) {
627 0 : return NULL;
628 : }
629 32 : result = relative_to;
630 32 : memcpy(cwd, relative_to, relative_to_len+1U);
631 : } else {
632 3549 : result = VCWD_GETCWD(cwd, MAXPATHLEN);
633 : }
634 :
635 3581 : if (!result && (iam != filepath)) {
636 0 : int fdtest = -1;
637 :
638 0 : fdtest = VCWD_OPEN(filepath, O_RDONLY);
639 0 : if (fdtest != -1) {
640 : /* return a relative file path if for any reason
641 : * we cannot cannot getcwd() and the requested,
642 : * relatively referenced file is accessible */
643 0 : copy_len = strlen(filepath) > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : strlen(filepath);
644 0 : real_path = estrndup(filepath, copy_len);
645 0 : close(fdtest);
646 0 : return real_path;
647 : } else {
648 0 : cwd[0] = '\0';
649 : }
650 3581 : } else if (!result) {
651 0 : cwd[0] = '\0';
652 : }
653 : }
654 :
655 76798 : new_state.cwd = strdup(cwd);
656 76798 : new_state.cwd_length = strlen(cwd);
657 :
658 76798 : if (virtual_file_ex(&new_state, filepath, NULL, CWD_FILEPATH)) {
659 2 : free(new_state.cwd);
660 2 : return NULL;
661 : }
662 :
663 76796 : if (real_path) {
664 16334 : copy_len = new_state.cwd_length > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : new_state.cwd_length;
665 16334 : memcpy(real_path, new_state.cwd, copy_len);
666 16334 : real_path[copy_len] = '\0';
667 : } else {
668 60462 : real_path = estrndup(new_state.cwd, new_state.cwd_length);
669 : }
670 76796 : free(new_state.cwd);
671 :
672 76796 : return real_path;
673 : }
674 : /* }}} */
675 :
676 : /*
677 : * Local variables:
678 : * tab-width: 4
679 : * c-basic-offset: 4
680 : * End:
681 : * vim600: sw=4 ts=4 fdm=marker
682 : * vim<600: sw=4 ts=4
683 : */
|