+109
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
procedure RemoveDir(path: string);
var
sr: TSearchRec;
begin
if FindFirst(path + '\*.*', faAnyFile, sr) = 0 then
begin
repeat
if sr.Attr and faDirectory = 0 then
DeleteFile(path + '\' + sr.name);
else
RemoveDir(path + '\' + sr.name);
until
FindNext(sr) <> 0;
end;
FindClose(sr);
RemoveDirectory(PChar(path));
end;
История такова, писал я как-то программу по курсовому. (Это было еще года два-три назад, когда я про юнит тесты и различные технологии проектирования и разработки ничего не знал.) По задумки программа распаковывала некие файлы во временный каталог рядом с приложением и по завершению работы с ними удаляла эту папку вот этим методом. Итак, запустил я эту подпрограмму на выполнение для проверки ее работоспособности и смотрю в файловом менеджере, что папка успешно удалилась и все ок. Но вдруг студия начала жаловаться что нет каких-то файлов, я смотрю в файловый менеджер и вижу что файлы проекта программы исчезают буквально на глазах! Естественно я резко убиваю программу и далее начинаю восстанавливать исходники. Благо, что делал бэкапы и эта подпрограмма проработала все ничего, а ведь последствия могли быть еще больше. А мораль такая, нужно быть предельно внимательным, когда работаешь с удалением какой-либо информации.
P.S. Нужно добавить проверку между 10 и 11 строкой:
if (sr.Name <> '..') and (sr.Name <> '.') then
Запостил: vanished,
18 Декабря 2010
istem 18.12.2010 12:35 # 0
komprenda 18.12.2010 13:26 # −10
TarasB 18.12.2010 18:02 # +1
Или нет, не сообразил. Или сообразил только для "..", а для "." забыл. Не помню. Кажется, у меня рекурсия (на ".") вылезла за стек и всё благополучно повисло, и всё.
bugmenot 18.12.2010 20:10 # +2
ctm 20.12.2010 18:21 # +2
К тому же в стек помещается только указатель на строку, а сама строка - в динамической памяти через GetMem
vanished 19.12.2010 10:57 # +2
bugmenot 19.12.2010 11:54 # +2
FadedInto 19.12.2010 13:07 # +3
Плохая формулировка. Просто "не знал" лучше.
inkanus-gray 19.12.2010 17:30 # 0
Lure Of Chaos 20.12.2010 20:17 # 0
я что-то пропустил оО
bugmenot 20.12.2010 20:21 # +1
inkanus-gray 20.12.2010 20:57 # 0
VFAT.VXD предоставлял API через INT 21 под VDM (смотрите Ralf Brown's Interrupt List, например). Этот же API предоставляет NTVDM, начиная с Windows XP (в более старых NT надо было ставить сторонний драйвер ntlfn).
Этот же API эмулирует драйвер doslfn (он к тому же умеет читать длинные имена Joliet на сиди-дисках), а также какой-то драйвер из ДР-ДОСа, а ROM-DOS имеет встроенную поддержку длинных имён.
Наконец, драйвер vfat в Линуксе откуда длинные имена берёт?
Lure Of Chaos 20.12.2010 21:07 # 0
inkanus-gray 20.12.2010 21:14 # 0
Обычный заголовок файла — 32 байта — содержит имя (8+3 символа), атрибуты, дату и время создания, размер, указатель на первый кластер и ещё кое-что.
Длинное имя разбивается на слоты, каждый слот содержит 13 уникодных символов (26 байт), символы запихиваются во все поля подряд (они не нужны), в атрибуте стоит 0xf - системный+скрытый+ридонли+метка, а сами слоты помещаются непосредственно перед коротким именем файла. Если мы не будем проверять атрибуты, то FindNext под голым ДОСом (без VFAT) будет находить слоты длинных имён как обычные файлы, размер и указатель на кластер этих слотов, естественно, будут содержать кашу.
Lure Of Chaos 20.12.2010 21:17 # 0
ctm 20.12.2010 18:26 # 0
FadedInto 18.12.2010 18:43 # +4
IncludeTrailingPathDelimiter() 1 раз в начало дописать. Тем более, что path не const.
inkanus-gray 19.12.2010 17:34 # +1
FadedInto 20.12.2010 13:20 # 0
inkanus-gray 20.12.2010 20:59 # +1