Annotation of embedaddon/php/ext/standard/filestat.c, revision 1.1.1.1
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 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: | Author: Jim Winstead <jimw@php.net> |
16: +----------------------------------------------------------------------+
17: */
18:
19: /* $Id: filestat.c 321634 2012-01-01 13:15:04Z felipe $ */
20:
21: #include "php.h"
22: #include "safe_mode.h"
23: #include "fopen_wrappers.h"
24: #include "php_globals.h"
25:
26: #include <stdlib.h>
27: #include <sys/stat.h>
28: #include <string.h>
29: #include <errno.h>
30: #include <ctype.h>
31: #include <time.h>
32:
33: #if HAVE_UNISTD_H
34: # include <unistd.h>
35: #endif
36:
37: #if HAVE_SYS_PARAM_H
38: # include <sys/param.h>
39: #endif
40:
41: #if HAVE_SYS_VFS_H
42: # include <sys/vfs.h>
43: #endif
44:
45: #ifdef OS2
46: # define INCL_DOS
47: # include <os2.h>
48: #endif
49:
50: #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
51: # include <sys/statvfs.h>
52: #elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_STATFS)
53: # include <sys/statfs.h>
54: #elif defined(HAVE_SYS_MOUNT_H) && defined(HAVE_STATFS)
55: # include <sys/mount.h>
56: #endif
57:
58: #if HAVE_PWD_H
59: # ifdef PHP_WIN32
60: # include "win32/pwd.h"
61: # else
62: # include <pwd.h>
63: # endif
64: #endif
65:
66: #if HAVE_GRP_H
67: # ifdef PHP_WIN32
68: # include "win32/grp.h"
69: # else
70: # include <grp.h>
71: # endif
72: #endif
73:
74: #if HAVE_UTIME
75: # ifdef PHP_WIN32
76: # include <sys/utime.h>
77: # else
78: # include <utime.h>
79: # endif
80: #endif
81:
82: #ifdef PHP_WIN32
83: #include "win32/winutil.h"
84: #endif
85:
86: #include "basic_functions.h"
87: #include "php_filestat.h"
88:
89: #ifndef S_ISDIR
90: #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
91: #endif
92: #ifndef S_ISREG
93: #define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
94: #endif
95: #ifndef S_ISLNK
96: #define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
97: #endif
98:
99: #define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
100:
101: PHP_RINIT_FUNCTION(filestat) /* {{{ */
102: {
103: BG(CurrentStatFile)=NULL;
104: BG(CurrentLStatFile)=NULL;
105: return SUCCESS;
106: }
107: /* }}} */
108:
109: PHP_RSHUTDOWN_FUNCTION(filestat) /* {{{ */
110: {
111: if (BG(CurrentStatFile)) {
112: efree (BG(CurrentStatFile));
113: BG(CurrentStatFile) = NULL;
114: }
115: if (BG(CurrentLStatFile)) {
116: efree (BG(CurrentLStatFile));
117: BG(CurrentLStatFile) = NULL;
118: }
119: return SUCCESS;
120: }
121: /* }}} */
122:
123: static int php_disk_total_space(char *path, double *space TSRMLS_DC) /* {{{ */
124: #if defined(WINDOWS) /* {{{ */
125: {
126: double bytestotal = 0;
127: HINSTANCE kernel32;
128: FARPROC gdfse;
129: typedef BOOL (WINAPI *gdfse_func)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
130: gdfse_func func;
131:
132: /* These are used by GetDiskFreeSpaceEx, if available. */
133: ULARGE_INTEGER FreeBytesAvailableToCaller;
134: ULARGE_INTEGER TotalNumberOfBytes;
135: ULARGE_INTEGER TotalNumberOfFreeBytes;
136:
137: /* These are used by GetDiskFreeSpace otherwise. */
138: DWORD SectorsPerCluster;
139: DWORD BytesPerSector;
140: DWORD NumberOfFreeClusters;
141: DWORD TotalNumberOfClusters;
142:
143: /* GetDiskFreeSpaceEx is only available in NT and Win95 post-OSR2,
144: so we have to jump through some hoops to see if the function
145: exists. */
146: kernel32 = LoadLibrary("kernel32.dll");
147: if (kernel32) {
148: gdfse = GetProcAddress(kernel32, "GetDiskFreeSpaceExA");
149: /* It's available, so we can call it. */
150: if (gdfse) {
151: func = (gdfse_func)gdfse;
152: if (func(path,
153: &FreeBytesAvailableToCaller,
154: &TotalNumberOfBytes,
155: &TotalNumberOfFreeBytes) == 0) {
156: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
157: return FAILURE;
158: }
159:
160: /* i know - this is ugly, but i works <thies@thieso.net> */
161: bytestotal = TotalNumberOfBytes.HighPart *
162: (double) (((unsigned long)1) << 31) * 2.0 +
163: TotalNumberOfBytes.LowPart;
164: } else { /* If it's not available, we just use GetDiskFreeSpace */
165: if (GetDiskFreeSpace(path,
166: &SectorsPerCluster, &BytesPerSector,
167: &NumberOfFreeClusters, &TotalNumberOfClusters) == 0) {
168: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
169: return FAILURE;
170: }
171: bytestotal = (double)TotalNumberOfClusters * (double)SectorsPerCluster * (double)BytesPerSector;
172: }
173: } else {
174: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load kernel32.dll");
175: return FAILURE;
176: }
177:
178: *space = bytestotal;
179: return SUCCESS;
180: }
181: /* }}} */
182: #elif defined(OS2) /* {{{ */
183: {
184: double bytestotal = 0;
185: FSALLOCATE fsinfo;
186: char drive = path[0] & 95;
187:
188: if (DosQueryFSInfo( drive ? drive - 64 : 0, FSIL_ALLOC, &fsinfo, sizeof( fsinfo ) ) == 0) {
189: bytestotal = (double)fsinfo.cbSector * fsinfo.cSectorUnit * fsinfo.cUnit;
190: *space = bytestotal;
191: return SUCCESS;
192: }
193: return FAILURE;
194: }
195: /* }}} */
196: #else /* {{{ if !defined(OS2) && !defined(WINDOWS) */
197: {
198: double bytestotal = 0;
199: #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
200: struct statvfs buf;
201: #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
202: struct statfs buf;
203: #endif
204:
205: #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
206: if (statvfs(path, &buf)) {
207: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
208: return FAILURE;
209: }
210: if (buf.f_frsize) {
211: bytestotal = (((double)buf.f_blocks) * ((double)buf.f_frsize));
212: } else {
213: bytestotal = (((double)buf.f_blocks) * ((double)buf.f_bsize));
214: }
215:
216: #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
217: if (statfs(path, &buf)) {
218: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
219: return FAILURE;
220: }
221: bytestotal = (((double)buf.f_bsize) * ((double)buf.f_blocks));
222: #endif
223:
224: *space = bytestotal;
225: return SUCCESS;
226: }
227: #endif
228: /* }}} */
229: /* }}} */
230:
231: /* {{{ proto float disk_total_space(string path)
232: Get total disk space for filesystem that path is on */
233: PHP_FUNCTION(disk_total_space)
234: {
235: double bytestotal;
236: char *path;
237: int path_len;
238:
239: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &path_len) == FAILURE) {
240: return;
241: }
242:
243: if (php_check_open_basedir(path TSRMLS_CC)) {
244: RETURN_FALSE;
245: }
246:
247: if (php_disk_total_space(path, &bytestotal TSRMLS_CC) == SUCCESS) {
248: RETURN_DOUBLE(bytestotal);
249: }
250: RETURN_FALSE;
251: }
252: /* }}} */
253:
254: static int php_disk_free_space(char *path, double *space TSRMLS_DC) /* {{{ */
255: #if defined(WINDOWS) /* {{{ */
256: {
257: double bytesfree = 0;
258:
259: HINSTANCE kernel32;
260: FARPROC gdfse;
261: typedef BOOL (WINAPI *gdfse_func)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
262: gdfse_func func;
263:
264: /* These are used by GetDiskFreeSpaceEx, if available. */
265: ULARGE_INTEGER FreeBytesAvailableToCaller;
266: ULARGE_INTEGER TotalNumberOfBytes;
267: ULARGE_INTEGER TotalNumberOfFreeBytes;
268:
269: /* These are used by GetDiskFreeSpace otherwise. */
270: DWORD SectorsPerCluster;
271: DWORD BytesPerSector;
272: DWORD NumberOfFreeClusters;
273: DWORD TotalNumberOfClusters;
274:
275: /* GetDiskFreeSpaceEx is only available in NT and Win95 post-OSR2,
276: so we have to jump through some hoops to see if the function
277: exists. */
278: kernel32 = LoadLibrary("kernel32.dll");
279: if (kernel32) {
280: gdfse = GetProcAddress(kernel32, "GetDiskFreeSpaceExA");
281: /* It's available, so we can call it. */
282: if (gdfse) {
283: func = (gdfse_func)gdfse;
284: if (func(path,
285: &FreeBytesAvailableToCaller,
286: &TotalNumberOfBytes,
287: &TotalNumberOfFreeBytes) == 0) {
288: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
289: return FAILURE;
290: }
291:
292: /* i know - this is ugly, but i works <thies@thieso.net> */
293: bytesfree = FreeBytesAvailableToCaller.HighPart *
294: (double) (((unsigned long)1) << 31) * 2.0 +
295: FreeBytesAvailableToCaller.LowPart;
296: } else { /* If it's not available, we just use GetDiskFreeSpace */
297: if (GetDiskFreeSpace(path,
298: &SectorsPerCluster, &BytesPerSector,
299: &NumberOfFreeClusters, &TotalNumberOfClusters) == 0) {
300: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
301: return FAILURE;
302: }
303: bytesfree = (double)NumberOfFreeClusters * (double)SectorsPerCluster * (double)BytesPerSector;
304: }
305: } else {
306: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load kernel32.dll");
307: return FAILURE;
308: }
309:
310: *space = bytesfree;
311: return SUCCESS;
312: }
313: /* }}} */
314: #elif defined(OS2) /* {{{ */
315: {
316: double bytesfree = 0;
317: FSALLOCATE fsinfo;
318: char drive = path[0] & 95;
319:
320: if (DosQueryFSInfo( drive ? drive - 64 : 0, FSIL_ALLOC, &fsinfo, sizeof( fsinfo ) ) == 0) {
321: bytesfree = (double)fsinfo.cbSector * fsinfo.cSectorUnit * fsinfo.cUnitAvail;
322: *space = bytesfree;
323: return SUCCESS;
324: }
325: return FAILURE;
326: }
327: /* }}} */
328: #else /* {{{ if !defined(OS2) && !defined(WINDOWS) */
329: {
330: double bytesfree = 0;
331: #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
332: struct statvfs buf;
333: #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
334: struct statfs buf;
335: #endif
336:
337: #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
338: if (statvfs(path, &buf)) {
339: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
340: return FAILURE;
341: }
342: if (buf.f_frsize) {
343: bytesfree = (((double)buf.f_bavail) * ((double)buf.f_frsize));
344: } else {
345: bytesfree = (((double)buf.f_bavail) * ((double)buf.f_bsize));
346: }
347: #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
348: if (statfs(path, &buf)) {
349: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
350: return FAILURE;
351: }
352: #ifdef NETWARE
353: bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bfree));
354: #else
355: bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bavail));
356: #endif
357: #endif
358:
359: *space = bytesfree;
360: return SUCCESS;
361: }
362: #endif
363: /* }}} */
364: /* }}} */
365:
366: /* {{{ proto float disk_free_space(string path)
367: Get free disk space for filesystem that path is on */
368: PHP_FUNCTION(disk_free_space)
369: {
370: double bytesfree;
371: char *path;
372: int path_len;
373:
374: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &path_len) == FAILURE) {
375: return;
376: }
377:
378: if (php_check_open_basedir(path TSRMLS_CC)) {
379: RETURN_FALSE;
380: }
381:
382: if (strlen(path) != path_len) {
383: RETURN_FALSE;
384: }
385:
386: if (php_disk_free_space(path, &bytesfree TSRMLS_CC) == SUCCESS) {
387: RETURN_DOUBLE(bytesfree);
388: }
389: RETURN_FALSE;
390: }
391: /* }}} */
392:
393: #if !defined(WINDOWS) && !defined(NETWARE)
394: static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp) /* {{{ */
395: {
396: char *filename;
397: int filename_len;
398: zval *group;
399: gid_t gid;
400: int ret;
401:
402: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/", &filename, &filename_len, &group) == FAILURE) {
403: RETURN_FALSE;
404: }
405:
406: if (strlen(filename) != filename_len) {
407: RETURN_FALSE;
408: }
409:
410: if (Z_TYPE_P(group) == IS_LONG) {
411: gid = (gid_t)Z_LVAL_P(group);
412: } else if (Z_TYPE_P(group) == IS_STRING) {
413: #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
414: struct group gr;
415: struct group *retgrptr;
416: long grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
417: char *grbuf;
418:
419: if (grbuflen < 1) {
420: RETURN_FALSE;
421: }
422:
423: grbuf = emalloc(grbuflen);
424: if (getgrnam_r(Z_STRVAL_P(group), &gr, grbuf, grbuflen, &retgrptr) != 0 || retgrptr == NULL) {
425: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_P(group));
426: efree(grbuf);
427: RETURN_FALSE;
428: }
429: efree(grbuf);
430: gid = gr.gr_gid;
431: #else
432: struct group *gr = getgrnam(Z_STRVAL_P(group));
433:
434: if (!gr) {
435: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_P(group));
436: RETURN_FALSE;
437: }
438: gid = gr->gr_gid;
439: #endif
440: } else {
441: php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(group));
442: RETURN_FALSE;
443: }
444:
445: if (PG(safe_mode) &&(!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
446: RETURN_FALSE;
447: }
448:
449: /* Check the basedir */
450: if (php_check_open_basedir(filename TSRMLS_CC)) {
451: RETURN_FALSE;
452: }
453:
454: if (do_lchgrp) {
455: #if HAVE_LCHOWN
456: ret = VCWD_LCHOWN(filename, -1, gid);
457: #endif
458: } else {
459: ret = VCWD_CHOWN(filename, -1, gid);
460: }
461: if (ret == -1) {
462: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
463: RETURN_FALSE;
464: }
465: RETURN_TRUE;
466: }
467: /* }}} */
468: #endif
469:
470: #ifndef NETWARE
471: /* {{{ proto bool chgrp(string filename, mixed group)
472: Change file group */
473: PHP_FUNCTION(chgrp)
474: {
475: #if !defined(WINDOWS)
476: php_do_chgrp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
477: #else
478: RETURN_FALSE;
479: #endif
480: }
481: /* }}} */
482:
483: /* {{{ proto bool lchgrp(string filename, mixed group)
484: Change symlink group */
485: #if HAVE_LCHOWN
486: PHP_FUNCTION(lchgrp)
487: {
488: # if !defined(WINDOWS)
489: php_do_chgrp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
490: # else
491: RETURN_FALSE;
492: # endif
493: }
494: #endif
495: /* }}} */
496: #endif /* !NETWARE */
497:
498: #if !defined(WINDOWS) && !defined(NETWARE)
499: static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown) /* {{{ */
500: {
501: char *filename;
502: int filename_len;
503: zval *user;
504: uid_t uid;
505: int ret;
506:
507: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/", &filename, &filename_len, &user) == FAILURE) {
508: return;
509: }
510:
511: if (strlen(filename) != filename_len) {
512: RETURN_FALSE;
513: }
514:
515: if (Z_TYPE_P(user) == IS_LONG) {
516: uid = (uid_t)Z_LVAL_P(user);
517: } else if (Z_TYPE_P(user) == IS_STRING) {
518: #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
519: struct passwd pw;
520: struct passwd *retpwptr = NULL;
521: long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
522: char *pwbuf;
523:
524: if (pwbuflen < 1) {
525: RETURN_FALSE;
526: }
527:
528: pwbuf = emalloc(pwbuflen);
529: if (getpwnam_r(Z_STRVAL_P(user), &pw, pwbuf, pwbuflen, &retpwptr) != 0 || retpwptr == NULL) {
530: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_P(user));
531: efree(pwbuf);
532: RETURN_FALSE;
533: }
534: efree(pwbuf);
535: uid = pw.pw_uid;
536: #else
537: struct passwd *pw = getpwnam(Z_STRVAL_P(user));
538:
539: if (!pw) {
540: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_P(user));
541: RETURN_FALSE;
542: }
543: uid = pw->pw_uid;
544: #endif
545: } else {
546: php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(user));
547: RETURN_FALSE;
548: }
549:
550: if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
551: RETURN_FALSE;
552: }
553:
554: /* Check the basedir */
555: if (php_check_open_basedir(filename TSRMLS_CC)) {
556: RETURN_FALSE;
557: }
558:
559: if (do_lchown) {
560: #if HAVE_LCHOWN
561: ret = VCWD_LCHOWN(filename, uid, -1);
562: #endif
563: } else {
564: ret = VCWD_CHOWN(filename, uid, -1);
565: }
566: if (ret == -1) {
567: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
568: RETURN_FALSE;
569: }
570: }
571: /* }}} */
572: #endif
573:
574: #ifndef NETWARE
575: /* {{{ proto bool chown (string filename, mixed user)
576: Change file owner */
577: PHP_FUNCTION(chown)
578: {
579: #if !defined(WINDOWS)
580: RETVAL_TRUE;
581: php_do_chown(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
582: #else
583: RETURN_FALSE;
584: #endif
585: }
586: /* }}} */
587:
588: /* {{{ proto bool chown (string filename, mixed user)
589: Change file owner */
590: #if HAVE_LCHOWN
591: PHP_FUNCTION(lchown)
592: {
593: # if !defined(WINDOWS)
594: RETVAL_TRUE;
595: php_do_chown(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
596: # else
597: RETURN_FALSE;
598: # endif
599: }
600: #endif
601: /* }}} */
602: #endif /* !NETWARE */
603:
604: /* {{{ proto bool chmod(string filename, int mode)
605: Change file mode */
606: PHP_FUNCTION(chmod)
607: {
608: char *filename;
609: int filename_len;
610: long mode;
611: int ret;
612: mode_t imode;
613:
614: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &filename, &filename_len, &mode) == FAILURE) {
615: return;
616: }
617:
618: if (PG(safe_mode) &&(!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
619: RETURN_FALSE;
620: }
621:
622: if (strlen(filename) != filename_len) {
623: RETURN_FALSE;
624: }
625:
626: /* Check the basedir */
627: if (php_check_open_basedir(filename TSRMLS_CC)) {
628: RETURN_FALSE;
629: }
630:
631: imode = (mode_t) mode;
632: /* In safe mode, do not allow to setuid files.
633: * Setuiding files could allow users to gain privileges
634: * that safe mode doesn't give them. */
635:
636: if (PG(safe_mode)) {
637: php_stream_statbuf ssb;
638: if (php_stream_stat_path_ex(filename, 0, &ssb, NULL)) {
639: php_error_docref(NULL TSRMLS_CC, E_WARNING, "stat failed for %s", filename);
640: RETURN_FALSE;
641: }
642: if ((imode & 04000) != 0 && (ssb.sb.st_mode & 04000) == 0) {
643: imode ^= 04000;
644: }
645: if ((imode & 02000) != 0 && (ssb.sb.st_mode & 02000) == 0) {
646: imode ^= 02000;
647: }
648: if ((imode & 01000) != 0 && (ssb.sb.st_mode & 01000) == 0) {
649: imode ^= 01000;
650: }
651: }
652:
653: ret = VCWD_CHMOD(filename, imode);
654: if (ret == -1) {
655: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
656: RETURN_FALSE;
657: }
658: RETURN_TRUE;
659: }
660: /* }}} */
661:
662: #if HAVE_UTIME
663: /* {{{ proto bool touch(string filename [, int time [, int atime]])
664: Set modification time of file */
665: PHP_FUNCTION(touch)
666: {
667: char *filename;
668: int filename_len;
669: long filetime = 0, fileatime = 0;
670: int ret, argc = ZEND_NUM_ARGS();
671: FILE *file;
672: struct utimbuf newtimebuf;
673: struct utimbuf *newtime = &newtimebuf;
674:
675: if (zend_parse_parameters(argc TSRMLS_CC, "s|ll", &filename, &filename_len, &filetime, &fileatime) == FAILURE) {
676: return;
677: }
678:
679: if (strlen(filename) != filename_len) {
680: RETURN_FALSE;
681: }
682:
683: switch (argc) {
684: case 1:
685: #ifdef HAVE_UTIME_NULL
686: newtime = NULL;
687: #else
688: newtime->modtime = newtime->actime = time(NULL);
689: #endif
690: break;
691: case 2:
692: newtime->modtime = newtime->actime = filetime;
693: break;
694: case 3:
695: newtime->modtime = filetime;
696: newtime->actime = fileatime;
697: break;
698: default:
699: /* Never reached */
700: WRONG_PARAM_COUNT;
701: }
702:
703: /* Safe-mode */
704: if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
705: RETURN_FALSE;
706: }
707:
708: /* Check the basedir */
709: if (php_check_open_basedir(filename TSRMLS_CC)) {
710: RETURN_FALSE;
711: }
712:
713: /* create the file if it doesn't exist already */
714: if (VCWD_ACCESS(filename, F_OK) != 0) {
715: file = VCWD_FOPEN(filename, "w");
716: if (file == NULL) {
717: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create file %s because %s", filename, strerror(errno));
718: RETURN_FALSE;
719: }
720: fclose(file);
721: }
722:
723: ret = VCWD_UTIME(filename, newtime);
724: if (ret == -1) {
725: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Utime failed: %s", strerror(errno));
726: RETURN_FALSE;
727: }
728: RETURN_TRUE;
729: }
730: /* }}} */
731: #endif
732:
733: /* {{{ php_clear_stat_cache()
734: */
735: PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len TSRMLS_DC)
736: {
737: /* always clear CurrentStatFile and CurrentLStatFile even if filename is not NULL
738: * as it may contain outdated data (e.g. "nlink" for a directory when deleting a file
739: * in this directory, as shown by lstat_stat_variation9.phpt) */
740:
741: if (BG(CurrentStatFile)) {
742: efree(BG(CurrentStatFile));
743: BG(CurrentStatFile) = NULL;
744: }
745: if (BG(CurrentLStatFile)) {
746: efree(BG(CurrentLStatFile));
747: BG(CurrentLStatFile) = NULL;
748: }
749: if (clear_realpath_cache) {
750: if (filename != NULL) {
751: realpath_cache_del(filename, filename_len TSRMLS_CC);
752: } else {
753: realpath_cache_clean(TSRMLS_C);
754: }
755: }
756: }
757: /* }}} */
758:
759: /* {{{ proto void clearstatcache([bool clear_realpath_cache[, string filename]])
760: Clear file stat cache */
761: PHP_FUNCTION(clearstatcache)
762: {
763: zend_bool clear_realpath_cache = 0;
764: char *filename = NULL;
765: int filename_len = 0;
766:
767: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bs", &clear_realpath_cache, &filename, &filename_len) == FAILURE) {
768: return;
769: }
770:
771: php_clear_stat_cache(clear_realpath_cache, filename, filename_len TSRMLS_CC);
772: }
773: /* }}} */
774:
775: #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
776: #define IS_EXISTS_CHECK(__t) ((__t) == FS_EXISTS || (__t) == FS_IS_W || (__t) == FS_IS_R || (__t) == FS_IS_X || (__t) == FS_IS_FILE || (__t) == FS_IS_DIR || (__t) == FS_IS_LINK)
777: #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
778: #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
779:
780: /* {{{ php_stat
781: */
782: PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int type, zval *return_value TSRMLS_DC)
783: {
784: zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
785: *stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
786: struct stat *stat_sb;
787: php_stream_statbuf ssb;
788: int flags = 0, rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
789: char *stat_sb_names[13] = {
790: "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
791: "size", "atime", "mtime", "ctime", "blksize", "blocks"
792: };
793: char *local;
794: php_stream_wrapper *wrapper;
795: char safe_mode_buf[MAXPATHLEN];
796:
797: if (!filename_length) {
798: RETURN_FALSE;
799: }
800:
801: if (strlen(filename) != filename_length) {
802: RETURN_FALSE;
803: }
804:
805: if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0 TSRMLS_CC)) == &php_plain_files_wrapper) {
806: if (php_check_open_basedir(local TSRMLS_CC)) {
807: RETURN_FALSE;
808: } else if (PG(safe_mode)) {
809: if (type == FS_IS_X) {
810: if (strstr(local, "..")) {
811: RETURN_FALSE;
812: } else {
813: char *b = strrchr(local, PHP_DIR_SEPARATOR);
814: snprintf(safe_mode_buf, MAXPATHLEN, "%s%s%s", PG(safe_mode_exec_dir), (b ? "" : "/"), (b ? b : local));
815: local = (char *)&safe_mode_buf;
816: }
817: } else if (!php_checkuid_ex(local, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS, CHECKUID_NO_ERRORS)) {
818: RETURN_FALSE;
819: }
820: }
821: }
822:
823: if (IS_ACCESS_CHECK(type)) {
824: if (wrapper == &php_plain_files_wrapper) {
825:
826: switch (type) {
827: #ifdef F_OK
828: case FS_EXISTS:
829: RETURN_BOOL(VCWD_ACCESS(local, F_OK) == 0);
830: break;
831: #endif
832: #ifdef W_OK
833: case FS_IS_W:
834: RETURN_BOOL(VCWD_ACCESS(local, W_OK) == 0);
835: break;
836: #endif
837: #ifdef R_OK
838: case FS_IS_R:
839: RETURN_BOOL(VCWD_ACCESS(local, R_OK) == 0);
840: break;
841: #endif
842: #ifdef X_OK
843: case FS_IS_X:
844: RETURN_BOOL(VCWD_ACCESS(local, X_OK) == 0);
845: break;
846: #endif
847: }
848: }
849: }
850:
851: if (IS_LINK_OPERATION(type)) {
852: flags |= PHP_STREAM_URL_STAT_LINK;
853: }
854: if (IS_EXISTS_CHECK(type)) {
855: flags |= PHP_STREAM_URL_STAT_QUIET;
856: }
857:
858: if (php_stream_stat_path_ex((char *)filename, flags, &ssb, NULL)) {
859: /* Error Occured */
860: if (!IS_EXISTS_CHECK(type)) {
861: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
862: }
863: RETURN_FALSE;
864: }
865:
866: stat_sb = &ssb.sb;
867:
868:
869: #ifndef NETWARE
870: if (type >= FS_IS_W && type <= FS_IS_X) {
871: if(ssb.sb.st_uid==getuid()) {
872: rmask=S_IRUSR;
873: wmask=S_IWUSR;
874: xmask=S_IXUSR;
875: } else if(ssb.sb.st_gid==getgid()) {
876: rmask=S_IRGRP;
877: wmask=S_IWGRP;
878: xmask=S_IXGRP;
879: } else {
880: int groups, n, i;
881: gid_t *gids;
882:
883: groups = getgroups(0, NULL);
884: if(groups > 0) {
885: gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
886: n=getgroups(groups, gids);
887: for(i=0;i<n;i++){
888: if(ssb.sb.st_gid==gids[i]) {
889: rmask=S_IRGRP;
890: wmask=S_IWGRP;
891: xmask=S_IXGRP;
892: break;
893: }
894: }
895: efree(gids);
896: }
897: }
898: }
899: #endif
900:
901: #ifndef NETWARE
902: if (IS_ABLE_CHECK(type) && getuid() == 0) {
903: /* root has special perms on plain_wrapper
904: But we don't know about root under Netware */
905: if (wrapper == &php_plain_files_wrapper) {
906: if (type == FS_IS_X) {
907: xmask = S_IXROOT;
908: } else {
909: RETURN_TRUE;
910: }
911: }
912: }
913: #endif
914:
915: switch (type) {
916: case FS_PERMS:
917: RETURN_LONG((long)ssb.sb.st_mode);
918: case FS_INODE:
919: RETURN_LONG((long)ssb.sb.st_ino);
920: case FS_SIZE:
921: RETURN_LONG((long)ssb.sb.st_size);
922: case FS_OWNER:
923: RETURN_LONG((long)ssb.sb.st_uid);
924: case FS_GROUP:
925: RETURN_LONG((long)ssb.sb.st_gid);
926: case FS_ATIME:
927: RETURN_LONG((long)ssb.sb.st_atime);
928: case FS_MTIME:
929: RETURN_LONG((long)ssb.sb.st_mtime);
930: case FS_CTIME:
931: RETURN_LONG((long)ssb.sb.st_ctime);
932: case FS_TYPE:
933: if (S_ISLNK(ssb.sb.st_mode)) {
934: RETURN_STRING("link", 1);
935: }
936: switch(ssb.sb.st_mode & S_IFMT) {
937: case S_IFIFO: RETURN_STRING("fifo", 1);
938: case S_IFCHR: RETURN_STRING("char", 1);
939: case S_IFDIR: RETURN_STRING("dir", 1);
940: case S_IFBLK: RETURN_STRING("block", 1);
941: case S_IFREG: RETURN_STRING("file", 1);
942: #if defined(S_IFSOCK) && !defined(ZEND_WIN32)&&!defined(__BEOS__)
943: case S_IFSOCK: RETURN_STRING("socket", 1);
944: #endif
945: }
946: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown file type (%d)", ssb.sb.st_mode&S_IFMT);
947: RETURN_STRING("unknown", 1);
948: case FS_IS_W:
949: RETURN_BOOL((ssb.sb.st_mode & wmask) != 0);
950: case FS_IS_R:
951: RETURN_BOOL((ssb.sb.st_mode&rmask)!=0);
952: case FS_IS_X:
953: RETURN_BOOL((ssb.sb.st_mode&xmask)!=0 && !S_ISDIR(ssb.sb.st_mode));
954: case FS_IS_FILE:
955: RETURN_BOOL(S_ISREG(ssb.sb.st_mode));
956: case FS_IS_DIR:
957: RETURN_BOOL(S_ISDIR(ssb.sb.st_mode));
958: case FS_IS_LINK:
959: RETURN_BOOL(S_ISLNK(ssb.sb.st_mode));
960: case FS_EXISTS:
961: RETURN_TRUE; /* the false case was done earlier */
962: case FS_LSTAT:
963: /* FALLTHROUGH */
964: case FS_STAT:
965: array_init(return_value);
966:
967: MAKE_LONG_ZVAL_INCREF(stat_dev, stat_sb->st_dev);
968: MAKE_LONG_ZVAL_INCREF(stat_ino, stat_sb->st_ino);
969: MAKE_LONG_ZVAL_INCREF(stat_mode, stat_sb->st_mode);
970: MAKE_LONG_ZVAL_INCREF(stat_nlink, stat_sb->st_nlink);
971: MAKE_LONG_ZVAL_INCREF(stat_uid, stat_sb->st_uid);
972: MAKE_LONG_ZVAL_INCREF(stat_gid, stat_sb->st_gid);
973: #ifdef HAVE_ST_RDEV
974: MAKE_LONG_ZVAL_INCREF(stat_rdev, stat_sb->st_rdev);
975: #else
976: MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
977: #endif
978: MAKE_LONG_ZVAL_INCREF(stat_size, stat_sb->st_size);
979: MAKE_LONG_ZVAL_INCREF(stat_atime, stat_sb->st_atime);
980: MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_sb->st_mtime);
981: MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_sb->st_ctime);
982: #ifdef HAVE_ST_BLKSIZE
983: MAKE_LONG_ZVAL_INCREF(stat_blksize, stat_sb->st_blksize);
984: #else
985: MAKE_LONG_ZVAL_INCREF(stat_blksize,-1);
986: #endif
987: #ifdef HAVE_ST_BLOCKS
988: MAKE_LONG_ZVAL_INCREF(stat_blocks, stat_sb->st_blocks);
989: #else
990: MAKE_LONG_ZVAL_INCREF(stat_blocks,-1);
991: #endif
992: /* Store numeric indexes in propper order */
993: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_dev, sizeof(zval *), NULL);
994: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ino, sizeof(zval *), NULL);
995: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mode, sizeof(zval *), NULL);
996: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_nlink, sizeof(zval *), NULL);
997: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_uid, sizeof(zval *), NULL);
998: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_gid, sizeof(zval *), NULL);
999:
1000: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_rdev, sizeof(zval *), NULL);
1001: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_size, sizeof(zval *), NULL);
1002: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_atime, sizeof(zval *), NULL);
1003: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mtime, sizeof(zval *), NULL);
1004: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ctime, sizeof(zval *), NULL);
1005: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blksize, sizeof(zval *), NULL);
1006: zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blocks, sizeof(zval *), NULL);
1007:
1008: /* Store string indexes referencing the same zval*/
1009: zend_hash_update(HASH_OF(return_value), stat_sb_names[0], strlen(stat_sb_names[0])+1, (void *) &stat_dev, sizeof(zval *), NULL);
1010: zend_hash_update(HASH_OF(return_value), stat_sb_names[1], strlen(stat_sb_names[1])+1, (void *) &stat_ino, sizeof(zval *), NULL);
1011: zend_hash_update(HASH_OF(return_value), stat_sb_names[2], strlen(stat_sb_names[2])+1, (void *) &stat_mode, sizeof(zval *), NULL);
1012: zend_hash_update(HASH_OF(return_value), stat_sb_names[3], strlen(stat_sb_names[3])+1, (void *) &stat_nlink, sizeof(zval *), NULL);
1013: zend_hash_update(HASH_OF(return_value), stat_sb_names[4], strlen(stat_sb_names[4])+1, (void *) &stat_uid, sizeof(zval *), NULL);
1014: zend_hash_update(HASH_OF(return_value), stat_sb_names[5], strlen(stat_sb_names[5])+1, (void *) &stat_gid, sizeof(zval *), NULL);
1015: zend_hash_update(HASH_OF(return_value), stat_sb_names[6], strlen(stat_sb_names[6])+1, (void *) &stat_rdev, sizeof(zval *), NULL);
1016: zend_hash_update(HASH_OF(return_value), stat_sb_names[7], strlen(stat_sb_names[7])+1, (void *) &stat_size, sizeof(zval *), NULL);
1017: zend_hash_update(HASH_OF(return_value), stat_sb_names[8], strlen(stat_sb_names[8])+1, (void *) &stat_atime, sizeof(zval *), NULL);
1018: zend_hash_update(HASH_OF(return_value), stat_sb_names[9], strlen(stat_sb_names[9])+1, (void *) &stat_mtime, sizeof(zval *), NULL);
1019: zend_hash_update(HASH_OF(return_value), stat_sb_names[10], strlen(stat_sb_names[10])+1, (void *) &stat_ctime, sizeof(zval *), NULL);
1020: zend_hash_update(HASH_OF(return_value), stat_sb_names[11], strlen(stat_sb_names[11])+1, (void *) &stat_blksize, sizeof(zval *), NULL);
1021: zend_hash_update(HASH_OF(return_value), stat_sb_names[12], strlen(stat_sb_names[12])+1, (void *) &stat_blocks, sizeof(zval *), NULL);
1022:
1023: return;
1024: }
1025: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Didn't understand stat call");
1026: RETURN_FALSE;
1027: }
1028: /* }}} */
1029:
1030: /* another quickie macro to make defining similar functions easier */
1031: /* {{{ FileFunction(name, funcnum) */
1032: #define FileFunction(name, funcnum) \
1033: void name(INTERNAL_FUNCTION_PARAMETERS) { \
1034: char *filename; \
1035: int filename_len; \
1036: \
1037: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \
1038: return; \
1039: } \
1040: \
1041: php_stat(filename, (php_stat_len) filename_len, funcnum, return_value TSRMLS_CC); \
1042: }
1043: /* }}} */
1044:
1045: /* {{{ proto int fileperms(string filename)
1046: Get file permissions */
1047: FileFunction(PHP_FN(fileperms), FS_PERMS)
1048: /* }}} */
1049:
1050: /* {{{ proto int fileinode(string filename)
1051: Get file inode */
1052: FileFunction(PHP_FN(fileinode), FS_INODE)
1053: /* }}} */
1054:
1055: /* {{{ proto int filesize(string filename)
1056: Get file size */
1057: FileFunction(PHP_FN(filesize), FS_SIZE)
1058: /* }}} */
1059:
1060: /* {{{ proto int fileowner(string filename)
1061: Get file owner */
1062: FileFunction(PHP_FN(fileowner), FS_OWNER)
1063: /* }}} */
1064:
1065: /* {{{ proto int filegroup(string filename)
1066: Get file group */
1067: FileFunction(PHP_FN(filegroup), FS_GROUP)
1068: /* }}} */
1069:
1070: /* {{{ proto int fileatime(string filename)
1071: Get last access time of file */
1072: FileFunction(PHP_FN(fileatime), FS_ATIME)
1073: /* }}} */
1074:
1075: /* {{{ proto int filemtime(string filename)
1076: Get last modification time of file */
1077: FileFunction(PHP_FN(filemtime), FS_MTIME)
1078: /* }}} */
1079:
1080: /* {{{ proto int filectime(string filename)
1081: Get inode modification time of file */
1082: FileFunction(PHP_FN(filectime), FS_CTIME)
1083: /* }}} */
1084:
1085: /* {{{ proto string filetype(string filename)
1086: Get file type */
1087: FileFunction(PHP_FN(filetype), FS_TYPE)
1088: /* }}} */
1089:
1090: /* {{{ proto bool is_writable(string filename)
1091: Returns true if file can be written */
1092: FileFunction(PHP_FN(is_writable), FS_IS_W)
1093: /* }}} */
1094:
1095: /* {{{ proto bool is_readable(string filename)
1096: Returns true if file can be read */
1097: FileFunction(PHP_FN(is_readable), FS_IS_R)
1098: /* }}} */
1099:
1100: /* {{{ proto bool is_executable(string filename)
1101: Returns true if file is executable */
1102: FileFunction(PHP_FN(is_executable), FS_IS_X)
1103: /* }}} */
1104:
1105: /* {{{ proto bool is_file(string filename)
1106: Returns true if file is a regular file */
1107: FileFunction(PHP_FN(is_file), FS_IS_FILE)
1108: /* }}} */
1109:
1110: /* {{{ proto bool is_dir(string filename)
1111: Returns true if file is directory */
1112: FileFunction(PHP_FN(is_dir), FS_IS_DIR)
1113: /* }}} */
1114:
1115: /* {{{ proto bool is_link(string filename)
1116: Returns true if file is symbolic link */
1117: FileFunction(PHP_FN(is_link), FS_IS_LINK)
1118: /* }}} */
1119:
1120: /* {{{ proto bool file_exists(string filename)
1121: Returns true if filename exists */
1122: FileFunction(PHP_FN(file_exists), FS_EXISTS)
1123: /* }}} */
1124:
1125: /* {{{ proto array lstat(string filename)
1126: Give information about a file or symbolic link */
1127: FileFunction(php_if_lstat, FS_LSTAT)
1128: /* }}} */
1129:
1130: /* {{{ proto array stat(string filename)
1131: Give information about a file */
1132: FileFunction(php_if_stat, FS_STAT)
1133: /* }}} */
1134:
1135: /* {{{ proto bool realpath_cache_size()
1136: Get current size of realpath cache */
1137: PHP_FUNCTION(realpath_cache_size)
1138: {
1139: if (zend_parse_parameters_none() == FAILURE) {
1140: return;
1141: }
1142: RETURN_LONG(realpath_cache_size(TSRMLS_C));
1143: }
1144:
1145: /* {{{ proto bool realpath_cache_get()
1146: Get current size of realpath cache */
1147: PHP_FUNCTION(realpath_cache_get)
1148: {
1149: realpath_cache_bucket **buckets = realpath_cache_get_buckets(TSRMLS_C), **end = buckets + realpath_cache_max_buckets(TSRMLS_C);
1150:
1151: if (zend_parse_parameters_none() == FAILURE) {
1152: return;
1153: }
1154:
1155: array_init(return_value);
1156: while(buckets < end) {
1157: realpath_cache_bucket *bucket = *buckets;
1158: while(bucket) {
1159: zval *entry;
1160: MAKE_STD_ZVAL(entry);
1161: array_init(entry);
1162:
1163: add_assoc_long(entry, "key", bucket->key);
1164: add_assoc_bool(entry, "is_dir", bucket->is_dir);
1165: add_assoc_stringl(entry, "realpath", bucket->realpath, bucket->realpath_len, 1);
1166: add_assoc_long(entry, "expires", bucket->expires);
1167: #ifdef PHP_WIN32
1168: add_assoc_bool(entry, "is_rvalid", bucket->is_rvalid);
1169: add_assoc_bool(entry, "is_wvalid", bucket->is_wvalid);
1170: add_assoc_bool(entry, "is_readable", bucket->is_readable);
1171: add_assoc_bool(entry, "is_writable", bucket->is_writable);
1172: #endif
1173: zend_hash_update(Z_ARRVAL_P(return_value), bucket->path, bucket->path_len+1, &entry, sizeof(zval *), NULL);
1174: bucket = bucket->next;
1175: }
1176: buckets++;
1177: }
1178: }
1179:
1180: /*
1181: * Local variables:
1182: * tab-width: 4
1183: * c-basic-offset: 4
1184: * End:
1185: * vim600: sw=4 ts=4 fdm=marker
1186: * vim<600: sw=4 ts=4
1187: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>