Esempio n. 1
0
static void php_stat(const char *filename, php_stat_len filename_length, int type, pval *return_value)
{
	struct stat *stat_sb;
	int rmask=S_IROTH,wmask=S_IWOTH,xmask=S_IXOTH; /* access rights defaults to other */
	BLS_FETCH();

	stat_sb = &BG(sb);

	if (!BG(CurrentStatFile) || strcmp(filename, BG(CurrentStatFile))) {
		if (!BG(CurrentStatFile) || filename_length > BG(CurrentStatLength)) {
			if (BG(CurrentStatFile)) {
				efree(BG(CurrentStatFile));
			}
			BG(CurrentStatLength) = filename_length;
			BG(CurrentStatFile) = estrndup(filename, filename_length);
		} else {
			memcpy(BG(CurrentStatFile), filename, filename_length+1);
		}
#if HAVE_SYMLINK
		BG(lsb).st_mode = 0; /* mark lstat buf invalid */
#endif
		if (VCWD_STAT(BG(CurrentStatFile), &BG(sb)) == -1) {
			if (!IS_LINK_OPERATION() && (type != 15 || errno != ENOENT)) { /* fileexists() test must print no error */
				php_error(E_NOTICE,"stat failed for %s (errno=%d - %s)", BG(CurrentStatFile), errno, strerror(errno));
			}
			efree(BG(CurrentStatFile));
			BG(CurrentStatFile) = NULL;
			if (!IS_LINK_OPERATION()) { /* Don't require success for link operation */
				RETURN_FALSE;
			}
		}
	}

#if HAVE_SYMLINK
	if (IS_LINK_OPERATION() && !BG(lsb).st_mode) {
		/* do lstat if the buffer is empty */
		if (VCWD_LSTAT(filename, &BG(lsb)) == -1) {
			php_error(E_NOTICE, "lstat failed for %s (errno=%d - %s)", filename, errno, strerror(errno));
			RETURN_FALSE;
		}
	}
#endif


	if (type >= 9 && type <= 11) {
		if(BG(sb).st_uid==getuid()) {
			rmask=S_IRUSR;
			wmask=S_IWUSR;
			xmask=S_IXUSR;
		} else if(BG(sb).st_gid==getgid()) {
			rmask=S_IRGRP;
			wmask=S_IWGRP;
			xmask=S_IXGRP;
		} else {
			int   groups,n,i;
			gid_t *gids;

			groups = getgroups(0,NULL);
			if(groups) {
				gids=(gid_t *)emalloc(groups*sizeof(gid_t));
				n=getgroups(groups,gids);
				for(i=0;i<n;i++){
					if(BG(sb).st_gid==gids[i]) {
						rmask=S_IRGRP;
						wmask=S_IWGRP;
						xmask=S_IXGRP;
						break;
					}
				}
				efree(gids);
			}
		}
	}

	switch (type) {
	case 0: /* fileperms */
		RETURN_LONG((long)BG(sb).st_mode);
	case 1: /* fileinode */
		RETURN_LONG((long)BG(sb).st_ino);
	case 2: /* filesize  */
		RETURN_LONG((long)BG(sb).st_size);
	case 3: /* fileowner */
		RETURN_LONG((long)BG(sb).st_uid);
	case 4: /* filegroup */
		RETURN_LONG((long)BG(sb).st_gid);
	case 5: /* fileatime */
		RETURN_LONG((long)BG(sb).st_atime);
	case 6: /* filemtime */
		RETURN_LONG((long)BG(sb).st_mtime);
	case 7: /* filectime */
		RETURN_LONG((long)BG(sb).st_ctime);
	case 8: /* filetype */
#if HAVE_SYMLINK
		if (S_ISLNK(BG(lsb).st_mode)) {
			RETURN_STRING("link",1);
		}
#endif
		switch(BG(sb).st_mode&S_IFMT) {
		case S_IFIFO: RETURN_STRING("fifo",1);
		case S_IFCHR: RETURN_STRING("char",1);
		case S_IFDIR: RETURN_STRING("dir",1);
		case S_IFBLK: RETURN_STRING("block",1);
		case S_IFREG: RETURN_STRING("file",1);
#if defined(S_IFSOCK) && !defined(ZEND_WIN32)&&!defined(__BEOS__)
		case S_IFSOCK: RETURN_STRING("socket",1);
#endif
		}
		php_error(E_WARNING,"Unknown file type (%d)",BG(sb).st_mode&S_IFMT);
		RETURN_STRING("unknown", 1);
	case 9: /*is writable*/
		if (getuid()==0) {
			RETURN_LONG(1); /* root */
		}
		RETURN_LONG((BG(sb).st_mode & wmask) != 0);
	case 10: /*is readable*/
		if (getuid()==0) {
			RETURN_LONG(1); /* root */
		}
		RETURN_LONG((BG(sb).st_mode&rmask)!=0);
	case 11: /*is executable*/
		if (getuid()==0) {
			xmask = S_IXROOT; /* root */
		}
		RETURN_LONG((BG(sb).st_mode&xmask)!=0 && !S_ISDIR(BG(sb).st_mode));
	case 12: /*is file*/
		RETURN_LONG(S_ISREG(BG(sb).st_mode));
	case 13: /*is dir*/
		RETURN_LONG(S_ISDIR(BG(sb).st_mode));
	case 14: /*is link*/
#if HAVE_SYMLINK
		RETURN_LONG(S_ISLNK(BG(lsb).st_mode));
#else
		RETURN_FALSE;
#endif
	case 15: /*file exists*/
		RETURN_TRUE; /* the false case was done earlier */
	case 16: /* lstat */
#if HAVE_SYMLINK
		stat_sb = &BG(lsb);
#endif
		/* FALLTHROUGH */
	case 17: /* stat */
		if (array_init(return_value) == FAILURE) {
			RETURN_FALSE;
		}
		add_next_index_long(return_value, stat_sb->st_dev);
		add_next_index_long(return_value, stat_sb->st_ino);
		add_next_index_long(return_value, stat_sb->st_mode);
		add_next_index_long(return_value, stat_sb->st_nlink);
		add_next_index_long(return_value, stat_sb->st_uid);
		add_next_index_long(return_value, stat_sb->st_gid);
#ifdef HAVE_ST_RDEV
		add_next_index_long(return_value, stat_sb->st_rdev);
#else
		add_next_index_long(return_value, -1);
#endif
		add_next_index_long(return_value, stat_sb->st_size);
		add_next_index_long(return_value, stat_sb->st_atime);
		add_next_index_long(return_value, stat_sb->st_mtime);
		add_next_index_long(return_value, stat_sb->st_ctime);
#ifdef HAVE_ST_BLKSIZE
		add_next_index_long(return_value, stat_sb->st_blksize);
#else
		add_next_index_long(return_value, -1);
#endif
#ifdef HAVE_ST_BLOCKS
		add_next_index_long(return_value, stat_sb->st_blocks);
#else
		add_next_index_long(return_value, -1);
#endif
		/* Support string references as well as numerical*/
		add_assoc_long ( return_value , "dev" , stat_sb->st_dev );
		add_assoc_long ( return_value , "ino" , stat_sb->st_ino );
		add_assoc_long ( return_value , "mode" , stat_sb->st_mode );
		add_assoc_long ( return_value , "nlink" , stat_sb->st_nlink );
		add_assoc_long ( return_value , "uid" , stat_sb->st_uid );
		add_assoc_long ( return_value , "gid" , stat_sb->st_gid );

#ifdef HAVE_ST_RDEV
		add_assoc_long ( return_value, "rdev" , stat_sb->st_rdev );
#endif
#ifdef HAVE_ST_BLKSIZE
		add_assoc_long ( return_value , "blksize" , stat_sb->st_blksize );
#endif

		add_assoc_long ( return_value , "size" , stat_sb->st_size );
		add_assoc_long ( return_value , "atime" , stat_sb->st_atime );
		add_assoc_long ( return_value , "mtime" , stat_sb->st_mtime );
		add_assoc_long ( return_value , "ctime" , stat_sb->st_ctime );

#ifdef HAVE_ST_BLOCKS
		add_assoc_long ( return_value , "blocks" , stat_sb->st_blocks );
#endif

		return;
	}
	php_error(E_WARNING, "didn't understand stat call");
	RETURN_FALSE;
}
Esempio n. 2
0
static void phar_file_stat(const char *filename, php_stat_len filename_length, int type, void (*orig_stat_func)(INTERNAL_FUNCTION_PARAMETERS), INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
	if (!filename_length) {
		RETURN_FALSE;
	}

	if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
		char *arch, *entry, *fname;
		int arch_len, entry_len, fname_len;
		zend_stat_t sb = {0};
		phar_entry_info *data = NULL;
		phar_archive_data *phar;

		fname = (char*)zend_get_executed_filename();

		/* we are checking for existence of a file within the relative path.  Chances are good that this is
		   retrieving something from within the phar archive */

		if (strncasecmp(fname, "phar://", 7)) {
			goto skip_phar;
		}
		fname_len = strlen(fname);
		if (PHAR_G(last_phar) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
			arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
			arch_len = PHAR_G(last_phar_name_len);
			entry = estrndup(filename, filename_length);
			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
			entry_len = (int) filename_length;
			phar = PHAR_G(last_phar);
			goto splitted;
		}
		if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {

			efree(entry);
			entry = estrndup(filename, filename_length);
			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
			entry_len = (int) filename_length;
			if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
				efree(arch);
				efree(entry);
				goto skip_phar;
			}
splitted:
			entry = phar_fix_filepath(entry, &entry_len, 1);
			if (entry[0] == '/') {
				if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
					efree(entry);
					goto stat_entry;
				}
				goto notfound;
			}
			if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
				efree(entry);
				goto stat_entry;
			}
			if (zend_hash_str_exists(&(phar->virtual_dirs), entry, entry_len)) {
				efree(entry);
				efree(arch);
				if (IS_EXISTS_CHECK(type)) {
					RETURN_TRUE;
				}
				sb.st_size = 0;
				sb.st_mode = 0777;
				sb.st_mode |= S_IFDIR; /* regular directory */
#ifdef NETWARE
				sb.st_mtime.tv_sec = phar->max_timestamp;
				sb.st_atime.tv_sec = phar->max_timestamp;
				sb.st_ctime.tv_sec = phar->max_timestamp;
#else
				sb.st_mtime = phar->max_timestamp;
				sb.st_atime = phar->max_timestamp;
				sb.st_ctime = phar->max_timestamp;
#endif
				goto statme_baby;
			} else {
				char *save;
				int save_len;

notfound:
				efree(entry);
				save = PHAR_G(cwd);
				save_len = PHAR_G(cwd_len);
				/* this file is not in the current directory, use the original path */
				entry = estrndup(filename, filename_length);
				entry_len = filename_length;
				PHAR_G(cwd) = "/";
				PHAR_G(cwd_len) = 0;
				/* clean path without cwd */
				entry = phar_fix_filepath(entry, &entry_len, 1);
				if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
					PHAR_G(cwd) = save;
					PHAR_G(cwd_len) = save_len;
					efree(entry);
					if (IS_EXISTS_CHECK(type)) {
						efree(arch);
						RETURN_TRUE;
					}
					goto stat_entry;
				}
				if (zend_hash_str_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
					PHAR_G(cwd) = save;
					PHAR_G(cwd_len) = save_len;
					efree(entry);
					efree(arch);
					if (IS_EXISTS_CHECK(type)) {
						RETURN_TRUE;
					}
					sb.st_size = 0;
					sb.st_mode = 0777;
					sb.st_mode |= S_IFDIR; /* regular directory */
#ifdef NETWARE
					sb.st_mtime.tv_sec = phar->max_timestamp;
					sb.st_atime.tv_sec = phar->max_timestamp;
					sb.st_ctime.tv_sec = phar->max_timestamp;
#else
					sb.st_mtime = phar->max_timestamp;
					sb.st_atime = phar->max_timestamp;
					sb.st_ctime = phar->max_timestamp;
#endif
					goto statme_baby;
				}
				PHAR_G(cwd) = save;
				PHAR_G(cwd_len) = save_len;
				efree(entry);
				efree(arch);
				/* Error Occurred */
				if (!IS_EXISTS_CHECK(type)) {
					php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
				}
				RETURN_FALSE;
			}
stat_entry:
			efree(arch);
			if (!data->is_dir) {
				sb.st_size = data->uncompressed_filesize;
				sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
				if (data->link) {
					sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
				} else {
					sb.st_mode |= S_IFREG; /* regular file */
				}
				/* timestamp is just the timestamp when this was added to the phar */
#ifdef NETWARE
				sb.st_mtime.tv_sec = data->timestamp;
				sb.st_atime.tv_sec = data->timestamp;
				sb.st_ctime.tv_sec = data->timestamp;
#else
				sb.st_mtime = data->timestamp;
				sb.st_atime = data->timestamp;
				sb.st_ctime = data->timestamp;
#endif
			} else {
				sb.st_size = 0;
				sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
				sb.st_mode |= S_IFDIR; /* regular directory */
				if (data->link) {
					sb.st_mode |= S_IFLNK;
				}
				/* timestamp is just the timestamp when this was added to the phar */
#ifdef NETWARE
				sb.st_mtime.tv_sec = data->timestamp;
				sb.st_atime.tv_sec = data->timestamp;
				sb.st_ctime.tv_sec = data->timestamp;
#else
				sb.st_mtime = data->timestamp;
				sb.st_atime = data->timestamp;
				sb.st_ctime = data->timestamp;
#endif
			}

statme_baby:
			if (!phar->is_writeable) {
				sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
			}

			sb.st_nlink = 1;
			sb.st_rdev = -1;
			/* this is only for APC, so use /dev/null device - no chance of conflict there! */
			sb.st_dev = 0xc;
			/* generate unique inode number for alias/filename, so no phars will conflict */
			if (data) {
				sb.st_ino = data->inode;
			}
#ifndef PHP_WIN32
			sb.st_blksize = -1;
			sb.st_blocks = -1;
#endif
			phar_fancy_stat(&sb, type, return_value);
			return;
		}
	}
skip_phar:
	orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
	return;
}