Re: [INTERNALS-WIN] chDir, chDrive, #35691

[email protected] ("Pierre Joye")
Newsgroups php.internals.win
Message-ID <[email protected]>
Hi!

On Mon, Jun 23, 2008 at 10:40 PM, Pierre Joye <[email protected]> wrote:
> On Mon, Jun 23, 2008 at 10:23 PM, Andi Gutmans <[email protected]> wrote:
>> Can you share the patch before committing? This is pretty touchy stuff
>> and we need to make sure we don't break anything else (incl.
>> performance) when we put this in.
>
> It is pretty much the same as:
>
> chdir('d:\public_html');
>
> when public_html is the current dir on d:
>
> except that it is actually a bit faster than calling chdir() only
> (userland comparison) because you know that the path is absolute (no
> check in virtual_chdir_file).
>
> I will post the patch once I managed to sit down to write it :) I
> thought I would have enough time to do it today.

My initial thought was to add this feature at the TSRM level to allow
some small optimization. But given the gain, it was not worth it.

The current patch adds three functions. The names used are the same as
in msdn or other language and use the letter syntax (C/C++ API uses
the driver number, 1=>A, 2=>B. VB and other high level language uses a
single letter to define a drive).

- getdrive
- chdrive
- getdcwd

There is no impact on anything else in php as the functions are self
contained and rely on TSRM to change the CWD.

Sample usage:

var_dump(getcwd());
var_dump(chdrive('D'));
var_dump(getcwd());
var_dump(getdrive());
var_dump(getdcwd('c'));

Output:
string(24) "C:\php-sdk\2k5\x86\php53"
bool(true)
string(3) "D:\"
string(1) "D"
string(24) "C:\php-sdk\2k5\x86\php53"

Cheers,
-- 
Pierre

http://blog.thepimp.net | http://www.libgd.org
windows_drive.patch.txt (text/plain, 5.1 KB)
Index: basic_functions.c
===================================================================
RCS file: /repository/php-src/ext/standard/basic_functions.c,v
retrieving revision 1.725.2.31.2.64.2.35
diff -u -r1.725.2.31.2.64.2.35 basic_functions.c
--- basic_functions.c	25 May 2008 14:06:13 -0000	1.725.2.31.2.64.2.35
+++ basic_functions.c	24 Jun 2008 10:08:44 -0000
@@ -1072,6 +1072,22 @@
 	ZEND_ARG_INFO(0, directory)
 ZEND_END_ARG_INFO()
 
+#ifdef PHP_WIN32
+static
+ZEND_BEGIN_ARG_INFO(arginfo_getdrive, 0)
+ZEND_END_ARG_INFO()
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_chdrive, 0)
+	ZEND_ARG_INFO(0, drive)
+ZEND_END_ARG_INFO()
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_getdcwd, 0)
+	ZEND_ARG_INFO(0, drive)
+ZEND_END_ARG_INFO()
+#endif
+
 static
 ZEND_BEGIN_ARG_INFO(arginfo_getcwd, 0)
 ZEND_END_ARG_INFO()
@@ -3559,6 +3575,12 @@
 	PHP_FE(closedir,														arginfo_closedir)
 	PHP_FE(chdir,															arginfo_chdir)
 
+#ifdef PHP_WIN32
+	PHP_FE(getdrive,														arginfo_getdrive)
+	PHP_FE(chdrive,															arginfo_chdrive)
+	PHP_FE(getdcwd,															arginfo_getdcwd)
+#endif
+
 #if defined(HAVE_CHROOT) && !defined(ZTS) && ENABLE_CHROOT_FUNC
 	PHP_FE(chroot,															arginfo_chroot)
 #endif
Index: dir.c
===================================================================
RCS file: /repository/php-src/ext/standard/dir.c,v
retrieving revision 1.147.2.3.2.12.2.7
diff -u -r1.147.2.3.2.12.2.7 dir.c
--- dir.c	11 Jun 2008 09:01:56 -0000	1.147.2.3.2.12.2.7
+++ dir.c	24 Jun 2008 10:21:18 -0000
@@ -306,6 +306,118 @@
 /* }}} */
 #endif
 
+#ifdef PHP_WIN32
+/* {{{ proto bool chdrive(string directory)
+   Change the current drive */
+PHP_FUNCTION(getdrive)
+{
+	int drivenr;
+	char drive[2] = "";
+	
+	if (zend_parse_parameters_none() == FAILURE) {
+		return;
+	}
+
+	/* backup current drive to restore it if safemode or open_basedir fail */
+	drivenr = _getdrive();
+	drive[0] = (char)(drivenr + 'A' - 1);
+	RETURN_STRINGL(drive, 1, 1);
+}
+/* }}} */
+
+/* {{{ proto bool chdrive(string directory)
+   Change the current drive */
+PHP_FUNCTION(chdrive)
+{
+	char *drive;
+	int ret, drive_len, drivenr, olddrive;
+	char path[MAXPATHLEN];
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &drive, &drive_len) == FAILURE) {
+		RETURN_FALSE;
+	}
+
+	if (drive_len > 0) {
+		drive[0] = toupper(drive[0]);
+		if ((drive[0] < 'A' || drive[0] > 'Z')) {
+			RETURN_FALSE;
+		}
+	} else {
+		RETURN_FALSE;
+	}
+
+	/* backup current drive to restore it if safemode or open_basedir fail */
+	olddrive = _getdrive();
+
+	drivenr =  drive[0] - 'A' + 1;
+	ret = _chdrive(drivenr);
+	if (ret != 0) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
+		RETURN_FALSE;
+	}
+
+	if (_getdcwd(drivenr, path, MAXPATHLEN) == NULL ) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
+		ret = _chdrive(olddrive);
+		if (ret != 0) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
+		}
+		RETURN_FALSE;
+	}
+
+	if ((PG(safe_mode) && !php_checkuid(path, NULL, CHECKUID_CHECK_FILE_AND_DIR)) || php_check_open_basedir(path TSRMLS_CC)) {
+		ret = _chdrive(olddrive);
+		if (ret != 0) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
+		}
+		RETURN_FALSE;
+	}
+
+	ret = VCWD_CHDIR(path);
+	if (ret != 0) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
+		ret = _chdrive(olddrive);
+		if (ret != 0) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
+		}
+		RETURN_FALSE;
+	}
+	RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool chdrive(string directory)
+   Change the current drive */
+PHP_FUNCTION(getdcwd)
+{
+	int drivenr, drive_len;
+	char *drive;
+	char path[MAXPATHLEN];
+	
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &drive, &drive_len) == FAILURE) {
+		RETURN_FALSE;
+	}
+	if (drive_len > 0) {
+		drive[0] = toupper(drive[0]);
+		if ((drive[0] < 'A' || drive[0] > 'Z')) {
+			RETURN_FALSE;
+		}
+	} else {
+		RETURN_FALSE;
+	}
+
+	drivenr =  drive[0] - 'A' + 1;
+
+	if (_getdcwd(drivenr, path, MAXPATHLEN) == NULL ) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
+		RETURN_FALSE;
+	}
+
+	RETURN_STRING(path, 1);
+}
+/* }}} */
+#endif
+
 /* {{{ proto bool chdir(string directory)
    Change the current directory */
 PHP_FUNCTION(chdir)
Index: php_dir.h
===================================================================
RCS file: /repository/php-src/ext/standard/php_dir.h,v
retrieving revision 1.24.2.1.2.1.2.1
diff -u -r1.24.2.1.2.1.2.1 php_dir.h
--- php_dir.h	31 Dec 2007 07:17:15 -0000	1.24.2.1.2.1.2.1
+++ php_dir.h	24 Jun 2008 10:07:55 -0000
@@ -27,6 +27,13 @@
 PHP_FUNCTION(opendir);
 PHP_FUNCTION(closedir);
 PHP_FUNCTION(chdir);
+
+#ifdef PHP_WIN32
+PHP_FUNCTION(getdrive);
+PHP_FUNCTION(chdrive);
+PHP_FUNCTION(getdcwd);
+#endif
+
 #if defined(HAVE_CHROOT) && !defined(ZTS) && ENABLE_CHROOT_FUNC
 PHP_FUNCTION(chroot);
 #endif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.