1 // streaming file system (virtual)
2 {$MODE DELPHI}
3 {.$R-}
6 interface
8 uses
12 type
21 public
23 fPath: TSFSString; // ðàçäåëèòåëè êàòàëîãîâ -- "/"; êîðåíü íèêàê íå îáîçíà÷åí, åñëè íå ïóñòîå, îáÿçàíî çàâåðøàåòñÿ "/"
36 // âèðòóàëüíàÿ ôàéëîâàÿ ñèñòåìà. ÒÎËÜÊÎ ÄËß ×ÒÅÍÈß!
37 // òîì ÍÅ ÄÎËÆÅÍ óáèâàòüñÿ íèêàê èíà÷å, ÷åì ïðè ïîìîùè ôàáðèêè!
39 protected
45 // ïðèøèáèòü âñå ñòðóêòóðû.
46 // íå äîëæíà ïàäàòü, åñëè å¸ âûçûâàþò íåñêîëüêî ðàç.
49 // âûçûâàåòñÿ èç DoDirectoryRead() äëÿ çàïîëíåíèÿ ñïèñêà ôàéëîâ.
50 // ñ÷èòàåòñÿ, ÷òî âñå ìàãèêè óæå ïðîâåðåíû è ôàéë òî÷íî íàø.
51 // fFileName, fFileStream óæå óñòàíîâëåíû, fFiles ñîçäàí,
52 // â í¸ì, ñêîðåå âñåãî, íèêîãî íåò.
53 // ïîçèöèÿ ïîòîêà -- òà, ÷òî îñòàâèëà ôàáðèêà.
54 // ïðè îøèáêàõ êèäàòü èñêëþ÷åíèå, òîãäà òîì áóäåò ïðèáèò ôàáðèêîé.
55 // ðàçäåëèòåëè ïóòåé äîëæíû áûòü òîëüêî "/", êîðíåâîé "/" äîëæåí
56 // áûòü îïóùåí, ïóòè (åñëè íå ïóñòûå) äîëæíû çàâåðøàòüñÿ "/"!
57 // fName äîëæíî ñîäåðæàòü òîëüêî èìÿ, fPath -- òîëüêî ïóòü.
58 // â ïðèíöèïå, îá ýòîì ïîçàáîòèòñÿ DoDirectoryRead(), íî çà÷åì
59 // äàâàòü åìó ëèøíþþ ðàáîòó?
62 // íàéòè ôàéë, âåðíóòü åãî èíäåêñ â fFiles.
63 // ýòà ïðîöåäóðà ìîæåò ìåíÿòü fFiles!
64 // fPath -- â ïðàâèëüíîé ôîðìå, ñ "/", êîðíåâîé "/" óáèò, ôèíàëüíûé äîáàâëåí.
65 // åñëè ôàéë íå íàéäåí, âåðíóòü -1.
68 // âîçâðàùàåò êîëè÷åñòâî ôàéëîâ â fFiles
71 // âîçâðàùàåò ôàéë ñ èíäåêñîì index.
72 // ìîæåò âîçâðàùàòü NIL.
73 // íèêàêèõ ïàäåíèé íà íåïðàâèëüíûå èíäåêñû!
78 public
79 // pSt íå îáÿçàòåëüíî çàïîìèíàòü, åñëè îí íå íóæåí.
81 // fFileStream óíè÷òîæàòü íåëüçÿ, åñëè îí ðàâåí ïàðàìåòðó pSt êîíñòðóêòîðà.
84 // âûçûâàåò ReadDirectory().
85 // ýòà ïðîöåäóðà ñàìà ðàçáåð¸òñÿ ñ äóáëèêàòàìè èì¸í: ïîäîáàâëÿåò â
86 // êîíåö èì¸í-äóáëèêàòîâ ïîä÷¸ðêèâàíèå è äåñÿòè÷íûé íîìåð.
87 // òàêæå îíà íîðìàëèçóåò âèä èì¸í.
90 // ïðè îøèáêàõ êèäàòüñÿ èñêëþ÷åíèÿìè.
93 // åñëè íå ñìîãëî îòêóïîðèòü ôàéëî (èëè åù¸ ãäå îøèáëîñü), çàøâûðí¸ò èñêëþ÷åíèå.
97 // ìîæåò âîçâðàùàòü NIL.
98 // íèêàêèõ ïàäåíèé íà íåïðàâèëüíûå èíäåêñû!
102 // ôàáðèêà òîìîâ. âñå SFS ïðè ñòàðòå äîáàâëÿþò ñâîè ôàáðèêè.
103 // áëàãîäàðÿ ýòîìó ìîæíî ñîçäàâàòü ðàçíûå âñÿêèå SFS ñòàíäàðòíûì
104 // âûçîâîì ñòàíäàðòíîé ïðîöåäóðû.
105 // ôàáðèêà ÍÅ ÄÎËÆÍÀ óáèâàòüñÿ íèêàê èíà÷å, ÷åì ïðè ïîìîùè âûçîâà
106 // SFSUnregisterVolumeFactory()! ýòî ãàðàíòèðóåò, ÷òî äâèæîê
107 // ïåðåä ðàññòðåëîì îòäàñò åé âñå å¸ òîìà.
109 public
110 // åñëè äîáàâëÿåì ôàéë äàííûõ ôàéë ñ èìåíåì òèïà "zip:....", òî
111 // SFS èçâëå÷¸ò ýòî "zip" è ïåðåäàñò â ñèþ ôóíêöèþ.
112 // åæåëè ôóíêöèÿ âåðí¸ò ïðàâäó, òî SFS âûçîâåò Produce äëÿ äàííîãî
113 // ôàéëà. åñëè íè îäíà ôàáðèêà ïðåôèêñ íå ïðèçíàåò, òî ôàéë íå îòêðîþò.
114 // èñïîëüçóåòñÿ äëÿ ñêèïàíèÿ àâòîäåòåêòà.
115 // SFS ÍÅ Ñ×ÈÒÀÅÒ ÏÐÅÔÈÊÑÎÌ ÑÒÐÎÊÓ ÊÎÐÎ×Å ÒÐ¨Õ ÑÈÌÂÎËÎÂ!
117 // ïðîâåðÿåò, ìîæåò ëè ôàáðèêà ñäåëàòü òîì äëÿ äàííîãî ôàéëà.
118 // st -- îòêðûòûé äëÿ ÷òåíèÿ ôàéëîâé ïîòîê. óêàçàòåëü ÷òåíèÿ ñòîèò â íà÷àëå.
119 // ýòîò ïîòîê íåëüçÿ çàêðûâàòü!
120 // prefix: òî, ÷òî áûëî ïåðåäàíî â IsMyVolumePrefix() èëè ''.
121 // èñêëþ÷åíèå ñ÷èòàåòñÿ îøèáêîé, âîçâðàò NIL ñ÷èòàåòñÿ îøèáêîé.
122 function Produce (const prefix, fileName: TSFSString; st: TStream): TSFSVolume; virtual; abstract;
123 // êîãäà òîì áîëüøå íå íóæåí, îí áóäåò îòäàí ôàáðèêå íà ïåðåðàáîòêó.
124 // äàëåå äâèæîê íå áóäåò þçàòü ñåé òîì.
128 // "èòåðàòîð", âîçâðàùàåìûé SFSFileList()
130 protected
136 public
142 // ïðè íåïðàâèëüíîì èíäåêñå ìîë÷à âåðí¸ò NIL.
143 // ïðè ïðàâèëüíîì òîæå ìîæåò âåðíóòü NIL!
144 // î÷åíü íå ñîâåòóþ ìåíÿòü ñîäåðæèìîå ïîëó÷åííîãî êëàññà.
145 // êîíå÷íî, ÿ ìîã áû âîçâðàùàòü íîâóþ ñòðóêòóðó èëè íå÷òî ïîõîæåå,
146 // íî áëèí, åñëè òû èäèîò è íå óìååøü äàæå êîììåíòû ÷èòàòü, òî
147 // êàêîãî òû âîîáùå â ïðîãðàììèíã ïîëåç?
153 // ýòà ôóíêöèÿ àâòîìàòè÷åñêè ïðèáü¸ò factory.
156 // äîáàâèòü ñáîðíèê â ïîñòîÿííûé ñïèñîê.
157 // åñëè ñáîðíèê ñ òàêèì èìåíåì óæå îòêðûò, òî íå îòêðûâàåò åãî ïîâòîðíî.
158 // íèêîãäà íå êèäàåò èñêëþ÷åíèé.
159 // top: äîáàâèòü â íà÷àëî ñïèñêà ïîèñêà.
160 // âåðí¸ò ëîæü ïðè îøèáêå.
161 // ñïîñîáíî îòêðûâàòü ñáîðíèêè â ñáîðíèêàõ ïðè ïîìîùè êðóòûõ èì¸í a-la:
162 // "zip:pack0::pack:pack1::wad2:pack2".
163 // â äàëüíåéøåì ñëåäóåò îáðàùàòüñÿ ê ñáîðíèêó êàê "pack2::xxx".
164 // èëè ìîæíî íàïèñàòü:
165 // "zip:pack0::pack:pack1::wad2:pack2|datafile".
166 // è îáðàùàòüñÿ êàê "datafile::xxx".
167 // "||" ïðåîáðàçóþòñÿ â ïðîñòîé "|" è ðàçäåëèòåëåì íå ñ÷èòàþòñÿ.
168 // ïðèíèìàåòñÿ âî âíèìàíèå òîëüêî ïîñëåäíÿÿ òðóáà.
171 // äîáàâèòü â ïîñòîÿííûé ñïèñîê ñáîðíèê èç ïîòîêà ds.
172 // åñëè âîçâðàùàåò èñòèíó, òî SFS ñòàíîâèòñÿ âëÿäåëüöåì ïîòîêà ds è ñàìà
173 // óãðîáèò ñåé ïîòîê ïî íåîáõîäèìîñòè.
174 // virtualName ñòàíîâèòñÿ èìåíåì ñáîðíèêà äëÿ îïåðàöèè îòêðûòèÿ ôàéëà òèïà
175 // "packfile:file.ext".
176 // åñëè êàêîé-íèáóäü ñáîðíèê ñ èìåíåì virtualName óæå îòêðûò, âåðí¸ò false.
177 // íèêîãäà íå êèäàåò èñêëþ÷åíèé.
178 // top: äîáàâèòü â íà÷àëî ñïèñêà ïîèñêà.
179 // âåðí¸ò ëîæü ïðè îøèáêå.
180 // îòêðûâàåò ñáîðíèê èç ïîòîêà. dataFileName -- ÂÈÐÒÓÀËÜÍÎÅ èìÿ.
181 // ò.å. íà ñàìîì äåëå òàêîãî ôàéëà ìîæåò è íå áûòü íà äèñêå.
182 function SFSAddSubDataFile (const virtualName: TSFSString; ds: TStream; top: Boolean=false): Boolean;
184 // øâûðÿåòñÿ èñêëþ÷åíèÿìè.
185 // åñëè fName íå èìååò óêàçàíèÿ íà ôàéë äàííûõ (ýòî òî, ÷òî îòäåëåíî îò
186 // îñòàëüíîãî èìåíè äâîåòî÷èåì), òî èùåì ñíà÷àëà ïî âñåì çàðåãèñòðèðîâàííûì
187 // ôàéëàì äàííûõ, ïîòîì â òåêóùåì êàòàëîãå, ïîòîì â êàòàëîãå, îòêóäà ñòàðòîâàëè.
188 // åñëè íè÷åãî íå íàøëè, êèäàåì èñêëþ÷åíèå.
191 // ïðè îøèáêå -- NIL, è íèêàêèõ èñêëþ÷åíèé.
194 // âîçâðàùàåò NIL ïðè îøèáêå.
195 // ïîñëå èñïîëüçîâàíèÿ, íàòóðàëüíî, èòåðàòîð íàäî ãðîõíóòü %-)
199 // èãíîðèðóåò ðåãèñòð ñèìâîëîâ
202 // ðàçîáðàòü òîëñòîå èìÿ ôàéëà, âåðíóòü âèðòóàëüíîå èìÿ ïîñëåäíåãî ñïèñêà
203 // èëè ïóñòóþ ñòîðîêó, åñëè ñïèñêîâ íå áûëî.
206 // ïðåîáðàçîâàòü ÷èñëî â ñòðîêó, êðàñèâî ðàçáàâëÿÿ çàïÿòûìè
209 // Wildcard matching
210 // this code is meant to allow wildcard pattern matches. tt is VERY useful
211 // for matching filename wildcard patterns. tt allows unix grep-like pattern
212 // comparisons, for instance:
213 //
214 // ? Matches any single characer
215 // + Matches any single characer or nothing
216 // * Matches any number of contiguous characters
217 // [abc] Matches a or b or c at that position
218 // [!abc] Matches anything but a or b or c at that position
219 // [a-e] Matches a through e at that position
220 //
221 // 'ma?ch.*' -Would match match.exe, mavch.dat, march.on, etc
222 // 'this [e-n]s a [!zy]est' -Would match 'this is a test', but would
223 // not match 'this as a yest'
224 //
229 // this will compare only last path element from sfspath
235 var
236 // ïðàâäà: ðàçðåøåíî èñêàòü ôàéëî íå òîëüêî â ôàéëàõ äàííûõ, íî è íà äèñêå.
238 // ïðàâäà: åñëè ôàéë íå ïðåôèêñîâàí, òî ñíà÷àëà èùåì ôàéëî íà äèñêå,
239 // ïîòîì â ôàéëàõ äàííûõ.
241 // ïðàâäà: äàæå äëÿ ïðåôèêñîâàíûõ ôàéëîâ ñíà÷àëà ïðîñìîòðèì äèñê
242 // (åñëè óñòàíîâëåí ôëàæîê sfsDiskFirst è sfsDiskEnabled).
244 // ñïèñîê äèñêîâûõ êàòàëîãîâ äëÿ ïîèñêà ôàéëà. åñëè ïóñò -- èùåì òîëüêî â
245 // òåêóùåì. êàòàëîãè ðàçäåëÿþòñÿ òðóáîé ("|").
246 // <currentdir> çàìåíÿåòñÿ íà òåêóùèé êàòàëîã (ñ çàâåðøàþùèì "/"),
247 // <exedir> çàìåíÿåòñÿ íà êàòàëîã, ãäå ñèäèò .EXE (ñ çàâåðøàþùèì "/").
251 implementation
253 uses
254 xstreams;
258 var
260 begin
264 begin
270 const
271 // character defines
283 begin
284 result :=
292 function MatchMask (const pattern: TSFSString; p, pend: Integer; const text: TSFSString; t, tend: Integer): Boolean;
293 var
297 begin
298 // sanity checks
304 begin
306 begin
307 // no more text. check if there's no more chars in pattern (except "*" & "+")
312 exit;
315 WILD_CHAR_SINGLE: ;
316 WILD_CHAR_ESCAPE:
317 begin
322 WILD_CHAR_RANGE_OPEN:
323 begin
331 repeat
337 begin
341 begin
343 end
345 end
350 // skip the rest or the range
354 WILD_CHAR_SINGLE_OR_NONE:
355 begin
359 exit;
361 WILD_CHAR_MULTI:
362 begin
366 begin
370 exit;
381 begin
388 var
390 begin
396 begin
398 begin
400 begin
407 begin
417 type
423 fPermanent: Boolean; // èñòèíà -- íå áóäåò óãðîáëåíà, åñëè íå îñòàíåòñÿ íè îäíîãî îòêðûòîãî òîìà
424 // èñòèíà -- ýòîò òîì áûë ñîçäàí èç ïîòîêà è íå èìååò äèñêîâîãî ôàéëà, ïîòîìó ôàáðèêå áóäåò ïåðåäàíî íå èìÿ ñáîðíèêà, à ïóñòàÿ ñòðîêà
432 protected
435 public
441 var
446 // ðàçáèòü èìÿ ôàéëà íà ÷àñòè: ïðåôèêñ ôàéëîâîé ñèñòåìû, èìÿ ôàéëà äàííûõ,
447 // ñîáñòâåííî èìÿ ôàéëà
448 // èìÿ âûãëÿäèò êàê:
449 // (("sfspfx:")?"datafile::")*"filename"
451 var
453 begin
456 begin
461 else
462 begin
468 // ñàéäýôôåêò: âûðåçàåò âèðòóàëüíîå èìÿ èç dataFile.
470 var
472 begin
475 begin
478 begin
480 else
481 begin
484 break;
491 // ðàçáèòü èìÿ ñáîðíèêà íà ÷àñòè: ïðåôèêñ ôàéëîâîé ñèñòåìû, èìÿ ôàéëà äàííûõ,
492 // âèðòóàëüíîå èìÿ. åñëè âèðòóàëüíîãî èìåíè íå äàíî, îíî áóäåò ðàâíî dataFile.
493 // èìÿ âûãëÿäèò êàê:
494 // [sfspfx:]datafile[|virtname]
495 // åñëè ïåðåä äâîåòî÷èåì ìåíüøå òð¸õ áóêâ, òî ýòî ñ÷èòàåòñÿ íå ïðåôèêñîì,
496 // à èìåíåì äèñêà.
498 var
500 begin
503 else
504 begin
511 // íàéòè ïðîèçâîäèòåëÿ äëÿ ýòîãî ôàéëà (åñëè ôàéë óæå îòêðûò).
512 // onlyPerm: òîëüêî "ïîñòîÿííûå" ïðîèçâîäèòåëè.
514 var
517 begin
520 begin
522 begin
525 begin
527 begin
529 exit;
538 // íàéòè èíôó äëÿ ýòîãî òîìà.
539 // õîðîøåå èìÿ, ïðàâäà? %-)
541 begin
544 begin
546 begin
554 begin
556 begin
558 end
559 else
560 begin
562 begin
564 end
565 else
566 begin
577 var
579 begin
580 //result := (AnsiCompareText(s0, s1) == 0);
584 begin
590 // this will compare only last path element from sfspath
592 {var
593 i: Integer;}
594 begin
596 (*
597 if not result and (length(sfspath) > 1) then
598 begin
599 i := length(sfspath);
600 while i > 1 do
601 begin
602 while (i > 1) and (sfspath[i-1] <> '/') do Dec(i);
603 if i <= 1 then exit;
604 writeln('{', sfspath, '} [', Copy(sfspath, i, length(sfspath)), '] : [', path, ']');
605 result := SFSStrEqu(Copy(sfspath, i, length(sfspath)), path);
606 end;
607 end;
608 *)
612 var
614 begin
617 begin
619 begin
620 // avoid unnecessary string changes
627 var
630 begin
632 repeat
640 { TVolumeInfo }
642 var
645 begin
652 // òèïà ìóñîðîñáîðíèê: åñëè íàø ïîòîê áîëåå íèêåì íå þçàåòñÿ, òî óãðîáèòü åãî íàôèã
654 begin
658 begin
660 begin
663 begin
676 { TOwnedPartialStream }
679 begin
686 var
688 begin
691 begin
694 begin
702 { TSFSFileInfo }
704 begin
715 begin
721 { TSFSVolume }
723 begin
732 begin
736 var
741 begin
744 try
748 // check for duplicate file names
751 begin
754 // normalize name & path
761 begin
762 // split path and name
769 // check for duplicates
771 begin
776 repeat
786 except
794 begin
801 begin
807 begin
809 else
810 begin
813 begin
816 begin
826 begin
831 begin
833 else
834 begin
841 var
844 begin
846 // normalize name, find split position
850 begin
863 { TSFSFileList }
865 var
867 begin
877 var
879 begin
884 // óáü¸ì çàïèñü, åñëè îíà âðåìåííàÿ, è â íåé íåò áîëüøå íè÷åãî îòêðûòîãî
891 begin
896 begin
903 var
905 begin
914 var
917 begin
922 begin
930 function SFSAddDataFileEx (dataFileName: TSFSString; ds: TStream; top, permanent: Integer): Integer;
931 // dataFileName ìîæåò èìåòü ïðåôèêñ òèïà "zip:" (ñì. âûøå: IsMyPrefix).
932 // ìîæåò âûêèíóòü èñêëþ÷åíèå!
933 // top:
934 // <0: äîáàâèòü â íà÷àëî ñïèñêà ïîèñêà.
935 // =0: íå ìåíÿòü.
936 // >0: äîáàâèòü â êîíåö ñïèñêà ïîèñêà.
937 // permanent:
938 // <0: ñîçäàòü "âðåìåííûé" òîì.
939 // =0: íå ìåíÿòü ôëàæîê ïîñòîÿíñòâà.
940 // >0: ñîçäàòü "ïîñòîÿííûé" òîì.
941 // åñëè ds <> nil, òî ñîçäà¸ò ñáîðíèê èç ïîòîêà. åñëè ñáîðíèê ñ èìåíåì
942 // dataFileName óæå çàðåãèñòðèðîâàí, òî ïàäàåò íàôèã.
943 // âîçâðàùàåò èíäåêñ â volumes.
944 // óìååò äåëàòü ðåêóðñèþ.
945 var
953 begin
956 begin
957 // ðåêóðñèâíîå îòêðûòèå.
958 // ðàçîáü¸ì dataFileName íà èìÿ ñáîðíèêà è îñòàòîê.
959 // pfx áóäåò èìåíåì ñáîðíèêà, dataFileName -- îñòàòêîì.
961 // ñíà÷àëà îòêðîåì ïåðâûé ñïèñîê...
963 // ...òåïåðü ïðîäîëæèì ñ îñòàòêîì.
964 // óçíàåì, êàêîå ôàéëî îòêðûâàòü.
965 // âûêîâûðÿåì ïåðâûé "::" ïðåôèêñ (ýòî áóäåò èìÿ ôàéëà).
968 // dataFileName õðàíèò îñòàòîê.
969 // èçâëå÷¸ì èìÿ ôàéëà:
971 // îòêðîåì ýòîò ôàéë
973 try
976 except
978 // óäàëèì íåèñïîëüçóåìûé âðåìåííûé òîì.
982 // óðà. îòêðûëè ôàéë. êèäàåì â âîçäóõ ÷åï÷èêè, ïðîäîëæàåì ðàçâëå÷åíèå.
984 try
987 except
991 exit;
994 // îáûêíîâåííîå íåðåêóðñèâíîå îòêðûòèå.
999 begin
1006 exit;
1016 try
1018 begin
1023 try
1026 except
1032 except
1038 try
1040 begin
1043 end
1045 except
1063 var
1065 begin
1067 try
1071 except
1077 var
1079 begin
1080 try
1084 except
1091 var
1094 begin
1097 begin
1108 begin
1113 end
1119 var
1127 // ïðîâåðèì, åñòü ëè ôàëî fn ãäå-òî íà äèñêàõ.
1128 var
1131 begin
1138 begin
1144 try
1146 exit;
1147 except
1152 begin
1159 begin
1160 // ïðåôèêñîâàíûé ôàéë
1162 begin
1170 try
1173 except
1178 exit;
1180 //Inc(vi.fOpenedFilesCount);
1182 exit;
1185 // íåïðåôèêñîâàíûé ôàéë
1187 begin
1191 // èùåì ïî âñåì ïåðìàíåíòíûì ïðåôèêñàì
1194 begin
1197 begin
1199 begin
1202 begin
1203 try
1206 //Inc(vi.fOpenedFilesCount);
1207 except
1221 begin
1222 try
1224 except
1230 var
1233 begin
1237 try
1239 except
1240 exit;
1244 try
1247 except
1253 initialization
1256 finalization
1257 //volumes.Free(); // it fails for some reason... Runtime 217 (^C hit). wtf?!
1258 //factories.Free(); // not need to be done actually...