Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Cимволические ссылки в Windows
Форумы портала PHP.SU » PHP » Пользовательские функции » Cимволические ссылки в Windows

Страниц (1): [1]
 

1. Uchkuma - 03 Июня, 2010 - 10:12:09 - перейти к сообщению
Работая над своим проектом и решая очередную задачу, я столкнулся необходимостью использования символических ссылок на файлы. Все бы ничего, но для windows php-функции для работы с символическими ссылками не реализованы. На сервере unix, однако разработка ведется в среде windows на Денвере.

Немного погуглив, я обналужил - в винде таки есть поддержка символических ссылок!!! Правда нормальная поддержка симлинков появилась сравнительно недавно, и если у вас WinXP, то вам ничего не светит.

Итак, для работы вам понадобится Windows Vista или старше. ИМХО, конечно, лучше Windows 7. В этих версиях появилась утилита mklink, с помощью которой мы и будем выкручиваться.

Функция symlink для windows:
PHP:
скопировать код в буфер обмена
  1. if(!function_exists('symlink')){
  2. function symlink($file, $link){
  3. //если винда младше висты - неудача
  4. if(preg_match('/^win/i', PHP_OS) AND substr(php_uname(), -4)<6000) return false;
  5. //меняем слеши на виндовый манер
  6. $file = str_replace('/', '\\', $file);
  7. $link = str_replace('/', '\\', $link);
  8.  
  9. if(!exec("mklink $link $file", $out, $err) OR $err!=0) return false;
  10.  
  11. return true;
  12. }
  13. }

Функция is_link для windows:
(функцию называем islink, ибо ф-я is_link есть и в windows-версии php, хотя она и не имеет смысла)
PHP:
скопировать код в буфер обмена
  1. function islink($link){
  2. //если не винда, используем стандартную is_link()
  3. if(!preg_match('/^win/i', PHP_OS)) return is_link($link);
  4. //винда младше висты - неудача
  5. if(substr(php_uname(), -4)<6000) return false;
  6. //меняем слеши на виндовый манер
  7. $link = str_replace('/', '\\', $link);
  8.  
  9. if(!exec("dir $link /a-d", $out, $err) OR !preg_match('/<SYMLINK>/i', utf8_encode($out[5]))) return false; //$out[5] - это нужная нам строка в выводе
  10.  
  11. return true;
  12. }

Необходимая строка вывода, по которой мы определяем является ли файл символической ссылкой, у меня появляется на 5 позиции ($out[5]). Не знаю для всех ли версий интерпретаторов командных строк это будет верно. В крайнем случае можно будет сделать обход по массиву $out.

В функциях мы проверяем операционную систему, на которой работает php и номер сборки windows (6xxx - vista, 7xxx - windows 7).

Надо сказать, что эти функции работают в десятки раз медленнее, чем их юниксовый аналог. Однако для вас это может оказаться не принципиальным. Я, например, провожу эти операции в цикле по списку из 1000 файлов - минуту-две ждать приходится =(

Жду комментарии. Спасибо!
2. Uchkuma - 11 Июня, 2010 - 10:59:25 - перейти к сообщению
Теперь требуется функция, с помощью которой можно будет определить существует файл, на который указывает символическая ссылка, или нет. Некоторый аналог функции linkinfo() для windows. Если есть идеи, пишите!

...

В общем пока назрело только это:
PHP:
скопировать код в буфер обмена
  1. function link_info($link){
  2. //если не винда, запускаем стандартную функцию linkinfo()
  3. if(!preg_match('/^win/i', PHP_OS)) return is_file(readlink($link));
  4. //винда ниже висты - неудача
  5. if(substr(php_uname(), -4)<6000) return false;
  6.  
  7. $fd = @fopen($link, 'r');
  8. //если дескриптор файла открылся, значит он существует
  9. if($fd){
  10. fclose($fd);
  11. return true;
  12. } else {
  13. return false;
  14. }
  15. }

...

Обнаружена странная вещь - функция linkinfo() выдает правду даже при отсутствующем файле, на который указывает ссылка.
Строку
PHP:
скопировать код в буфер обмена
  1. if(!preg_match('/^win/i', PHP_OS)) return linkinfo($link);
заменил на
PHP:
скопировать код в буфер обмена
  1. if(!preg_match('/^win/i', PHP_OS)) return is_file(readlink($link));

 

Powered by ExBB FM 1.0 RC1