Coverage Report

Created: 2025-06-13 06:43

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