Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.02.24;
Скачать: CL | DM;

Вниз

Рекурсивная работа с 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;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.017 c
2-1201937189
Urvin
2008-02-02 10:26
2008.02.24
Размер плюсиков в TTreeView


2-1201959461
Scapman
2008-02-02 16:37
2008.02.24
Сделать форму активной


2-1201555963
IntruderLab
2008-01-29 00:32
2008.02.24
TStringGrid


2-1201598063
Ник
2008-01-29 12:14
2008.02.24
Что возвращает Chr(I)?


15-1201220309
Riply
2008-01-25 03:18
2008.02.24
К вопросу "каким способом надо решать задачу"