Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.02.24;
Скачать: [xml.tar.bz2];

Вниз

Рекурсивная работа с FindFirst/Next   Найти похожие ветки 

 
Riply ©   (2008-01-20 00:05) [0]

Здравствуйте !
Начинающим, часто приводят примеры, рекурсивного перебора файлов,
имеющие небольшой подводный камень. Вот решила написать об этом.
Дело в том, что пренебрегают проверкой атрибутов объекта на FILE_ATTRIBUTE_REPARSE_POINT.
А это может привести нас к различным неприятностям:
Например, к бесконечной рекурсии (директория C:\Bla_Bla\Bla_Bla\Bla_Bla_Bla ссылается на С
или идет копирование файлов на др. диск из директории, сожержащей на него ссылку).
Кроме неприятностей с зацикливанием,
могут быть и другие типа: файлы (как бы) на одном диске, но в разных файловых системах :)
И т.д. и т.п.


 
korneley ©   (2008-01-20 00:43) [1]

Рекурсия вообще, вещь скользкая. Как, впрочем, и все вокруг. Главное - вовремя остановиться. Т.е. понять, что ходишь по кругу и принять решение "стоп". Это к зацикливанию. А перебор файлов, просто естественный пример рекурсии. Обычно преподаватели внимание на особенностях файловых систем не "заостряют". Для меня до сих пор образчик рекурсии - составление однонаправленного графа (дерева) из одной таблицы. Не "File Allocation" :)


 
antonn ©   (2008-01-20 01:06) [2]

а так что может произойти?
procedure GetDirectories( Directory: string; sub:boolean; var ST:Tstrings);
var Dirs: TSearchRec; Res,Ver: integer;
begin    Res:=FindFirst(Directory+"*.*",faReadOnly+faHidden+faArchive+faDirectory,Dirs);
   while Res=0 do begin
    if((Dirs.Name<>"")and(Dirs.Name<>".")and(Dirs.Name<>"..")) then
     if ((Dirs.Attr and faDirectory)<>0) then begin
      if(sub) then
        GetDirectories(extractfilepath(Directory)+Dirs.Name+"\",sub,ST);
       // ST.Add(Dirs.Name);
     end else begin
        ST.Add(extractfilepath(Directory)+Dirs.Name);
     end;

   Res := FindNext(Dirs);
 end;
 FindClose(Dirs);
end;


 
Riply ©   (2008-01-20 01:25) [3]

> [2] antonn ©   (20.01.08 01:06)
> а так что может произойти?

Все то, что я описывала выше.
Перед вызовом GetDirectories(extractfilepath(Directory)+Dirs.Name+"\",sub,ST)
IMHO, стоит проверять не является ли наша Dirs REPARSE_POINT - ом,
и в зависимости от результата и от того, что мы хотим, принимать решение
о продолжении ее сканирования.


 
antonn ©   (2008-01-20 01:28) [4]

это типа симлинка?


 
Riply ©   (2008-01-20 01:30) [5]

> [4] antonn ©   (20.01.08 01:28)
> это типа симлинка?

Типа да, если я правильно догадалась что такое "симлинк" :)


 
korneley ©   (2008-01-20 01:32) [6]

Вот var для ST лишний, и при добавлении (.Add.) можно проверить на присутствие первого слеша (х:\) :))) А то я сдуру "х:" задал для проверки...


 
Германн ©   (2008-01-20 01:51) [7]


> Riply ©   (20.01.08 00:05)

На старости лет любопытство замучило. А чему в реальности соответствует атрибут FILE_ATTRIBUTE_REPARSE_POINT? С чем его едят, чем (ложкой или вилкой) и в каких ресторанах его подают?
:)


 
Riply ©   (2008-01-20 01:59) [8]

> [7] Германн ©   (20.01.08 01:51)
> На старости лет любопытство замучило.
> А чему в реальности соответствует атрибут FILE_ATTRIBUTE_REPARSE_POINT ?

Вполне равноправный атрибут. Такй же как и FILE_ATTRIBUTE_DIRECTORY.
Грубо, говоря он нам сообщает, что данный объект ссылается на что-то другое.

> С чем его едят, чем (ложкой или вилкой) и в каких ресторанах его подают ?

Едят его всевозможными ф-ми, связанными с файловой системой. Зависит от пожеланий клиента.
Подают на NTFS это точно, на других не смотрела :)


 
korneley ©   (2008-01-20 02:07) [9]

А если "данный объект ссылается на что-то другое", то это "другое" не надо сканировать? Просто написАть "Объект ссылается на что-то другое. Возможны циклические ссылки."? Думаю, пользователя не порадует.


 
Riply ©   (2008-01-20 02:14) [10]

> [9] korneley ©   (20.01.08 02:07)
> А если "данный объект ссылается на что-то другое", то это "другое" не надо сканировать?

Это по твоему (клиента) желанию (велению) :)

> Просто написАть "Объект ссылается на что-то другое.
> Возможны циклические ссылки."? Думаю, пользователя не порадует.

Можно попробоавть анализировать,
то на что он ссылается и при сканировании этого опять же смотреть на наличие REPARSE_POINT - ов.

Я (при работе с MFT) поступаю проще: создаю битовую маску, того где я уже была,
и если встречаю повтор, то громко кричу о "циклической зависимости" :)


 
Германн ©   (2008-01-20 02:19) [11]


> Riply ©   (20.01.08 01:59) [8]
>
> > [7] Германн ©   (20.01.08 01:51)
> > На старости лет любопытство замучило.
> > А чему в реальности соответствует атрибут FILE_ATTRIBUTE_REPARSE_POINT
> ?
>
> Вполне равноправный атрибут. Такй же как и FILE_ATTRIBUTE_DIRECTORY.
>
> Грубо, говоря он нам сообщает, что данный объект ссылается
> на что-то другое.
>

Эээ. Саша. А по русски можешь объяснить в каком случае и как, что-то (файл или каталог), получает сей атрибут?


 
Riply ©   (2008-01-20 02:28) [12]

> [11] Германн ©   (20.01.08 02:19)
> Эээ. Саша. А по русски можешь объяснить в каком случае и как, что-то (файл или каталог), получает сей атрибут?

Приведу один из вариантов его "получения"

function Volume_SetMountPointEx(const pwVolume: PWideChar; const wPointPath: WideString): DWord;
var
UniqName: array[0..Pred(MAX_VOLUME_NAME)] of WideChar;
begin
FillChar(UniqName, MAX_VOLUME_NAME, 0);
SetLastError(ERROR_SUCCESS);
if GetVolumeNameForVolumeMountPointW(pwVolume, @UniqName, MAX_VOLUME_NAME) then
 if DirectoryExists(wPointPath) or ForceDirectories(wPointPath) then
  if SetVolumeMountPointW(PWideChar(wPointPath), @UniqName) then
   begin
    Result := ERROR_SUCCESS;
    Exit;
   end;
Result := GetLastError;
end;

function Volume_SetMountPoint(const Volume: WideChar; const PointPath: WideString): DWord;
begin
if wPointPath <> ""
 then Result := Volume_SetMountPointEx(PWideChar(Volume + ":\"), PointPath)
 else Result := ERROR_INVALID_PARAMETER;
end;


Удалять при помощи DeleteVolumeMountPointW


 
Германн ©   (2008-01-20 02:37) [13]


> Riply ©   (20.01.08 02:28) [12]
>
> > [11] Германн ©   (20.01.08 02:19)
> > Эээ. Саша. А по русски можешь объяснить в каком случае
> и как, что-то (файл или каталог), получает сей атрибут?
>
> Приведу один из вариантов его "получения"
>

Norvegian Wood.
Имхо мы с тобой существуем в разных плоскостях реальности. :(
Снимаю свой вопрос: Германн ©   (20.01.08 02:19) [11].


 
korneley ©   (2008-01-20 02:42) [14]


> Можно попробоавть анализировать, то на что он ссылается
> и при сканировании этого опять же смотреть на наличие REPARSE_POINT
> - ов.Я (при работе с MFT) поступаю проще: создаю битовую
> маску, того где я уже была,и если встречаю повтор, то громко
> кричу о "циклической зависимости" :)

Ну так и я о том же: "вовремя остановиться".


 
MsGuns ©   (2008-01-20 02:54) [15]

Так много и, главное, совершенно непонятно ЗАЧЕМ ЭТО НУЖНО.
Полностью солидарен с германном


 
Virgo_Style ©   (2008-01-20 10:51) [16]

Я так понимаю, грубо говоря, это некий аналог ярлыка получается. Если в каталоге C:\Documents\Texts лежит такой "ярлык" на C:\Documents , то начнется беготня по кругу, о чем и пишет Riply (c)


 
homm ©   (2008-01-20 11:09) [17]

> [15] MsGuns ©   (20.01.08 02:54)
> Так много и, главное, совершенно непонятно ЗАЧЕМ ЭТО НУЖНО.

Мой компьютер (правый клик) — Управление — Управление дисками — любой диск (правый клик) — Изменить букву диска или путь к диску — добавить — подключить том как пустую NTFS папку — Указываем спустубю папку, например «temp\D».
Далее заходим проводником по пути «D:\temp\D\temp\D\temp\D\temp\D\temp\D…» и так далее.

Очень не приятно когда не глупые люди говорят очень глупые веши типа «да кому это надо». Как видите, надо.


 
antonn ©   (2008-01-20 12:28) [18]


> korneley ©   (20.01.08 01:32) [6]
>
> Вот var для ST лишний, и при добавлении (.Add.) можно проверить
> на присутствие первого слеша (х:\) :))) А то я сдуру "х:
> " задал для проверки...
>

нет не лишний, нужно передать именно ST:Tstrings, а не кусок ListBox :)
а корректность написания пути проверяется еще перед вызовом самой функции.


 
Zeqfreed ©   (2008-01-20 13:28) [19]

Товарищи виндузятники даже не понимают что такое симлинки и зачем нужно монтирование :)


 
antonn ©   (2008-01-20 13:32) [20]


> Товарищи виндузятники даже не понимают что такое симлинки
> и зачем нужно монтирование :)

но-но, не надо нас обижать ))


 
DVM ©   (2008-01-20 13:34) [21]


> Zeqfreed ©   (20.01.08 13:28) [19]

И это скорее достоинство Windows, чем недостаток. Зачем обычному пользователю знать, что такой символическая ссылка в файловой системе или, скажем поток NTFS? Или примонтирование/размонтирование тома?


 
Zeqfreed ©   (2008-01-20 13:37) [22]

> DVM ©   (20.01.08 13:34) [21]

Наверное, чтобы адекватно пользоваться удобными инструментами.
А разработчикам — вдвойне полезно.


 
antonn ©   (2008-01-20 13:45) [23]


> Наверное, чтобы адекватно пользоваться удобными инструментами.
>
> А разработчикам — вдвойне полезно.

это развитие холивара, не иначе :)
виндузятникам из без симлинков живется неплохо, не нужны они просто.
лучше скажите, что это за ерунда, когда ФС это визуально одно дерево относительно одной папки, а не множество деревьев относительно разделов %)


 
Zeqfreed ©   (2008-01-20 13:52) [24]

> antonn ©   (20.01.08 13:45) [23]

Одно из применений симлинков — создание одной папки с бинарниками так, чтобы не захламлять переменную PATH_DIR (или как она там называется). Продвинутым пользователям продвинутой операционной системы такое не нужно, и они радостно прописывают в переменную все директории, существующие в их файловой системе? :)


 
homm ©   (2008-01-20 13:56) [25]

> [24] Zeqfreed ©   (20.01.08 13:52)
> Продвинутым пользователям продвинутой операционной системы
> такое не нужно, и они радостно прописывают в переменную
> все директории

Чего? Пользователи продвинутых систем знают что такое PATH_DIR?


 
DVM ©   (2008-01-20 13:57) [26]


> Продвинутым пользователям продвинутой операционной системы
> такое не нужно, и они радостно прописывают в переменную
> все директории, существующие в их файловой системе?

Я уже много лет не менял вручную содержимое переменной окружения Path.


 
Zeqfreed ©   (2008-01-20 14:00) [27]

> DVM ©   (20.01.08 13:57) [26]

Как и я. Только мне не нужно прописывать полный путь к приложению, чтобы запустить его из консоли.


 
homm ©   (2008-01-20 14:23) [28]

> [27] Zeqfreed ©   (20.01.08 14:00)
> Только мне не нужно прописывать полный путь к приложению,
> чтобы запустить его из консоли.

Мне не нужно запускать приложения из консоли. Уже много лет. Странно, да?


 
homm ©   (2008-01-20 14:30) [29]

> [28] homm ©   (20.01.08 14:23)

Ксстати, немного лукавлю.
Мне не нужно запускать из консоли приложения, которые не лежат в system32 :) так правильнее. Тем не менее [25] в силе. А «пользователи» о консоле вообще не сном ни духом.


 
Zeqfreed ©   (2008-01-20 14:34) [30]

> homm ©   (20.01.08 14:30) [29]

Почему-то многим нравятся всякие велосипедные запускальщики, которые запускают программы по названию или псевдониму. Стандартный диалог запуска мог бы делать то же, если бы люди умели пользоваться симлинками.


 
DVM ©   (2008-01-20 14:34) [31]

я, кстати, постоянно запускаю из командной строки разные там bat файлы для компиляции программ из командной строки.


 
homm ©   (2008-01-20 14:35) [32]

> [30] Zeqfreed ©   (20.01.08 14:34)
> Почему-то многим нравятся всякие велосипедные запускальщики,
> которые запускают программы по названию или псевдониму.

Не понимаю, о чем вы %)


 
Virgo_Style ©   (2008-01-20 15:03) [33]

Запускальщик гораздо проще настроить, imo


 
ketmar ©   (2008-01-20 17:10) [34]

>[33] Virgo_Style©(20.01.08 15:03)
проще чем что? чем симлинк сделать? сегодня день неудачных шуток?


 
kaif ©   (2008-01-20 19:01) [35]

Однажды я писал рекурсивный вызов, в котором забыл исключить при сканировании файлов директории с именем "." и "..". Процедура занималась удалением файлов внутри "выбранной директории".
 После того, как я ее бездумно запустил и диск стал подозрительно долго чем-то заниматься, у меня возник неприятный холодок в душе... В общем, я вырубил компьютер ресет-кнопкой. Но все равно было поздно. Одним словом, пришлось переустанавливать все, включая Windows. Отсутствие простого if-а на привело к тому что процедура удаления поднялась заниматься своим черным делом в корневую директорию диска...
 :)



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2008.02.24;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.54 MB
Время: 0.08 c
2-1201192492
q1485
2008-01-24 19:34
2008.02.24
Запуск программы в модальном режиме


2-1201801065
Artem
2008-01-31 20:37
2008.02.24
Сохранить строку в ресурсе


15-1200760437
cartman315
2008-01-19 19:33
2008.02.24
Delphi и flash.ocx


2-1201596073
Edit
2008-01-29 11:41
2008.02.24
Edit с заглавной буквы


15-1201238844
user_
2008-01-25 08:27
2008.02.24
QT и БД FireBird





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский