|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-08-19 19:10 UTC] shaun dot spiller at yahoo dot com
Description: ------------ Hello developers I realised recently that PHP has no function to determine the available drive letters on Windows. As far as I can tell it's not possible to get such a list with the standard filesystem functions without generating errors for missing letters and waking up all other drives, which is, at best, extremely inefficient. I've written a function called filesys_get_roots, modelled after Java's File.listRoots(): http://java.sun.com/javase/6/docs/api/java/io/File.html#listRoots%28%29 It returns an array, which on Windows looks like this (for example): array(7) { [0]=> string(3) "A:\" [1]=> string(3) "C:\" [2]=> string(3) "D:\" [3]=> string(3) "E:\" [4]=> string(3) "F:\" [5]=> string(3) "G:\" [6]=> string(3) "M:\" } And on other platforms, like this: array(1) { [0]=> string(1) "/" } I don't know how to properly propose/submit/include the code. I've made a diff against the PHP 5.3.3 sources, if that helps: ====================================== diff -rc php-5.3.3-orig/ext/standard/basic_functions.c php-5.3.3/ext/standard/basic_functions.c *** php-5.3.3-orig/ext/standard/basic_functions.c Thu May 13 03:13:30 2010 --- php-5.3.3/ext/standard/basic_functions.c Tue Aug 17 16:34:40 2010 *************** *** 1249,1254 **** --- 1249,1257 ---- ZEND_BEGIN_ARG_INFO(arginfo_sys_get_temp_dir, 0) ZEND_END_ARG_INFO() + + ZEND_BEGIN_ARG_INFO(arginfo_filesys_get_roots, 0) + ZEND_END_ARG_INFO() /* }}} */ /* {{{ filestat.c */ ZEND_BEGIN_ARG_INFO(arginfo_disk_total_space, 0) *************** *** 3078,3083 **** --- 3081,3087 ---- PHP_FE(file, arginfo_file) PHP_FE(file_get_contents, arginfo_file_get_contents) PHP_FE(file_put_contents, arginfo_file_put_contents) + PHP_FE(filesys_get_roots, arginfo_filesys_get_roots) PHP_FE(stream_select, arginfo_stream_select) PHP_FE(stream_context_create, arginfo_stream_context_create) PHP_FE(stream_context_set_params, arginfo_stream_context_set_params) diff -rc php-5.3.3-orig/ext/standard/file.c php-5.3.3/ext/standard/file.c *** php-5.3.3-orig/ext/standard/file.c Sun May 2 21:11:22 2010 --- php-5.3.3/ext/standard/file.c Tue Aug 17 17:38:30 2010 *************** *** 2539,2544 **** --- 2539,2570 ---- } /* }}} */ + /* {{{ proto string filesys_get_roots() + Returns a list of the filesystem roots */ + PHP_FUNCTION(filesys_get_roots) + { + #ifdef PHP_WIN32 + DWORD drives = GetLogicalDrives(); + char temp[3] = "?:\\"; + int i; + + array_init(return_value); + + for (i = 0; i < 26; i++) { + if (drives & 1) { + temp[0] = 'A' + i; + add_next_index_stringl(return_value, temp, 3, 1); + } + drives >>= 1; + if (!drives) break; + } + #else + array_init(return_value); + add_index_string(return_value, 0, "/", 1); + #endif + } + /* }}} */ + /* * Local variables: * tab-width: 4 diff -rc php-5.3.3-orig/ext/standard/file.h php-5.3.3/ext/standard/file.h *** php-5.3.3-orig/ext/standard/file.h Sun Jan 3 09:23:28 2010 --- php-5.3.3/ext/standard/file.h Tue Aug 17 16:34:46 2010 *************** *** 69,74 **** --- 69,75 ---- PHP_NAMED_FUNCTION(php_if_ftruncate); PHP_NAMED_FUNCTION(php_if_fstat); PHP_FUNCTION(sys_get_temp_dir); + PHP_FUNCTION(filesys_get_roots); PHP_MINIT_FUNCTION(user_streams); ====================================== I've also written a documentation page: ====================================== <?xml version="1.0" encoding="utf-8"?> <!-- $Revision$ --> <refentry xmlns="http://docbook.org/ns/docbook" xml:id="function.filesys-get-roots"> <refnamediv> <refname>filesys_get_roots</refname> <refpurpose>Returns a list of the filesystem roots</refpurpose> </refnamediv> <refsect1 role="description"> &reftitle.description; <methodsynopsis> <type>array</type><methodname>filesys_get_roots</methodname> <void/> </methodsynopsis> <para> Returns an array listing the filesystem root directories. Unix-like systems have a single root directory ("/"). Windows systems have one or more independent drive letters ("A:\", "C:\", "D:\", etc.). </para> <para> On Windows the function returns all drive letters present in the context of the user that runs PHP. It does not attempt to determine whether drives are ready for use (e.g., whether they have a disk in). </refsect1> <refsect1 role="returnvalues"> &reftitle.returnvalues; <para> The function returns an array of strings identifying the filesystem roots, including the trailing "/" or "\". </para> </refsect1> <refsect1 role="examples"> &reftitle.examples; <para> <example> <title><function>filesys_get_roots</function> example</title> <programlisting role="php"> <![CDATA[ <?php $roots = filesys_get_roots(); var_dump($roots); ?> ]]> </programlisting> On a Unix system, the above example will output: <screen> <![CDATA[ array(1) { [0]=> string(1) "/" } ]]> </screen> On Windows, the above example will output something similar to: <screen> <![CDATA[ array(4) { [0]=> string(3) "A:\" [1]=> string(3) "C:\" [2]=> string(3) "D:\" [3]=> string(3) "E:\" } ]]> </screen> </example> </para> </refsect1> </refentry> <!-- Keep this comment at the end of the file Local variables: mode: sgml sgml-omittag:t sgml-shorttag:t sgml-minimize-attributes:nil sgml-always-quote-attributes:t sgml-indent-step:1 sgml-indent-data:t indent-tabs-mode:nil sgml-parent-document:nil sgml-default-dtd-file:"~/.phpdoc/manual.ced" sgml-exposed-tags:nil sgml-local-catalogs:nil sgml-local-ecat-files:nil End: vim600: syn=xml fen fdm=syntax fdl=2 si vim: et tw=78 syn=sgml vi: ts=1 sw=1 --> ====================================== Help me?! :) PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 05:00:01 2025 UTC |
So useless. function get_drives() { $d='ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $drives=''; for($i=0;$i<strlen($d);$i++) if(is_dir($d[$i].':\\')) $drives.=$d[$i]; echo $drives; }This does it in PHP-only code, but it takes about half a second to load the COM object, so it's probably no use except in long-running CLI scripts, or unless you cache the result for a while. function filesys_get_roots() { static $roots = null; if ($roots === null) { if (strncasecmp(PHP_OS, 'WIN', 3) === 0) { $fso = new COM('Scripting.FileSystemObject'); foreach ($fso->Drives as $drive) { $roots[] = $drive->DriveLetter . ':\\'; } } else { $roots = array('/'); } } return $roots; } Really the function needs to be in the PHP core.