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 // èãíîðèðóåò ðåãèñòð ñèìâîëîâ
198 // <0: s0 < s1
199 // =0: s0 = s1
200 // >0: s0 > s1
203 // ðàçîáðàòü òîëñòîå èìÿ ôàéëà, âåðíóòü âèðòóàëüíîå èìÿ ïîñëåäíåãî ñïèñêà
204 // èëè ïóñòóþ ñòîðîêó, åñëè ñïèñêîâ íå áûëî.
207 // ïðåîáðàçîâàòü ÷èñëî â ñòðîêó, êðàñèâî ðàçáàâëÿÿ çàïÿòûìè
210 // Wildcard matching
211 // this code is meant to allow wildcard pattern matches. tt is VERY useful
212 // for matching filename wildcard patterns. tt allows unix grep-like pattern
213 // comparisons, for instance:
214 //
215 // ? Matches any single characer
216 // + Matches any single characer or nothing
217 // * Matches any number of contiguous characters
218 // [abc] Matches a or b or c at that position
219 // [!abc] Matches anything but a or b or c at that position
220 // [a-e] Matches a through e at that position
221 //
222 // 'ma?ch.*' -Would match match.exe, mavch.dat, march.on, etc
223 // 'this [e-n]s a [!zy]est' -Would match 'this is a test', but would
224 // not match 'this as a yest'
225 //
231 var
232 // ïðàâäà: ðàçðåøåíî èñêàòü ôàéëî íå òîëüêî â ôàéëàõ äàííûõ, íî è íà äèñêå.
234 // ïðàâäà: åñëè ôàéë íå ïðåôèêñîâàí, òî ñíà÷àëà èùåì ôàéëî íà äèñêå,
235 // ïîòîì â ôàéëàõ äàííûõ.
237 // ïðàâäà: äàæå äëÿ ïðåôèêñîâàíûõ ôàéëîâ ñíà÷àëà ïðîñìîòðèì äèñê
238 // (åñëè óñòàíîâëåí ôëàæîê sfsDiskFirst è sfsDiskEnabled).
240 // ñïèñîê äèñêîâûõ êàòàëîãîâ äëÿ ïîèñêà ôàéëà. åñëè ïóñò -- èùåì òîëüêî â
241 // òåêóùåì. êàòàëîãè ðàçäåëÿþòñÿ òðóáîé ("|").
242 // <currentdir> çàìåíÿåòñÿ íà òåêóùèé êàòàëîã (ñ çàâåðøàþùèì "/"),
243 // <exedir> çàìåíÿåòñÿ íà êàòàëîã, ãäå ñèäèò .EXE (ñ çàâåðøàþùèì "/").
247 implementation
249 uses
250 xstreams;
254 var
256 begin
260 begin
266 const
267 // character defines
279 begin
280 result :=
288 function MatchMask (const pattern: TSFSString; p, pend: Integer; const text: TSFSString; t, tend: Integer): Boolean;
289 var
293 begin
294 // sanity checks
300 begin
302 begin
303 // no more text. check if there's no more chars in pattern (except "*" & "+")
308 exit;
311 WILD_CHAR_SINGLE: ;
312 WILD_CHAR_ESCAPE:
313 begin
318 WILD_CHAR_RANGE_OPEN:
319 begin
327 repeat
333 begin
337 begin
339 end
341 end
346 // skip the rest or the range
350 WILD_CHAR_SINGLE_OR_NONE:
351 begin
355 exit;
357 WILD_CHAR_MULTI:
358 begin
362 begin
366 exit;
377 begin
384 var
386 begin
392 begin
394 begin
396 begin
403 begin
413 type
419 fPermanent: Boolean; // èñòèíà -- íå áóäåò óãðîáëåíà, åñëè íå îñòàíåòñÿ íè îäíîãî îòêðûòîãî òîìà
420 // èñòèíà -- ýòîò òîì áûë ñîçäàí èç ïîòîêà è íå èìååò äèñêîâîãî ôàéëà, ïîòîìó ôàáðèêå áóäåò ïåðåäàíî íå èìÿ ñáîðíèêà, à ïóñòàÿ ñòðîêà
428 protected
431 public
437 var
442 // ðàçáèòü èìÿ ôàéëà íà ÷àñòè: ïðåôèêñ ôàéëîâîé ñèñòåìû, èìÿ ôàéëà äàííûõ,
443 // ñîáñòâåííî èìÿ ôàéëà
444 // èìÿ âûãëÿäèò êàê:
445 // (("sfspfx:")?"datafile::")*"filename"
447 var
449 begin
452 begin
457 else
458 begin
464 // ñàéäýôôåêò: âûðåçàåò âèðòóàëüíîå èìÿ èç dataFile.
466 var
468 begin
471 begin
474 begin
476 else
477 begin
480 break;
487 // ðàçáèòü èìÿ ñáîðíèêà íà ÷àñòè: ïðåôèêñ ôàéëîâîé ñèñòåìû, èìÿ ôàéëà äàííûõ,
488 // âèðòóàëüíîå èìÿ. åñëè âèðòóàëüíîãî èìåíè íå äàíî, îíî áóäåò ðàâíî dataFile.
489 // èìÿ âûãëÿäèò êàê:
490 // [sfspfx:]datafile[|virtname]
491 // åñëè ïåðåä äâîåòî÷èåì ìåíüøå òð¸õ áóêâ, òî ýòî ñ÷èòàåòñÿ íå ïðåôèêñîì,
492 // à èìåíåì äèñêà.
494 var
496 begin
499 else
500 begin
507 // íàéòè ïðîèçâîäèòåëÿ äëÿ ýòîãî ôàéëà (åñëè ôàéë óæå îòêðûò).
508 // onlyPerm: òîëüêî "ïîñòîÿííûå" ïðîèçâîäèòåëè.
510 var
513 begin
516 begin
518 begin
521 begin
523 begin
525 exit;
534 // íàéòè èíôó äëÿ ýòîãî òîìà.
535 // õîðîøåå èìÿ, ïðàâäà? %-)
537 begin
540 begin
542 begin
549 // <0: s0 < s1
550 // =0: s0 = s1
551 // >0: s0 > s1
553 begin
558 var
560 begin
563 begin
565 begin
566 // avoid unnecessary string changes
573 var
576 begin
578 repeat
586 { TVolumeInfo }
588 var
591 begin
598 // òèïà ìóñîðîñáîðíèê: åñëè íàø ïîòîê áîëåå íèêåì íå þçàåòñÿ, òî óãðîáèòü åãî íàôèã
600 begin
604 begin
606 begin
609 begin
622 { TOwnedPartialStream }
625 begin
632 var
634 begin
637 begin
640 begin
648 { TSFSFileInfo }
650 begin
661 begin
667 { TSFSVolume }
669 begin
678 var
683 begin
686 try
690 // check for duplicate file names
693 begin
696 // normalize name & path
703 begin
704 // split path and name
711 // check for duplicates
713 begin
718 repeat
728 except
735 begin
742 begin
748 begin
750 else
751 begin
754 begin
757 begin
767 begin
772 begin
774 else
775 begin
782 var
785 begin
787 // normalize name, find split position
791 begin
804 { TSFSFileList }
806 var
808 begin
818 var
820 begin
825 // óáü¸ì çàïèñü, åñëè îíà âðåìåííàÿ, è â íåé íåò áîëüøå íè÷åãî îòêðûòîãî
832 begin
837 begin
844 var
846 begin
855 var
858 begin
863 begin
871 function SFSAddDataFileEx (dataFileName: TSFSString; ds: TStream; top, permanent: Integer): Integer;
872 // dataFileName ìîæåò èìåòü ïðåôèêñ òèïà "zip:" (ñì. âûøå: IsMyPrefix).
873 // ìîæåò âûêèíóòü èñêëþ÷åíèå!
874 // top:
875 // <0: äîáàâèòü â íà÷àëî ñïèñêà ïîèñêà.
876 // =0: íå ìåíÿòü.
877 // >0: äîáàâèòü â êîíåö ñïèñêà ïîèñêà.
878 // permanent:
879 // <0: ñîçäàòü "âðåìåííûé" òîì.
880 // =0: íå ìåíÿòü ôëàæîê ïîñòîÿíñòâà.
881 // >0: ñîçäàòü "ïîñòîÿííûé" òîì.
882 // åñëè ds <> nil, òî ñîçäà¸ò ñáîðíèê èç ïîòîêà. åñëè ñáîðíèê ñ èìåíåì
883 // dataFileName óæå çàðåãèñòðèðîâàí, òî ïàäàåò íàôèã.
884 // âîçâðàùàåò èíäåêñ â volumes.
885 // óìååò äåëàòü ðåêóðñèþ.
886 var
894 begin
897 begin
898 // ðåêóðñèâíîå îòêðûòèå.
899 // ðàçîáü¸ì dataFileName íà èìÿ ñáîðíèêà è îñòàòîê.
900 // pfx áóäåò èìåíåì ñáîðíèêà, dataFileName -- îñòàòêîì.
902 // ñíà÷àëà îòêðîåì ïåðâûé ñïèñîê...
904 // ...òåïåðü ïðîäîëæèì ñ îñòàòêîì.
905 // óçíàåì, êàêîå ôàéëî îòêðûâàòü.
906 // âûêîâûðÿåì ïåðâûé "::" ïðåôèêñ (ýòî áóäåò èìÿ ôàéëà).
909 // dataFileName õðàíèò îñòàòîê.
910 // èçâëå÷¸ì èìÿ ôàéëà:
912 // îòêðîåì ýòîò ôàéë
914 try
917 except
919 // óäàëèì íåèñïîëüçóåìûé âðåìåííûé òîì.
923 // óðà. îòêðûëè ôàéë. êèäàåì â âîçäóõ ÷åï÷èêè, ïðîäîëæàåì ðàçâëå÷åíèå.
925 try
928 except
932 exit;
935 // îáûêíîâåííîå íåðåêóðñèâíîå îòêðûòèå.
940 begin
947 exit;
957 try
959 begin
964 try
967 except
973 except
979 try
981 begin
984 end
986 except
1004 var
1006 begin
1008 try
1012 except
1018 var
1020 begin
1021 try
1025 except
1032 var
1035 begin
1038 begin
1049 begin
1054 end
1060 var
1068 // ïðîâåðèì, åñòü ëè ôàëî fn ãäå-òî íà äèñêàõ.
1069 var
1072 begin
1079 begin
1085 try
1087 exit;
1088 except
1093 begin
1100 begin
1101 // ïðåôèêñîâàíûé ôàéë
1103 begin
1111 try
1114 except
1119 exit;
1121 //Inc(vi.fOpenedFilesCount);
1123 exit;
1126 // íåïðåôèêñîâàíûé ôàéë
1128 begin
1132 // èùåì ïî âñåì ïåðìàíåíòíûì ïðåôèêñàì
1135 begin
1138 begin
1140 begin
1143 begin
1144 try
1147 //Inc(vi.fOpenedFilesCount);
1148 except
1162 begin
1163 try
1165 except
1171 var
1174 begin
1178 try
1180 except
1181 exit;
1185 try
1188 except
1194 initialization
1197 finalization
1198 //volumes.Free(); // it fails for some reason... Runtime 217 (^C hit). wtf?!
1199 //factories.Free(); // not need to be done actually...