filestat.c 31 KB

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