14919a4cb2f1f8df67e57cd56554a5d719bf4dc9
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 *)
611 // adds '/' too
613 var
615 begin
619 begin
621 begin
623 continue;
626 begin
628 end
629 else
630 begin
639 var
641 begin
644 begin
646 begin
647 // avoid unnecessary string changes
654 var
657 begin
659 repeat
667 { TVolumeInfo }
669 var
672 begin
679 // òèïà ìóñîðîñáîðíèê: åñëè íàø ïîòîê áîëåå íèêåì íå þçàåòñÿ, òî óãðîáèòü åãî íàôèã
681 begin
685 begin
687 begin
690 begin
703 { TOwnedPartialStream }
706 begin
713 var
715 begin
718 begin
721 begin
729 { TSFSFileInfo }
731 begin
742 begin
748 { TSFSVolume }
750 begin
759 begin
763 var
767 begin
773 begin
775 // normalize name & path
782 begin
783 // split path and name
795 begin
802 begin
808 begin
810 else
811 begin
814 begin
817 begin
827 begin
832 begin
834 else
835 begin
842 var
845 begin
847 // normalize name, find split position
851 begin
864 { TSFSFileList }
866 var
868 begin
878 var
880 begin
885 // óáü¸ì çàïèñü, åñëè îíà âðåìåííàÿ, è â íåé íåò áîëüøå íè÷åãî îòêðûòîãî
892 begin
897 begin
904 var
906 begin
915 var
918 begin
923 begin
931 function SFSAddDataFileEx (dataFileName: TSFSString; ds: TStream; top, permanent: Integer): Integer;
932 // dataFileName ìîæåò èìåòü ïðåôèêñ òèïà "zip:" (ñì. âûøå: IsMyPrefix).
933 // ìîæåò âûêèíóòü èñêëþ÷åíèå!
934 // top:
935 // <0: äîáàâèòü â íà÷àëî ñïèñêà ïîèñêà.
936 // =0: íå ìåíÿòü.
937 // >0: äîáàâèòü â êîíåö ñïèñêà ïîèñêà.
938 // permanent:
939 // <0: ñîçäàòü "âðåìåííûé" òîì.
940 // =0: íå ìåíÿòü ôëàæîê ïîñòîÿíñòâà.
941 // >0: ñîçäàòü "ïîñòîÿííûé" òîì.
942 // åñëè ds <> nil, òî ñîçäà¸ò ñáîðíèê èç ïîòîêà. åñëè ñáîðíèê ñ èìåíåì
943 // dataFileName óæå çàðåãèñòðèðîâàí, òî ïàäàåò íàôèã.
944 // âîçâðàùàåò èíäåêñ â volumes.
945 // óìååò äåëàòü ðåêóðñèþ.
946 var
954 begin
957 begin
958 // ðåêóðñèâíîå îòêðûòèå.
959 // ðàçîáü¸ì dataFileName íà èìÿ ñáîðíèêà è îñòàòîê.
960 // pfx áóäåò èìåíåì ñáîðíèêà, dataFileName -- îñòàòêîì.
962 // ñíà÷àëà îòêðîåì ïåðâûé ñïèñîê...
964 // ...òåïåðü ïðîäîëæèì ñ îñòàòêîì.
965 // óçíàåì, êàêîå ôàéëî îòêðûâàòü.
966 // âûêîâûðÿåì ïåðâûé "::" ïðåôèêñ (ýòî áóäåò èìÿ ôàéëà).
969 // dataFileName õðàíèò îñòàòîê.
970 // èçâëå÷¸ì èìÿ ôàéëà:
972 // îòêðîåì ýòîò ôàéë
974 try
977 except
979 // óäàëèì íåèñïîëüçóåìûé âðåìåííûé òîì.
983 // óðà. îòêðûëè ôàéë. êèäàåì â âîçäóõ ÷åï÷èêè, ïðîäîëæàåì ðàçâëå÷åíèå.
985 try
988 except
992 exit;
995 // îáûêíîâåííîå íåðåêóðñèâíîå îòêðûòèå.
1000 begin
1007 exit;
1017 try
1019 begin
1024 try
1027 except
1033 except
1039 try
1041 begin
1044 end
1046 except
1064 var
1066 begin
1068 try
1072 except
1078 var
1080 begin
1081 try
1085 except
1092 var
1095 begin
1098 begin
1109 begin
1114 end
1120 var
1128 // ïðîâåðèì, åñòü ëè ôàëî fn ãäå-òî íà äèñêàõ.
1129 var
1132 begin
1139 begin
1145 try
1147 exit;
1148 except
1153 begin
1160 begin
1161 // ïðåôèêñîâàíûé ôàéë
1163 begin
1171 try
1174 except
1179 exit;
1181 //Inc(vi.fOpenedFilesCount);
1183 exit;
1186 // íåïðåôèêñîâàíûé ôàéë
1188 begin
1192 // èùåì ïî âñåì ïåðìàíåíòíûì ïðåôèêñàì
1195 begin
1198 begin
1200 begin
1203 begin
1204 try
1207 //Inc(vi.fOpenedFilesCount);
1208 except
1222 begin
1223 try
1225 except
1231 var
1234 begin
1238 try
1240 except
1241 exit;
1245 try
1248 except
1254 initialization
1257 //finalization
1258 //volumes.Free(); // it fails for some reason... Runtime 217 (^C hit). wtf?!
1259 //factories.Free(); // not need to be done actually...