📄 filestat.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Jim Winstead <jimw@php.net> | +----------------------------------------------------------------------+ *//* $Id: filestat.c,v 1.112.2.11.2.4 2007/01/01 09:46:48 sebastian Exp $ */#include "php.h"#include "safe_mode.h"#include "fopen_wrappers.h"#include "php_globals.h"#include <stdlib.h>#include <sys/stat.h>#include <string.h>#include <errno.h>#include <ctype.h>#include <time.h>#if HAVE_UNISTD_H# include <unistd.h>#endif#if HAVE_SYS_PARAM_H# include <sys/param.h>#endif#if HAVE_SYS_VFS_H# include <sys/vfs.h>#endif#ifdef OS2# define INCL_DOS# include <os2.h>#endif#if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)# include <sys/statvfs.h>#elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_STATFS)# include <sys/statfs.h>#elif defined(HAVE_SYS_MOUNT_H) && defined(HAVE_STATFS)# include <sys/mount.h>#endif#if HAVE_PWD_H# ifdef PHP_WIN32# include "win32/pwd.h"# else# include <pwd.h># endif#endif#if HAVE_GRP_H# ifdef PHP_WIN32# include "win32/grp.h"# else# include <grp.h># endif#endif#if HAVE_UTIME# ifdef PHP_WIN32# include <sys/utime.h># else# include <utime.h># endif#endif#include "basic_functions.h"#include "php_filestat.h"#ifndef S_ISDIR#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)#endif#ifndef S_ISREG#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)#endif#ifndef S_ISLNK#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)#endif#define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )/* Switches for various filestat functions: */#define FS_PERMS 0#define FS_INODE 1#define FS_SIZE 2#define FS_OWNER 3#define FS_GROUP 4#define FS_ATIME 5#define FS_MTIME 6#define FS_CTIME 7#define FS_TYPE 8#define FS_IS_W 9#define FS_IS_R 10#define FS_IS_X 11#define FS_IS_FILE 12#define FS_IS_DIR 13#define FS_IS_LINK 14#define FS_EXISTS 15#define FS_LSTAT 16#define FS_STAT 17PHP_RINIT_FUNCTION(filestat){ BG(CurrentStatFile)=NULL; BG(CurrentStatLength)=0; return SUCCESS;}PHP_RSHUTDOWN_FUNCTION(filestat) { if (BG(CurrentStatFile)) { efree (BG(CurrentStatFile)); BG(CurrentStatFile) = NULL; } return SUCCESS;}/* {{{ proto float disk_total_space(string path) Get total disk space for filesystem that path is on */PHP_FUNCTION(disk_total_space){ pval **path;#ifdef WINDOWS double bytestotal; HINSTANCE kernel32; FARPROC gdfse; typedef BOOL (WINAPI *gdfse_func)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER); gdfse_func func; /* These are used by GetDiskFreeSpaceEx, if available. */ ULARGE_INTEGER FreeBytesAvailableToCaller; ULARGE_INTEGER TotalNumberOfBytes; ULARGE_INTEGER TotalNumberOfFreeBytes; /* These are used by GetDiskFreeSpace otherwise. */ DWORD SectorsPerCluster; DWORD BytesPerSector; DWORD NumberOfFreeClusters; DWORD TotalNumberOfClusters;#else /* not - WINDOWS */#if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS) struct statvfs buf;#elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS) struct statfs buf;#endif double bytestotal = 0;#endif /* WINDOWS */ if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &path)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(path); if (php_check_open_basedir(Z_STRVAL_PP(path) TSRMLS_CC)) { RETURN_FALSE; }#ifdef WINDOWS /* GetDiskFreeSpaceEx is only available in NT and Win95 post-OSR2, so we have to jump through some hoops to see if the function exists. */ kernel32 = LoadLibrary("kernel32.dll"); if (kernel32) { gdfse = GetProcAddress(kernel32, "GetDiskFreeSpaceExA"); /* It's available, so we can call it. */ if (gdfse) { func = (gdfse_func)gdfse; if (func(Z_STRVAL_PP(path), &FreeBytesAvailableToCaller, &TotalNumberOfBytes, &TotalNumberOfFreeBytes) == 0) RETURN_FALSE; /* i know - this is ugly, but i works <thies@thieso.net> */ bytestotal = TotalNumberOfBytes.HighPart * (double) (((unsigned long)1) << 31) * 2.0 + TotalNumberOfBytes.LowPart; } /* If it's not available, we just use GetDiskFreeSpace */ else { if (GetDiskFreeSpace(Z_STRVAL_PP(path), &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters) == 0) RETURN_FALSE; bytestotal = (double)TotalNumberOfClusters * (double)SectorsPerCluster * (double)BytesPerSector; } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load kernel32.dll"); RETURN_FALSE; }#elif defined(OS2) { FSALLOCATE fsinfo; char drive = Z_STRVAL_PP(path)[0] & 95; if (DosQueryFSInfo( drive ? drive - 64 : 0, FSIL_ALLOC, &fsinfo, sizeof( fsinfo ) ) == 0) bytestotal = (double)fsinfo.cbSector * fsinfo.cSectorUnit * fsinfo.cUnit; }#else /* WINDOWS, OS/2 */#if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS) if (statvfs(Z_STRVAL_PP(path), &buf)) RETURN_FALSE; if (buf.f_frsize) { bytestotal = (((double)buf.f_blocks) * ((double)buf.f_frsize)); } else { bytestotal = (((double)buf.f_blocks) * ((double)buf.f_bsize)); }#elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS) if (statfs(Z_STRVAL_PP(path), &buf)) RETURN_FALSE; bytestotal = (((double)buf.f_bsize) * ((double)buf.f_blocks));#endif#endif /* WINDOWS */ RETURN_DOUBLE(bytestotal);}/* }}} *//* {{{ proto float disk_free_space(string path) Get free disk space for filesystem that path is on */PHP_FUNCTION(disk_free_space){ pval **path;#ifdef WINDOWS double bytesfree; HINSTANCE kernel32; FARPROC gdfse; typedef BOOL (WINAPI *gdfse_func)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER); gdfse_func func; /* These are used by GetDiskFreeSpaceEx, if available. */ ULARGE_INTEGER FreeBytesAvailableToCaller; ULARGE_INTEGER TotalNumberOfBytes; ULARGE_INTEGER TotalNumberOfFreeBytes; /* These are used by GetDiskFreeSpace otherwise. */ DWORD SectorsPerCluster; DWORD BytesPerSector; DWORD NumberOfFreeClusters; DWORD TotalNumberOfClusters;#else /* not - WINDOWS */#if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS) struct statvfs buf;#elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS) struct statfs buf;#endif double bytesfree = 0;#endif /* WINDOWS */ if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &path)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(path); if (php_check_open_basedir(Z_STRVAL_PP(path) TSRMLS_CC)) { RETURN_FALSE; }#ifdef WINDOWS /* GetDiskFreeSpaceEx is only available in NT and Win95 post-OSR2, so we have to jump through some hoops to see if the function exists. */ kernel32 = LoadLibrary("kernel32.dll"); if (kernel32) { gdfse = GetProcAddress(kernel32, "GetDiskFreeSpaceExA"); /* It's available, so we can call it. */ if (gdfse) { func = (gdfse_func)gdfse; if (func(Z_STRVAL_PP(path), &FreeBytesAvailableToCaller, &TotalNumberOfBytes, &TotalNumberOfFreeBytes) == 0) RETURN_FALSE; /* i know - this is ugly, but i works <thies@thieso.net> */ bytesfree = FreeBytesAvailableToCaller.HighPart * (double) (((unsigned long)1) << 31) * 2.0 + FreeBytesAvailableToCaller.LowPart; } /* If it's not available, we just use GetDiskFreeSpace */ else { if (GetDiskFreeSpace(Z_STRVAL_PP(path), &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters) == 0) RETURN_FALSE; bytesfree = (double)NumberOfFreeClusters * (double)SectorsPerCluster * (double)BytesPerSector; } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load kernel32.dll"); RETURN_FALSE; }#elif defined(OS2) { FSALLOCATE fsinfo; char drive = Z_STRVAL_PP(path)[0] & 95; if (DosQueryFSInfo( drive ? drive - 64 : 0, FSIL_ALLOC, &fsinfo, sizeof( fsinfo ) ) == 0) bytesfree = (double)fsinfo.cbSector * fsinfo.cSectorUnit * fsinfo.cUnitAvail; }#else /* WINDOWS, OS/2 */#if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS) if (statvfs(Z_STRVAL_PP(path), &buf)) RETURN_FALSE; if (buf.f_frsize) { bytesfree = (((double)buf.f_bavail) * ((double)buf.f_frsize)); } else { bytesfree = (((double)buf.f_bavail) * ((double)buf.f_bsize)); }#elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS) if (statfs(Z_STRVAL_PP(path), &buf)) RETURN_FALSE;#ifdef NETWARE bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bfree));#else bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bavail));#endif#endif#endif /* WINDOWS */ RETURN_DOUBLE(bytesfree);}/* }}} *//* {{{ proto bool chgrp(string filename, mixed group) Change file group */PHP_FUNCTION(chgrp){#if !defined(WINDOWS) && !defined(NETWARE) /* I guess 'chgrp' won't be available on NetWare */ pval **filename, **group; gid_t gid; struct group *gr=NULL; int ret; if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &filename, &group)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(filename); if (Z_TYPE_PP(group) == IS_STRING) { gr = getgrnam(Z_STRVAL_PP(group)); if (!gr) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_PP(group)); RETURN_FALSE; } gid = gr->gr_gid; } else { convert_to_long_ex(group); gid = Z_LVAL_PP(group); } if (PG(safe_mode) &&(!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) { RETURN_FALSE; } /* Check the basedir */ if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) { RETURN_FALSE; } ret = VCWD_CHOWN(Z_STRVAL_PP(filename), -1, gid); if (ret == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); RETURN_FALSE; } RETURN_TRUE;#else RETURN_FALSE;#endif}/* }}} *//* {{{ proto bool chown (string filename, mixed user) Change file owner */PHP_FUNCTION(chown){#if !defined(WINDOWS) && !defined(NETWARE) /* I guess 'chown' won't be available on NetWare */ pval **filename, **user; int ret; uid_t uid; struct passwd *pw = NULL; if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &filename, &user)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(filename); if (Z_TYPE_PP(user) == IS_STRING) { pw = getpwnam(Z_STRVAL_PP(user)); if (!pw) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_PP(user)); RETURN_FALSE; } uid = pw->pw_uid; } else { convert_to_long_ex(user); uid = Z_LVAL_PP(user); } if (PG(safe_mode) &&(!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) { RETURN_FALSE; } /* Check the basedir */ if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) { RETURN_FALSE; } ret = VCWD_CHOWN(Z_STRVAL_PP(filename), uid, -1); if (ret == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); RETURN_FALSE; }#endif RETURN_TRUE;}/* }}} *//* {{{ proto bool chmod(string filename, int mode) Change file mode */PHP_FUNCTION(chmod){ pval **filename, **mode; int ret; mode_t imode; if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &filename, &mode)==FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(filename); convert_to_long_ex(mode); if (PG(safe_mode) &&(!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) { RETURN_FALSE; } /* Check the basedir */ if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) { RETURN_FALSE; } imode = (mode_t) Z_LVAL_PP(mode); /* in safe mode, do not allow to setuid files. Setuiding files could allow users to gain privileges that safe mode doesn't give them. */ if(PG(safe_mode)) imode &= 0777; ret = VCWD_CHMOD(Z_STRVAL_PP(filename), imode); if (ret == -1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -