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 // íèêàêèõ ïàäåíèé íà íåïðàâèëüíûå èíäåêñû!
76 public
77 // pSt íå îáÿçàòåëüíî çàïîìèíàòü, åñëè îí íå íóæåí.
79 // fFileStream óíè÷òîæàòü íåëüçÿ, åñëè îí ðàâåí ïàðàìåòðó pSt êîíñòðóêòîðà.
82 // âûçûâàåò ReadDirectory().
83 // ýòà ïðîöåäóðà ñàìà ðàçáåð¸òñÿ ñ äóáëèêàòàìè èì¸í: ïîäîáàâëÿåò â
84 // êîíåö èì¸í-äóáëèêàòîâ ïîä÷¸ðêèâàíèå è äåñÿòè÷íûé íîìåð.
85 // òàêæå îíà íîðìàëèçóåò âèä èì¸í.
88 // ïðè îøèáêàõ êèäàòüñÿ èñêëþ÷åíèÿìè.
91 // åñëè íå ñìîãëî îòêóïîðèòü ôàéëî (èëè åù¸ ãäå îøèáëîñü), çàøâûðí¸ò èñêëþ÷åíèå.
95 // ìîæåò âîçâðàùàòü NIL.
96 // íèêàêèõ ïàäåíèé íà íåïðàâèëüíûå èíäåêñû!
100 // ôàáðèêà òîìîâ. âñå SFS ïðè ñòàðòå äîáàâëÿþò ñâîè ôàáðèêè.
101 // áëàãîäàðÿ ýòîìó ìîæíî ñîçäàâàòü ðàçíûå âñÿêèå SFS ñòàíäàðòíûì
102 // âûçîâîì ñòàíäàðòíîé ïðîöåäóðû.
103 // ôàáðèêà ÍÅ ÄÎËÆÍÀ óáèâàòüñÿ íèêàê èíà÷å, ÷åì ïðè ïîìîùè âûçîâà
104 // SFSUnregisterVolumeFactory()! ýòî ãàðàíòèðóåò, ÷òî äâèæîê
105 // ïåðåä ðàññòðåëîì îòäàñò åé âñå å¸ òîìà.
107 public
108 // åñëè äîáàâëÿåì ôàéë äàííûõ ôàéë ñ èìåíåì òèïà "zip:....", òî
109 // SFS èçâëå÷¸ò ýòî "zip" è ïåðåäàñò â ñèþ ôóíêöèþ.
110 // åæåëè ôóíêöèÿ âåðí¸ò ïðàâäó, òî SFS âûçîâåò Produce äëÿ äàííîãî
111 // ôàéëà. åñëè íè îäíà ôàáðèêà ïðåôèêñ íå ïðèçíàåò, òî ôàéë íå îòêðîþò.
112 // èñïîëüçóåòñÿ äëÿ ñêèïàíèÿ àâòîäåòåêòà.
113 // SFS ÍÅ Ñ×ÈÒÀÅÒ ÏÐÅÔÈÊÑÎÌ ÑÒÐÎÊÓ ÊÎÐÎ×Å ÒÐ¨Õ ÑÈÌÂÎËÎÂ!
115 // ïðîâåðÿåò, ìîæåò ëè ôàáðèêà ñäåëàòü òîì äëÿ äàííîãî ôàéëà.
116 // st -- îòêðûòûé äëÿ ÷òåíèÿ ôàéëîâé ïîòîê. óêàçàòåëü ÷òåíèÿ ñòîèò â íà÷àëå.
117 // ýòîò ïîòîê íåëüçÿ çàêðûâàòü!
118 // prefix: òî, ÷òî áûëî ïåðåäàíî â IsMyVolumePrefix() èëè ''.
119 // èñêëþ÷åíèå ñ÷èòàåòñÿ îøèáêîé, âîçâðàò NIL ñ÷èòàåòñÿ îøèáêîé.
120 function Produce (const prefix, fileName: TSFSString; st: TStream): TSFSVolume; virtual; abstract;
121 // êîãäà òîì áîëüøå íå íóæåí, îí áóäåò îòäàí ôàáðèêå íà ïåðåðàáîòêó.
122 // äàëåå äâèæîê íå áóäåò þçàòü ñåé òîì.
126 // "èòåðàòîð", âîçâðàùàåìûé SFSFileList()
128 protected
134 public
140 // ïðè íåïðàâèëüíîì èíäåêñå ìîë÷à âåðí¸ò NIL.
141 // ïðè ïðàâèëüíîì òîæå ìîæåò âåðíóòü NIL!
142 // î÷åíü íå ñîâåòóþ ìåíÿòü ñîäåðæèìîå ïîëó÷åííîãî êëàññà.
143 // êîíå÷íî, ÿ ìîã áû âîçâðàùàòü íîâóþ ñòðóêòóðó èëè íå÷òî ïîõîæåå,
144 // íî áëèí, åñëè òû èäèîò è íå óìååøü äàæå êîììåíòû ÷èòàòü, òî
145 // êàêîãî òû âîîáùå â ïðîãðàììèíã ïîëåç?
151 // ýòà ôóíêöèÿ àâòîìàòè÷åñêè ïðèáü¸ò factory.
154 // äîáàâèòü ñáîðíèê â ïîñòîÿííûé ñïèñîê.
155 // åñëè ñáîðíèê ñ òàêèì èìåíåì óæå îòêðûò, òî íå îòêðûâàåò åãî ïîâòîðíî.
156 // íèêîãäà íå êèäàåò èñêëþ÷åíèé.
157 // top: äîáàâèòü â íà÷àëî ñïèñêà ïîèñêà.
158 // âåðí¸ò ëîæü ïðè îøèáêå.
159 // ñïîñîáíî îòêðûâàòü ñáîðíèêè â ñáîðíèêàõ ïðè ïîìîùè êðóòûõ èì¸í a-la:
160 // "zip:pack0::pack:pack1::wad2:pack2".
161 // â äàëüíåéøåì ñëåäóåò îáðàùàòüñÿ ê ñáîðíèêó êàê "pack2::xxx".
162 // èëè ìîæíî íàïèñàòü:
163 // "zip:pack0::pack:pack1::wad2:pack2|datafile".
164 // è îáðàùàòüñÿ êàê "datafile::xxx".
165 // "||" ïðåîáðàçóþòñÿ â ïðîñòîé "|" è ðàçäåëèòåëåì íå ñ÷èòàþòñÿ.
166 // ïðèíèìàåòñÿ âî âíèìàíèå òîëüêî ïîñëåäíÿÿ òðóáà.
169 // äîáàâèòü â ïîñòîÿííûé ñïèñîê ñáîðíèê èç ïîòîêà ds.
170 // åñëè âîçâðàùàåò èñòèíó, òî SFS ñòàíîâèòñÿ âëÿäåëüöåì ïîòîêà ds è ñàìà
171 // óãðîáèò ñåé ïîòîê ïî íåîáõîäèìîñòè.
172 // virtualName ñòàíîâèòñÿ èìåíåì ñáîðíèêà äëÿ îïåðàöèè îòêðûòèÿ ôàéëà òèïà
173 // "packfile:file.ext".
174 // åñëè êàêîé-íèáóäü ñáîðíèê ñ èìåíåì virtualName óæå îòêðûò, âåðí¸ò false.
175 // íèêîãäà íå êèäàåò èñêëþ÷åíèé.
176 // top: äîáàâèòü â íà÷àëî ñïèñêà ïîèñêà.
177 // âåðí¸ò ëîæü ïðè îøèáêå.
178 // îòêðûâàåò ñáîðíèê èç ïîòîêà. dataFileName -- ÂÈÐÒÓÀËÜÍÎÅ èìÿ.
179 // ò.å. íà ñàìîì äåëå òàêîãî ôàéëà ìîæåò è íå áûòü íà äèñêå.
180 function SFSAddSubDataFile (const virtualName: TSFSString; ds: TStream; top: Boolean=false): Boolean;
182 // øâûðÿåòñÿ èñêëþ÷åíèÿìè.
183 // åñëè fName íå èìååò óêàçàíèÿ íà ôàéë äàííûõ (ýòî òî, ÷òî îòäåëåíî îò
184 // îñòàëüíîãî èìåíè äâîåòî÷èåì), òî èùåì ñíà÷àëà ïî âñåì çàðåãèñòðèðîâàííûì
185 // ôàéëàì äàííûõ, ïîòîì â òåêóùåì êàòàëîãå, ïîòîì â êàòàëîãå, îòêóäà ñòàðòîâàëè.
186 // åñëè íè÷åãî íå íàøëè, êèäàåì èñêëþ÷åíèå.
189 // ïðè îøèáêå -- NIL, è íèêàêèõ èñêëþ÷åíèé.
192 // âîçâðàùàåò NIL ïðè îøèáêå.
193 // ïîñëå èñïîëüçîâàíèÿ, íàòóðàëüíî, èòåðàòîð íàäî ãðîõíóòü %-)
197 // èãíîðèðóåò ðåãèñòð ñèìâîëîâ
200 // ðàçîáðàòü òîëñòîå èìÿ ôàéëà, âåðíóòü âèðòóàëüíîå èìÿ ïîñëåäíåãî ñïèñêà
201 // èëè ïóñòóþ ñòîðîêó, åñëè ñïèñêîâ íå áûëî.
204 // ïðåîáðàçîâàòü ÷èñëî â ñòðîêó, êðàñèâî ðàçáàâëÿÿ çàïÿòûìè
207 // Wildcard matching
208 // this code is meant to allow wildcard pattern matches. tt is VERY useful
209 // for matching filename wildcard patterns. tt allows unix grep-like pattern
210 // comparisons, for instance:
211 //
212 // ? Matches any single characer
213 // + Matches any single characer or nothing
214 // * Matches any number of contiguous characters
215 // [abc] Matches a or b or c at that position
216 // [!abc] Matches anything but a or b or c at that position
217 // [a-e] Matches a through e at that position
218 //
219 // 'ma?ch.*' -Would match match.exe, mavch.dat, march.on, etc
220 // 'this [e-n]s a [!zy]est' -Would match 'this is a test', but would
221 // not match 'this as a yest'
222 //
228 var
229 // ïðàâäà: ðàçðåøåíî èñêàòü ôàéëî íå òîëüêî â ôàéëàõ äàííûõ, íî è íà äèñêå.
231 // ïðàâäà: åñëè ôàéë íå ïðåôèêñîâàí, òî ñíà÷àëà èùåì ôàéëî íà äèñêå,
232 // ïîòîì â ôàéëàõ äàííûõ.
234 // ïðàâäà: äàæå äëÿ ïðåôèêñîâàíûõ ôàéëîâ ñíà÷àëà ïðîñìîòðèì äèñê
235 // (åñëè óñòàíîâëåí ôëàæîê sfsDiskFirst è sfsDiskEnabled).
237 // ñïèñîê äèñêîâûõ êàòàëîãîâ äëÿ ïîèñêà ôàéëà. åñëè ïóñò -- èùåì òîëüêî â
238 // òåêóùåì. êàòàëîãè ðàçäåëÿþòñÿ òðóáîé ("|").
239 // <currentdir> çàìåíÿåòñÿ íà òåêóùèé êàòàëîã (ñ çàâåðøàþùèì "/"),
240 // <exedir> çàìåíÿåòñÿ íà êàòàëîã, ãäå ñèäèò .EXE (ñ çàâåðøàþùèì "/").
244 implementation
246 uses
247 xstreams;
251 var
253 begin
257 begin
263 const
264 // character defines
276 begin
277 result :=
285 function MatchMask (const pattern: TSFSString; p, pend: Integer; const text: TSFSString; t, tend: Integer): Boolean;
286 var
290 begin
291 // sanity checks
297 begin
299 begin
300 // no more text. check if there's no more chars in pattern (except "*" & "+")
305 exit;
308 WILD_CHAR_SINGLE: ;
309 WILD_CHAR_ESCAPE:
310 begin
315 WILD_CHAR_RANGE_OPEN:
316 begin
324 repeat
330 begin
334 begin
336 end
338 end
343 // skip the rest or the range
347 WILD_CHAR_SINGLE_OR_NONE:
348 begin
352 exit;
354 WILD_CHAR_MULTI:
355 begin
359 begin
363 exit;
374 begin
381 var
383 begin
389 begin
391 begin
393 begin
400 begin
410 type
416 fPermanent: Boolean; // èñòèíà -- íå áóäåò óãðîáëåíà, åñëè íå îñòàíåòñÿ íè îäíîãî îòêðûòîãî òîìà
417 // èñòèíà -- ýòîò òîì áûë ñîçäàí èç ïîòîêà è íå èìååò äèñêîâîãî ôàéëà, ïîòîìó ôàáðèêå áóäåò ïåðåäàíî íå èìÿ ñáîðíèêà, à ïóñòàÿ ñòðîêà
425 protected
428 public
434 var
439 // ðàçáèòü èìÿ ôàéëà íà ÷àñòè: ïðåôèêñ ôàéëîâîé ñèñòåìû, èìÿ ôàéëà äàííûõ,
440 // ñîáñòâåííî èìÿ ôàéëà
441 // èìÿ âûãëÿäèò êàê:
442 // (("sfspfx:")?"datafile::")*"filename"
444 var
446 begin
449 begin
454 else
455 begin
461 // ñàéäýôôåêò: âûðåçàåò âèðòóàëüíîå èìÿ èç dataFile.
463 var
465 begin
468 begin
471 begin
473 else
474 begin
477 break;
484 // ðàçáèòü èìÿ ñáîðíèêà íà ÷àñòè: ïðåôèêñ ôàéëîâîé ñèñòåìû, èìÿ ôàéëà äàííûõ,
485 // âèðòóàëüíîå èìÿ. åñëè âèðòóàëüíîãî èìåíè íå äàíî, îíî áóäåò ðàâíî dataFile.
486 // èìÿ âûãëÿäèò êàê:
487 // [sfspfx:]datafile[|virtname]
488 // åñëè ïåðåä äâîåòî÷èåì ìåíüøå òð¸õ áóêâ, òî ýòî ñ÷èòàåòñÿ íå ïðåôèêñîì,
489 // à èìåíåì äèñêà.
491 var
493 begin
496 else
497 begin
504 // íàéòè ïðîèçâîäèòåëÿ äëÿ ýòîãî ôàéëà (åñëè ôàéë óæå îòêðûò).
505 // onlyPerm: òîëüêî "ïîñòîÿííûå" ïðîèçâîäèòåëè.
507 var
510 begin
513 begin
515 begin
518 begin
520 begin
522 exit;
531 // íàéòè èíôó äëÿ ýòîãî òîìà.
532 // õîðîøåå èìÿ, ïðàâäà? %-)
534 begin
537 begin
539 begin
547 begin
549 begin
551 end
552 else
553 begin
555 begin
557 end
558 else
559 begin
570 var
572 begin
573 //result := (AnsiCompareText(s0, s1) == 0);
577 begin
584 var
586 begin
589 begin
591 begin
592 // avoid unnecessary string changes
599 var
602 begin
604 repeat
612 { TVolumeInfo }
614 var
617 begin
624 // òèïà ìóñîðîñáîðíèê: åñëè íàø ïîòîê áîëåå íèêåì íå þçàåòñÿ, òî óãðîáèòü åãî íàôèã
626 begin
630 begin
632 begin
635 begin
648 { TOwnedPartialStream }
651 begin
658 var
660 begin
663 begin
666 begin
674 { TSFSFileInfo }
676 begin
687 begin
693 { TSFSVolume }
695 begin
704 var
709 begin
712 try
716 // check for duplicate file names
719 begin
722 // normalize name & path
729 begin
730 // split path and name
737 // check for duplicates
739 begin
744 repeat
754 except
761 begin
768 begin
774 begin
776 else
777 begin
780 begin
783 begin
793 begin
798 begin
800 else
801 begin
808 var
811 begin
813 // normalize name, find split position
817 begin
830 { TSFSFileList }
832 var
834 begin
844 var
846 begin
851 // óáü¸ì çàïèñü, åñëè îíà âðåìåííàÿ, è â íåé íåò áîëüøå íè÷åãî îòêðûòîãî
858 begin
863 begin
870 var
872 begin
881 var
884 begin
889 begin
897 function SFSAddDataFileEx (dataFileName: TSFSString; ds: TStream; top, permanent: Integer): Integer;
898 // dataFileName ìîæåò èìåòü ïðåôèêñ òèïà "zip:" (ñì. âûøå: IsMyPrefix).
899 // ìîæåò âûêèíóòü èñêëþ÷åíèå!
900 // top:
901 // <0: äîáàâèòü â íà÷àëî ñïèñêà ïîèñêà.
902 // =0: íå ìåíÿòü.
903 // >0: äîáàâèòü â êîíåö ñïèñêà ïîèñêà.
904 // permanent:
905 // <0: ñîçäàòü "âðåìåííûé" òîì.
906 // =0: íå ìåíÿòü ôëàæîê ïîñòîÿíñòâà.
907 // >0: ñîçäàòü "ïîñòîÿííûé" òîì.
908 // åñëè ds <> nil, òî ñîçäà¸ò ñáîðíèê èç ïîòîêà. åñëè ñáîðíèê ñ èìåíåì
909 // dataFileName óæå çàðåãèñòðèðîâàí, òî ïàäàåò íàôèã.
910 // âîçâðàùàåò èíäåêñ â volumes.
911 // óìååò äåëàòü ðåêóðñèþ.
912 var
920 begin
923 begin
924 // ðåêóðñèâíîå îòêðûòèå.
925 // ðàçîáü¸ì dataFileName íà èìÿ ñáîðíèêà è îñòàòîê.
926 // pfx áóäåò èìåíåì ñáîðíèêà, dataFileName -- îñòàòêîì.
928 // ñíà÷àëà îòêðîåì ïåðâûé ñïèñîê...
930 // ...òåïåðü ïðîäîëæèì ñ îñòàòêîì.
931 // óçíàåì, êàêîå ôàéëî îòêðûâàòü.
932 // âûêîâûðÿåì ïåðâûé "::" ïðåôèêñ (ýòî áóäåò èìÿ ôàéëà).
935 // dataFileName õðàíèò îñòàòîê.
936 // èçâëå÷¸ì èìÿ ôàéëà:
938 // îòêðîåì ýòîò ôàéë
940 try
943 except
945 // óäàëèì íåèñïîëüçóåìûé âðåìåííûé òîì.
949 // óðà. îòêðûëè ôàéë. êèäàåì â âîçäóõ ÷åï÷èêè, ïðîäîëæàåì ðàçâëå÷åíèå.
951 try
954 except
958 exit;
961 // îáûêíîâåííîå íåðåêóðñèâíîå îòêðûòèå.
966 begin
973 exit;
983 try
985 begin
990 try
993 except
999 except
1005 try
1007 begin
1010 end
1012 except
1030 var
1032 begin
1034 try
1038 except
1044 var
1046 begin
1047 try
1051 except
1058 var
1061 begin
1064 begin
1075 begin
1080 end
1086 var
1094 // ïðîâåðèì, åñòü ëè ôàëî fn ãäå-òî íà äèñêàõ.
1095 var
1098 begin
1105 begin
1111 try
1113 exit;
1114 except
1119 begin
1126 begin
1127 // ïðåôèêñîâàíûé ôàéë
1129 begin
1137 try
1140 except
1145 exit;
1147 //Inc(vi.fOpenedFilesCount);
1149 exit;
1152 // íåïðåôèêñîâàíûé ôàéë
1154 begin
1158 // èùåì ïî âñåì ïåðìàíåíòíûì ïðåôèêñàì
1161 begin
1164 begin
1166 begin
1169 begin
1170 try
1173 //Inc(vi.fOpenedFilesCount);
1174 except
1188 begin
1189 try
1191 except
1197 var
1200 begin
1204 try
1206 except
1207 exit;
1211 try
1214 except
1220 initialization
1223 finalization
1224 //volumes.Free(); // it fails for some reason... Runtime 217 (^C hit). wtf?!
1225 //factories.Free(); // not need to be done actually...