Coverage Report

Created: 2022-02-19 20:30

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