Форум: "Прочее";
Текущий архив: 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.076 c