From 863d06efa0eaf267d27a012edec2bd02e3077438 Mon Sep 17 00:00:00 2001 From: Erich Eckner Date: Mon, 6 Jul 2015 12:22:47 +0200 Subject: Prüfung, ob gewisse Befehle ihre Ausgaben nicht außerhalb vom aktuellen Wurzelverzeichnis machen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Make | Bin 1376992 -> 1672864 bytes Make.lpi | 20 +++-- Make.lpr | 189 +++++++++++++++---------------------------- Make.lps | 166 ++++++++++++++++++++----------------- tools.pas | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 445 insertions(+), 204 deletions(-) create mode 100644 tools.pas diff --git a/Make b/Make index 4bcd710..6c41c22 100755 Binary files a/Make and b/Make differ diff --git a/Make.lpi b/Make.lpi index 9c353cd..a98aa59 100644 --- a/Make.lpi +++ b/Make.lpi @@ -32,16 +32,25 @@ - + - + + + + + + + + + + @@ -51,6 +60,7 @@ + @@ -68,12 +78,6 @@ - - - - - - diff --git a/Make.lpr b/Make.lpr index 6db584d..7e7f042 100644 --- a/Make.lpr +++ b/Make.lpr @@ -8,7 +8,7 @@ uses {$ENDIF}{$ENDIF} Classes, SysUtils, CustApp { you can add units after this }, - RegExpr, Math, Process; + RegExpr, Math, tools; type @@ -24,7 +24,6 @@ type TAbhArt = (aaFinal,aaEinsZuEins,aaNZuN,aaIgnore); TDateienMitDaten = array of ^TDateiMitDatum; - tStringlistBArray = array[boolean] of tStringlist; { TAbhaengigkeit } @@ -97,50 +96,6 @@ begin inherited destroy; end; -function testeSummen(sumNam: string): tStringlistBArray; -var p: tProcess; - rb,i: longint; - s: string; - erg: tStringlist; - gut: boolean; -const leseHappen=65536; -begin - p:=tProcess.create(nil); - p.Executable:='/usr/bin/sha512sum'; - p.Parameters.add('-c'); - p.Parameters.add(sumNam); - p.Options:=p.Options + [poUsePipes]; - p.Execute; - rb:=0; - s:=''; - while p.Running do begin - if p.Output.NumBytesAvailable=0 then sleep(10) - else begin - setlength(s,rb+leseHappen); - rb:=rb+p.Output.Read(s[rb+1],leseHappen); - end; - end; - if p.Output.NumBytesAvailable>0 then begin - setlength(s,rb+leseHappen); - rb:=rb+p.Output.Read(s[rb+1],leseHappen); - end; - p.free; - setlength(s,rb); - erg:=tStringlist.create; - erg.text:=s; - s:=''; - for gut:=false to true do begin - result[gut]:=tStringlist.create; - rb:=0; - for i:=0 to erg.count-1 do - if not gut xor (rightStr(erg[i],4)=': OK') then begin - result[gut].add(leftStr(erg[i],pos(':',erg[i])-1)); - inc(rb); - end; - end; - erg.free; -end; - function liesZeile(var dat: textfile; out s: string): boolean; begin repeat @@ -177,50 +132,6 @@ begin FindClose(sr); end; -function anzCs(c: char; s: string): longint; -var i: longint; -begin - result:=0; - for i:=1 to length(s) do - if s[i]=c then - inc(result); -end; - -function notQuotedPos(was,worin: string): longint; -begin - result:=0; - repeat - if pos(was,copy(worin,result+1,length(worin)-result))=0 then begin - result:=0; - exit; - end; - result:=result+pos(was,copy(worin,result+1,length(worin)-result)); - if not odd(anzCs('"',copy(worin,1,result-1))) then - exit; - until false; -end; - -function unescapedpos(was,worin: string): integer; -var Ebene: longint; -begin - result:=0; - Ebene:=0; - while pos(was,copy(worin,result+1,length(worin)))>0 do begin - repeat - result:=result+1; - case worin[result] of - '{': inc(Ebene); - '}': dec(Ebene); - end; - until (result>=length(worin)) or ((copy(worin,result,length(was))=was) and (Ebene=0)); - if - ((result=1) or ((worin[result-1]<>'\') and (worin[result-1]<>was))) and - ((result=length(worin)) or (worin[result+1]<>was)) and - (copy(worin,result,length(was))=was) then exit; - end; - result:=0; -end; - function liesMakeFile(datNam: string; out Abh: TAbhaengigkeiten; out dats: TDateienMitDaten): boolean; var f: textfile; s,t: string; @@ -360,6 +271,8 @@ begin end; end; + for gefunden:=false to true do + gutschlecht[gefunden].free; result:=true; end; @@ -584,23 +497,24 @@ begin mgl[length(mgl)-1]^.ZieleFkt.Text:=mgl[i]^.ZieleFkt.Text; mgl[length(mgl)-1]^.Befehle.Text:=mgl[i]^.Befehle.Text; end; - for j:=0 to length(dats)-1 do if mgl[i]^.QuellenRE.Exec(dats[j]^.Name) then begin - schonda:=false; - for k:=0 to length(mgl[i]^.Erben[0]^.Quellen)-1 do - schonda:=schonda or (mgl[i]^.Erben[0]^.Quellen[k]=dats[j]); - if schonda then continue; - - SetLength(mgl[i]^.Erben[0]^.Quellen,length(mgl[i]^.Erben[0]^.Quellen)+1); - mgl[i]^.Erben[0]^.Quellen[length(mgl[i]^.Erben[0]^.Quellen)-1]:=dats[j]; - - for k:=0 to mgl[i]^.Befehle.Count-1 do begin - s:=mgl[i]^.Befehle[k]; - if Quellersetzung(s,dats[j]^.Name,inputfile) then begin - if k=0 then mgl[i]^.Erben[0]^.Befehle.Clear; - mgl[i]^.Erben[0]^.Befehle.Add(s); + for j:=0 to length(dats)-1 do + if mgl[i]^.QuellenRE.Exec(dats[j]^.Name) then begin + schonda:=false; + for k:=0 to length(mgl[i]^.Erben[0]^.Quellen)-1 do + schonda:=schonda or (mgl[i]^.Erben[0]^.Quellen[k]=dats[j]); + if schonda then continue; + + SetLength(mgl[i]^.Erben[0]^.Quellen,length(mgl[i]^.Erben[0]^.Quellen)+1); + mgl[i]^.Erben[0]^.Quellen[length(mgl[i]^.Erben[0]^.Quellen)-1]:=dats[j]; + + for k:=0 to mgl[i]^.Befehle.Count-1 do begin + s:=mgl[i]^.Befehle[k]; + if Quellersetzung(s,dats[j]^.Name,inputfile) then begin + if k=0 then mgl[i]^.Erben[0]^.Befehle.Clear; + mgl[i]^.Erben[0]^.Befehle.Add(s); + end; end; end; - end; end; aaEinsZuEins: begin // jede Quelle muss einzeln behandelt werden for j:=0 to length(dats)-1 do @@ -609,7 +523,9 @@ begin for k:=0 to length(mgl[i]^.Erben)-1 do for l:=0 to length(mgl[i]^.Erben[k]^.Quellen)-1 do schonda:=schonda or (mgl[i]^.Erben[k]^.Quellen[l]=dats[j]); + if schonda then continue; + SetLength(mgl,length(mgl)+1); getmem(mgl[length(mgl)-1],sizeof(TAbhaengigkeit)); fillchar(mgl[length(mgl)-1]^,sizeof(TAbhaengigkeiten),0); @@ -619,7 +535,8 @@ begin mgl[length(mgl)-1]^.AbhArt:=aaFinal; SetLength(mgl[length(mgl)-1]^.Quellen,1); mgl[length(mgl)-1]^.Quellen[0]:=dats[j]; - findeZiele(mgl[length(mgl)-1]^.Ziele,mgl[i]^.ZieleFkt,dats[j]^.name,inputfile,dats); + mgl[length(mgl)-1]^.ZieleFkt:=mgl[i]^.ZieleFkt; +// findeZiele(mgl[length(mgl)-1]^.Ziele,mgl[i]^.ZieleFkt,dats[j]^.name,inputfile,dats); // sollte unten geschehen mgl[length(mgl)-1]^.Befehle.Clear; for k:=0 to mgl[i]^.Befehle.Count-1 do begin s:=mgl[i]^.Befehle[k]; @@ -627,32 +544,32 @@ begin mgl[length(mgl)-1]^.Befehle.Add(s); end; if mgl[length(mgl)-1]^.Befehle.Count=0 then begin - writeln('Keine Befehle für diese Abhängigkeit auszuführen!'); + writeln('Fehler: Keine Befehle für diese Abhängigkeit auszuführen!'); halt; end; mgl[length(mgl)-1]^.Prioritaet:=mgl[i]^.Prioritaet; end; end; - aaFinal: if length(mgl[i]^.Erben)=0 then begin // Quellen stehen schon fest, noch nicht auszuführen - if length(mgl[i]^.Quellen)=0 then begin - inc(i); - continue; - end; - quNeu:=mgl[i]^.Quellen[0]^.Datum; - for j:=1 to length(mgl[i]^.Quellen)-1 do - quNeu:=max(quNeu,mgl[i]^.Quellen[j]^.Datum); + aaFinal: if (length(mgl[i]^.Erben)=0) and + (length(mgl[i]^.Quellen)<>0) then begin // Quellen stehen schon fest, noch nicht auszuführen if length(mgl[i]^.Ziele)=0 then begin for j:=0 to length(mgl[i]^.Quellen)-1 do findeMehrZiele(mgl[i]^.Ziele,mgl[i]^.ZieleFkt,mgl[i]^.Quellen[j]^.Name,inputfile,dats); - if length(mgl[i]^.Ziele)=0 then begin + if length(mgl[i]^.Ziele)=0 then begin // immer noch keine Ziele + writeln('Warnung: Keine Ziele für diese Abhängigkeit!'); mgl[i]^.AbhArt:=aaIgnore; continue; end; end; + quNeu:=mgl[i]^.Quellen[0]^.Datum; + for j:=1 to length(mgl[i]^.Quellen)-1 do // neueste Quelle ermitteln + quNeu:=max(quNeu,mgl[i]^.Quellen[j]^.Datum); ziAlt:=mgl[i]^.Ziele[0]^.Datum; - for j:=1 to length(mgl[i]^.Ziele)-1 do + for j:=1 to length(mgl[i]^.Ziele)-1 do // ältestes Ziel ermitteln ziAlt:=min(ziAlt,mgl[i]^.Ziele[j]^.Datum); + if ziAlt ',mgl[i]^.Befehle.text); SetLength(zuTun,length(zuTun)+1); getmem(zuTun[length(zuTun)-1],sizeof(TAbhaengigkeit)); fillchar(zuTun[length(zuTun)-1]^,sizeof(TAbhaengigkeit),0); @@ -671,11 +588,13 @@ begin until not neues; end; -procedure tueWasZuTunIst(alles,zuTun: TAbhaengigkeiten; nurAnzeigen, allesNeu: boolean; Ausgabedatei,Summendatei: string); +procedure tueWasZuTunIst(alles,zuTun: TAbhaengigkeiten; var dats: TDateienMitDaten; nurAnzeigen, allesNeu, unsicher: boolean; Ausgabedatei,Summendatei: string); var Prior,i,j: integer; Ausg: Textfile; - Befehle,geaenderteDateien,alteDateien: TStringlist; - ms: boolean; + Befehle,geaenderteDateien, + alteDateien,sumDateien: TStringlist; + ms,gefunden: boolean; + lokTest: tRegExpr; begin Befehle:=TStringlist.create; Prior:=0; @@ -684,6 +603,19 @@ begin Prior:=max(Prior,zuTun[i]^.Prioritaet); if ms then begin geaenderteDateien:=TStringlist.create; + sumDateien:=dateienMitGueltigerSumme(Summendatei); + for i:=0 to length(dats)-1 do begin + gefunden:=(dats[i]^.name=Summendatei) or (dats[i]^.name=Ausgabedatei); + for j:=0 to sumDateien.count-1 do + if sumDateien[j]=dats[i]^.name then begin + gefunden:=true; + sumDateien.delete(j); + break; + end; + if not gefunden then + geaenderteDateien.add(dats[i]^.name); + end; + sumDateien.free; if allesNeu then for i:=0 to length(alles)-1 do begin for j:=0 to length(alles[i]^.Ziele)-1 do @@ -705,6 +637,16 @@ begin Befehle.Add(zuTun[i]^.Befehle[j]); dec(Prior); end; + if not unsicher then begin + lokTest:=tRegExpr.create; + if extractfilepath(Ausgabedatei)=extractfilepath(Summendatei) then + lokTest.Expression:='^'+extractfilepath(Ausgabedatei)+'/' + else + lokTest.Expression:='^('+extractfilepath(Ausgabedatei)+'|'+extractfilepath(Summendatei)+')/'; + for i:=0 to Befehle.count-1 do + testeObBefehlLokal(Befehle[i],extractfiledir(Ausgabedatei),lokTest); + lokTest.free; + end; if ms then begin for i:=geaenderteDateien.count-1 downto 0 do begin if geaenderteDateien[i]='.uralt.' then begin @@ -739,7 +681,6 @@ begin if length(zuTun)=0 then Befehle.Add('echo "Es gibt hier nichts zu tun!"'); - Befehle.Add('sleep 2'); if nurAnzeigen then begin writeln('Befehle:'); for i:=0 to Befehle.Count-1 do @@ -765,7 +706,7 @@ var mglAbhaengigkeiten,zutunAbhaengigkeiten: TAbhaengigkeiten; Dateien: TDateienMitDaten; begin - ErrorMsg:=CheckOptions('A:HWD:P:a','Ausgabe: Hilfe Watte Datei: Prüfsummen: alleSummenErneuern'); + ErrorMsg:=CheckOptions('A:HWD:P:au','Ausgabe: Hilfe Watte Datei: Prüfsummen: alleSummenErneuern unsicher'); if ErrorMsg<>'' then begin ShowException(Exception.Create(ErrorMsg+#10'Hilfe: '+Exename+' -H/--Hilfe')); Terminate; @@ -819,7 +760,7 @@ begin writeln('Regeln: '+inttostr(length(mglAbhaengigkeiten))+', Dateien: '+inttostr(length(Dateien))); findeWasZuTunIst(mglAbhaengigkeiten,zuTunAbhaengigkeiten,Dateien,inputfile,now); writeln('anzuwendende Regeln: '+inttostr(length(zuTunAbhaengigkeiten))); - tueWasZuTunIst(mglAbhaengigkeiten,zuTunAbhaengigkeiten,HasOption('W','Watte'),HasOption('a','alleSummenErneuern'),GetOptionValue('A','Ausgabe'),pruefsummenfile); + tueWasZuTunIst(mglAbhaengigkeiten,zuTunAbhaengigkeiten,Dateien,HasOption('W','Watte'),HasOption('a','alleSummenErneuern'),HasOption('u','unsicher'),GetOptionValue('A','Ausgabe'),pruefsummenfile); Terminate; end; @@ -833,7 +774,7 @@ end; procedure TMake.WriteHelp; begin writeln('Verwendung:'); - writeln(' ',ExeName,' -A/--Ausgabe $Ausgabedatei -H/--Hilfe -W/--Watte -D/--Datei $Machdatei -P/--Prüfsummen $Prüfsummendatei -a/--alleSummenErneuern'); + writeln(' ',ExeName,' -A/--Ausgabe $Ausgabedatei -H/--Hilfe -W/--Watte -D/--Datei $Machdatei -P/--Prüfsummen $Prüfsummendatei -a/--alleSummenErneuern -u/--unsicher'); end; var diff --git a/Make.lps b/Make.lps index 78994fb..5d4fb07 100644 --- a/Make.lps +++ b/Make.lps @@ -3,163 +3,185 @@ - + - - - - - - - - + + + + - - - - + + + + + + + + + + + + + - - - + - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - diff --git a/tools.pas b/tools.pas new file mode 100644 index 0000000..0a6feb1 --- /dev/null +++ b/tools.pas @@ -0,0 +1,274 @@ +unit tools; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Process, lowlevelunit, regExpr; + +type + tStringlistBArray = array[boolean] of tStringlist; + tSummenDatei = record + name: string; + inhalt: tStringlistBArray; + end; + +function anzCs(c: char; s: string): longint; +function notQuotedPos(was,worin: string): longint; +function unescapedpos(was,worin: string): integer; +procedure testeObBefehlLokal(bef, ordner: string; lokTest: tRegExpr); +function extrahiereAlleDateien(woraus: string): tMyStringList; + +// Routinen für sha512-Prüfsummen + +function testeSummen(sumNam: string): tStringlistBArray; +function dateienMitGueltigerSumme(sumNam: string): tStringList; + +implementation + +function anzCs(c: char; s: string): longint; +var i: longint; +begin + result:=0; + for i:=1 to length(s) do + if s[i]=c then + inc(result); +end; + +function notQuotedPos(was,worin: string): longint; +begin + result:=0; + repeat + if pos(was,copy(worin,result+1,length(worin)-result))=0 then begin + result:=0; + exit; + end; + result:=result+pos(was,copy(worin,result+1,length(worin)-result)); + if not odd(anzCs('"',copy(worin,1,result-1))) then + exit; + until false; +end; + +function unescapedpos(was,worin: string): integer; +var Ebene: longint; +begin + result:=0; + Ebene:=0; + while pos(was,copy(worin,result+1,length(worin)))>0 do begin + repeat + result:=result+1; + case worin[result] of + '{': inc(Ebene); + '}': dec(Ebene); + end; + until (result>=length(worin)) or ((copy(worin,result,length(was))=was) and (Ebene=0)); + if + ((result=1) or ((worin[result-1]<>'\') and (worin[result-1]<>was))) and + ((result=length(worin)) or (worin[result+1]<>was)) and + (copy(worin,result,length(was))=was) then exit; + end; + result:=0; +end; + +procedure testeObBefehlLokal(bef, ordner: string; lokTest: tRegExpr); +var + exe,args,regex,oBef,s: string; + dateien,sl,relZeil: tMyStringlist; + i,j: longint; + re: tRegExpr; +begin + oBef:=bef; + + while notQuotedPos(';',bef)>0 do begin + testeObBefehlLokal(trim(leftStr(bef,notQuotedPos(';',bef))),ordner,lokTest); + delete(bef,1,notQuotedPos(';',bef)); + bef:=trim(bef); + end; + + args:=''; + repeat + exe:=leftstr(bef,notQuotedPos(' ',bef)-1); + delete(bef,1,length(exe)); + if exe='cat' then begin + args:=args+' '+trim(leftStr(bef,notQuotedPos('|',bef)-1)); + delete(bef,1,notQuotedPos('|',bef)); + end; + bef:=trim(bef); + until (notQuotedPos('=',bef)=0) and (exe<>'do') and (exe<>'cat'); + + delete(args,1,1); + exe:=extractfilename(exe); + + if exe='gnuplot' then begin + // set output "~/Dokumente/Erich_Masterarbeit/Bilder/gnuplot/Energiescan.tex" + regex:='^ *set +output +'; + re:=tRegExpr.create; + re.Expression:='"[^"]*/[^"]*"'; + end + else if exe='epost' then begin + // Datei: + regex:='^ *(Datei|Legende): *'; + re:=tRegExpr.create; + re.Expression:='[^ :]*/[^ ]*'; + end + else if exe='math' then begin + // das wird vmtl. schwer zu überprüfen, außer man nimmt Muster, + // die generisch auf Pfade passen, aber dann erwischt man auch den Input mit ... + regex:='^([^"]*"[^"]*")*[^"]*"([^"]*/)+[^"]*"'; + re:=tRegExpr.create; + re.Expression:='"[^"]*/[^"]*"'; + end + else exit; + + // folgende Executables sind unkritisch, da der Name des Outputs i.d.R. direkt + // vom Namen des Inputs abhängt bzw. per Kommandozeilenparameter übergeben + // wird (und nicht in einer Datei steht): + // + // 'convert' + // 'epstopdf' + // 'latexmk' + // 'mpost' + // 'pdflatex' + + dateien:=extrahiereAlleDateien(args+' '+bef); + if dateien.count = 0 then + writeln('*** Warnung: Hier ist ein Befehl ohne offensichtliche input-Dateien! ('''+oBef+''')!'); + + sl:=tMyStringlist.create; + relZeil:=tMyStringlist.create; + for i:=0 to dateien.count-1 do begin + sl.loadFromFile(dateien[i]); + sl.grep(regex); + relZeil.addStrings(sl); + end; + sl.free; + dateien.free; + + for i:=0 to relZeil.count-1 do begin + re.InputString:=relZeil[i]; + if re.SubExprMatchCount=0 then + writeln('*** Warnung: Hier ist eine Zeile in der Optionsdatei, die keine passende Inputdatei benennt, es aber sollte! ('''+relZeil[i]+''')!'); + for j:=0 to re.SubExprMatchCount-1 do begin + s:=trim(re.Match[j]); + if (leftStr(s,1)='"') and (rightStr(s,1)='"') then begin + delete(s,1,1); + delete(s,length(s),1); + end; + if not lokTest.Exec(s) then begin + writeln('*** FEHLER: '''+relZeil[i]+''' in Befehl '''+oBef+''' hat Lokalitätstest nicht bestanden! ('+lokTest.Expression+')'); + halt(1); + end; + end; + end; + re.free; + relZeil.free; +end; + +function extrahiereAlleDateien(woraus: string): tMyStringList; +var + s: string; +begin + result:=tMyStringlist.create; + woraus:=woraus+' '; + while notQuotedPos(' ',woraus)>0 do begin + s:=leftStr(woraus,notQuotedPos(' ',woraus)); + delete(woraus,1,length(s)); + s:=trim(s); + if fileexists(s) then + result.add(s); + end; +end; + +// Routinen für sha512-Prüfsummen + +var + Summenvorrat: array of tSummenDatei; + +function testeSummen(sumNam: string): tStringlistBArray; +var p: tProcess; + rb,i: longint; + s: string; + erg: tStringlist; + gut: boolean; +const leseHappen=65536; +begin + for i:=0 to length(Summenvorrat)-1 do + if Summenvorrat[i].name=sumNam then begin + for gut:=false to true do begin + result[gut]:=tStringlist.create; + result[gut].text:=Summenvorrat[i].inhalt[gut].text; + end; + exit; + end; + + p:=tProcess.create(nil); + p.Executable:='/usr/bin/sha512sum'; + p.Parameters.add('-c'); + p.Parameters.add(sumNam); + p.Options:=p.Options + [poUsePipes]; + p.Execute; + rb:=0; + s:=''; + while p.Running do begin + if p.Output.NumBytesAvailable=0 then sleep(10) + else begin + setlength(s,rb+leseHappen); + rb:=rb+p.Output.Read(s[rb+1],leseHappen); + end; + end; + if p.Output.NumBytesAvailable>0 then begin + setlength(s,rb+leseHappen); + rb:=rb+p.Output.Read(s[rb+1],leseHappen); + end; + p.free; + setlength(s,rb); + erg:=tStringlist.create; + erg.text:=s; + s:=''; + for gut:=false to true do begin + result[gut]:=tStringlist.create; + rb:=0; + for i:=0 to erg.count-1 do + if not gut xor (rightStr(erg[i],4)=': OK') then begin + result[gut].add(leftStr(erg[i],pos(':',erg[i])-1)); + inc(rb); + end; + end; + erg.free; + + setlength(Summenvorrat,length(Summenvorrat)+1); + with Summenvorrat[length(Summenvorrat)-1] do begin + name:=sumNam; + for gut:=false to true do begin + inhalt[gut]:=tStringlist.create; + inhalt[gut].text:=result[gut].text; + end; + end; +end; + +function dateienMitGueltigerSumme(sumNam: string): tStringList; +var + sums: tStringlistBArray; +begin + sums:=testeSummen(sumNam); + result:=sums[true]; + sums[false].free; +end; + +var + i: longint; + +initialization + setlength(Summenvorrat,0); + +finalization + for i:=0 to length(Summenvorrat)-1 do + with Summenvorrat[i] do begin + name:=''; + inhalt[false].free; + inhalt[true].free; + end; + setlength(Summenvorrat,0); +end. + -- cgit v1.2.3-54-g00ecf